improve terminology consistency in Membership

This commit is contained in:
Sergei Tikhomirov 2024-09-24 14:50:14 +02:00
parent 4b3f608bee
commit ad92298a0c
No known key found for this signature in database
GPG Key ID: 6A1F8ED9D6538027
3 changed files with 253 additions and 238 deletions

View File

@ -11,98 +11,100 @@ error InvalidRateLimit();
// It's not possible to acquire the rate limit due to exceeding the expected limits
// even after attempting to erase expired memberships
error ExceedAvailableMaxRateLimitPerEpoch();
error ExceededMaxTotalRateLimit();
// This membership is not in grace period yet
// This membership is not in grace period yet // FIXME: yet or also already?
error NotInGracePeriod(uint256 idCommitment);
// The sender is not the holder of the membership
error NotHolder(uint256 idCommitment);
error AttemptedExtensionByNonHolder(uint256 idCommitment);
// This membership cannot be erased (either it is not expired or not in grace period and/or not the owner)
// This membership cannot be erased (either it is not expired or not in grace period and/or not the owner) // FIXME:
// separate into two errors?
error CantEraseMembership(uint256 idCommitment);
abstract contract MembershipUpgradeable is Initializable {
using SafeERC20 for IERC20;
/// @notice Address of the Price Calculator used to calculate the price of a new membership
IPriceCalculator public priceCalculator;
IPriceCalculator public priceCalculator; // FIXME: naming: price vs deposit?
/// @notice Maximum total rate limit of all memberships in the tree
/// @notice Maximum total rate limit of all memberships in the membership set (messages per epoch)
uint32 public maxTotalRateLimit;
/// @notice Maximum rate limit of one membership
uint32 public maxRateLimitPerMembership;
uint32 public maxMembershipRateLimit;
/// @notice Minimum rate limit of one membership
uint32 public minRateLimitPerMembership;
uint32 public minMembershipRateLimit;
/// @notice Membership billing period
/// @notice Membership expiration term (T in the spec)
uint32 public expirationTerm;
/// @notice Membership grace period
uint32 public gracePeriod;
/// @notice Membership grace period (G in the spec)
uint32 public gracePeriodDuration;
/// @notice balances available to withdraw
/// @notice deposit balances available to withdraw // FIXME: are balances unavailable for withdrawal stored
/// elsewhere?
mapping(address holder => mapping(address token => uint256 balance)) public balancesToWithdraw;
/// @notice Total rate limit of all memberships in the tree
uint256 public totalRateLimitPerEpoch;
/// @notice Total rate limit of all memberships in the membership set (messages per epoch)
uint256 public totalRateLimit;
/// @notice List of registered memberships
mapping(uint256 idCommitment => MembershipInfo member) public memberships;
mapping(uint256 idCommitment => MembershipInfo membership) public memberships;
/// @notice The index in the membership set for the next membership to be registered
uint32 public nextFreeIndex;
/// @notice track available indices that are available due to expired memberships being removed
uint32[] public availableExpiredIndices;
/// @notice indices of expired memberships (can be erased)
uint32[] public availableExpiredMembershipsIndices;
struct MembershipInfo {
/// @notice amount of the token used to acquire this membership
uint256 amount;
/// @notice amount of the token used to make the deposit to register this membership
uint256 depositAmount;
/// @notice timestamp of when the grace period starts for this membership
uint256 gracePeriodStartDate;
uint256 gracePeriodStartTimestamp;
/// @notice duration of the grace period
uint32 gracePeriod;
uint32 gracePeriodDuration;
/// @notice the membership rate limit
uint32 rateLimit;
/// @notice the index of the member in the membership set
/// @notice the index of the membership in the membership set
uint32 index;
/// @notice address of the owner of this membership
/// @notice address of the holder of this membership
address holder;
/// @notice token used to acquire this membership
/// @notice token used to make the deposit to register this membership
address token;
}
/// @notice Emitted when a membership is erased due to having exceeded the grace period or the owner having chosen
/// to not extend it
/// @param idCommitment the idCommitment of the member
/// to not extend it // FIXME: expired or erased?
/// @param idCommitment the idCommitment of the membership
/// @param membershipRateLimit the rate limit of this membership
/// @param index the index of the membership in the merkle tree
event MemberExpired(uint256 idCommitment, uint32 membershipRateLimit, uint32 index);
/// @param index the index of the membership in the membership set
event MembershipExpired(uint256 idCommitment, uint32 membershipRateLimit, uint32 index);
/// @notice Emitted when a membership in grace period is extended
/// @param idCommitment the idCommitment of the member
/// @notice Emitted when a membership in its grace period is extended
/// @param idCommitment the idCommitment of the membership
/// @param membershipRateLimit the rate limit of this membership
/// @param index the index of the membership in the merkle tree
/// @param newExpirationDate the new expiration date of this membership
event MemberExtended(uint256 idCommitment, uint32 membershipRateLimit, uint32 index, uint256 newExpirationDate);
/// @param index the index of the membership in the membership set
/// @param newExpirationTime the new expiration timestamp of this membership
event MembershipExtended(uint256 idCommitment, uint32 membershipRateLimit, uint32 index, uint256 newExpirationTime);
/// @dev contract initializer
/// @param _priceCalculator Address of an instance of IPriceCalculator
/// @param _maxTotalRateLimit Maximum total rate limit of all memberships in the tree
/// @param _minRateLimitPerMembership Minimum rate limit of one membership
/// @param _maxRateLimitPerMembership Maximum rate limit of one membership
/// @param _expirationTerm Membership expiration term
/// @param _gracePeriod Membership grace period
/// @param _maxTotalRateLimit Maximum total rate limit of all memberships in the membership set
/// @param _minMembershipRateLimit Minimum rate limit of each membership
/// @param _maxMembershipRateLimit Maximum rate limit of each membership
/// @param _expirationTerm Expiration term of each membership
/// @param _gracePeriodDuration Grace period duration for each membership
function __MembershipUpgradeable_init(
address _priceCalculator,
uint32 _maxTotalRateLimit,
uint32 _minRateLimitPerMembership,
uint32 _maxRateLimitPerMembership,
uint32 _minMembershipRateLimit,
uint32 _maxMembershipRateLimit,
uint32 _expirationTerm,
uint32 _gracePeriod
uint32 _gracePeriodDuration
)
internal
onlyInitializing
@ -110,61 +112,61 @@ abstract contract MembershipUpgradeable is Initializable {
__MembershipUpgradeable_init_unchained(
_priceCalculator,
_maxTotalRateLimit,
_minRateLimitPerMembership,
_maxRateLimitPerMembership,
_minMembershipRateLimit,
_maxMembershipRateLimit,
_expirationTerm,
_gracePeriod
_gracePeriodDuration
);
}
function __MembershipUpgradeable_init_unchained(
address _priceCalculator,
uint32 _maxTotalRateLimit,
uint32 _minRateLimitPerMembership,
uint32 _maxRateLimitPerMembership,
uint32 _minMembershipRateLimit,
uint32 _maxMembershipRateLimit,
uint32 _expirationTerm,
uint32 _gracePeriod
uint32 _gracePeriodDuration
)
internal
onlyInitializing
{
require(_maxTotalRateLimit >= maxRateLimitPerMembership);
require(_maxRateLimitPerMembership > minRateLimitPerMembership);
require(_minRateLimitPerMembership > 0);
require(_expirationTerm > 0);
require(_maxTotalRateLimit >= maxMembershipRateLimit);
require(_maxMembershipRateLimit > minMembershipRateLimit); // FIXME: > or >=?
require(_minMembershipRateLimit > 0);
require(_expirationTerm > 0); // FIXME: also _gracePeriodDuration > 0?
priceCalculator = IPriceCalculator(_priceCalculator);
maxTotalRateLimit = _maxTotalRateLimit;
maxRateLimitPerMembership = _maxRateLimitPerMembership;
minRateLimitPerMembership = _minRateLimitPerMembership;
maxMembershipRateLimit = _maxMembershipRateLimit;
minMembershipRateLimit = _minMembershipRateLimit;
expirationTerm = _expirationTerm;
gracePeriod = _gracePeriod;
gracePeriodDuration = _gracePeriodDuration;
}
/// @notice Checks if a membership rate limit is valid. This does not take into account whether we the total
/// memberships have reached already the `maxTotalRateLimit`
/// @notice Checks if a membership rate limit is valid. This does not take into account whether the total
/// memberships have reached already the `maxTotalRateLimit` // FIXME: clarify
/// @param membershipRateLimit The membership rate limit
/// @return true if the membership rate limit is valid, false otherwise
function isValidMembershipRateLimit(uint32 membershipRateLimit) external view returns (bool) {
return membershipRateLimit >= minRateLimitPerMembership && membershipRateLimit <= maxRateLimitPerMembership;
return membershipRateLimit >= minMembershipRateLimit && membershipRateLimit <= maxMembershipRateLimit;
}
/// @dev acquire a membership and trasnfer the fees to the contract
/// @dev acquire a membership and trasnfer the fees to the contract // FIXME: fees == deposit?
/// @param _sender address of the owner of the new membership
/// @param _idCommitment the idcommitment of the new membership
/// @param _idCommitment the idCommitment of the new membership
/// @param _rateLimit the membership rate limit
/// @return index the index in the merkle tree
/// @return reuseIndex indicates whether a new leaf is being used or if using an existing leaf in the merkle tree
/// @return index the index in the membership set
/// @return indexReused indicates whether using a new Merkle tree leaf or an existing one
function _acquireMembership(
address _sender,
uint256 _idCommitment,
uint32 _rateLimit
)
internal
returns (uint32 index, bool reuseIndex)
returns (uint32 index, bool indexReused)
{
(address token, uint256 amount) = priceCalculator.calculate(_rateLimit);
(index, reuseIndex) = _setupMembershipDetails(_sender, _idCommitment, _rateLimit, token, amount);
(index, indexReused) = _setupMembershipDetails(_sender, _idCommitment, _rateLimit, token, amount);
_transferFees(_sender, token, amount);
}
@ -173,147 +175,159 @@ abstract contract MembershipUpgradeable is Initializable {
}
/// @dev Setup a new membership. If there are not enough remaining rate limit to acquire
/// a new membership, it will attempt to erase existing memberships and reuse one of the
/// slots helds by the membership
/// @param _sender holder of the membership. Generally `msg.sender`
/// @param _idCommitment IDCommitment
/// a new membership, it will attempt to erase existing expired memberships
/// and reuse one of their slots
/// @param _sender holder of the membership. Generally `msg.sender` // FIXME: rename to holder?
/// @param _idCommitment idCommitment
/// @param _rateLimit membership rate limit
/// @param _token Address of the token used to acquire the membership
/// @param _amount Amount of the token used to acquire the membership
/// @return index membership index on the merkle tree
/// @return reuseIndex indicates whether the index returned was a reused slot on the tree or not
/// @param _depositAmount Amount of the tokens used to acquire the membership
/// @return index membership index in the membership set
/// @return indexReused indicates whether the index returned was a reused slot on the tree or not
function _setupMembershipDetails(
address _sender,
uint256 _idCommitment,
uint32 _rateLimit,
address _token,
uint256 _amount
uint256 _depositAmount
)
internal
returns (uint32 index, bool reuseIndex)
returns (uint32 index, bool indexReused)
{
if (_rateLimit < minRateLimitPerMembership || _rateLimit > maxRateLimitPerMembership) {
if (_rateLimit < minMembershipRateLimit || _rateLimit > maxMembershipRateLimit) {
revert InvalidRateLimit();
}
// Determine if we exceed the total rate limit
totalRateLimitPerEpoch += _rateLimit;
if (totalRateLimitPerEpoch > maxTotalRateLimit) {
revert ExceedAvailableMaxRateLimitPerEpoch(); // List is empty or can't
totalRateLimit += _rateLimit;
if (totalRateLimit > maxTotalRateLimit) {
revert ExceededMaxTotalRateLimit();
}
// Reuse available slots from previously removed expired memberships
(index, reuseIndex) = _nextIndex();
// Reuse available slots from previously removed (FIXME: clarify "removed") expired memberships
(index, indexReused) = _getFreeIndex();
memberships[_idCommitment] = MembershipInfo({
holder: _sender,
gracePeriodStartDate: block.timestamp + uint256(expirationTerm),
gracePeriod: gracePeriod,
gracePeriodStartTimestamp: block.timestamp + uint256(expirationTerm),
gracePeriodDuration: gracePeriodDuration,
token: _token,
amount: _amount,
depositAmount: _depositAmount,
rateLimit: _rateLimit,
index: index
});
}
/// @dev reuse available slots from previously removed expired memberships
/// @return index index to use
/// @return reuseIndex indicates whether it is reusing an existing index, or using a new one
function _nextIndex() internal returns (uint32 index, bool reuseIndex) {
// Reuse available slots from previously removed expired memberships
uint256 arrLen = availableExpiredIndices.length;
/// @dev Get a free index (possibly from reusing a slot of an expired membership)
/// @return index index to be used for another membership registration
/// @return indexReused indicates whether index comes form reusing a slot of an expired membership
function _getFreeIndex() internal returns (uint32 index, bool indexReused) {
// Reuse available slots from previously removed (FIXME: clarify "removed") expired memberships
uint256 arrLen = availableExpiredMembershipsIndices.length;
if (arrLen != 0) {
index = availableExpiredIndices[arrLen - 1];
availableExpiredIndices.pop();
reuseIndex = true;
index = availableExpiredMembershipsIndices[arrLen - 1];
availableExpiredMembershipsIndices.pop();
indexReused = true;
} else {
index = nextFreeIndex;
}
}
/// @dev Extend a membership expiration date. Membership must be on grace period
/// @dev Extend the expiration date of a grace-period membership
/// @param _sender the address of the holder of the membership
/// @param _idCommitment the idCommitment of the membership
function _extendMembership(address _sender, uint256 _idCommitment) public {
MembershipInfo storage mdetails = memberships[_idCommitment];
MembershipInfo storage membership = memberships[_idCommitment];
if (!_isGracePeriod(mdetails.gracePeriodStartDate, mdetails.gracePeriod)) {
if (!_isInGracePeriodNow(membership.gracePeriodStartTimestamp, membership.gracePeriodDuration)) {
revert NotInGracePeriod(_idCommitment);
}
if (_sender != mdetails.holder) revert NotHolder(_idCommitment);
if (_sender != membership.holder) revert AttemptedExtensionByNonHolder(_idCommitment); // FIXME: turn into a
// modifier?
// FIXME: see spec: should extension depend on the current block.timestamp?
uint256 newGracePeriodStartTimestamp = block.timestamp + uint256(expirationTerm);
uint256 gracePeriodStartDate = block.timestamp + uint256(expirationTerm);
membership.gracePeriodStartTimestamp = newGracePeriodStartTimestamp;
membership.gracePeriodDuration = gracePeriodDuration; // FIXME: redundant: just assigns old value
mdetails.gracePeriodStartDate = gracePeriodStartDate;
mdetails.gracePeriod = gracePeriod;
emit MemberExtended(_idCommitment, mdetails.rateLimit, mdetails.index, gracePeriodStartDate);
emit MembershipExtended(
_idCommitment, membership.rateLimit, membership.index, membership.gracePeriodStartTimestamp
);
}
/// @dev Determine whether a timestamp is considered to be expired or not after exceeding the grace period
/// @param _gracePeriodStartDate timestamp in which the grace period starts
/// @param _gracePeriod duration of the grace period
function _isExpired(uint256 _gracePeriodStartDate, uint32 _gracePeriod) internal view returns (bool) {
return block.timestamp > _gracePeriodStartDate + uint256(_gracePeriod);
/// @dev Determine whether a grace period has passed (the membership is expired)
/// @param _gracePeriodStartTimestamp timestamp in which the grace period starts
/// @param _gracePeriodDuration duration of the grace period
function _isExpired(uint256 _gracePeriodStartTimestamp, uint32 _gracePeriodDuration) internal view returns (bool) {
return block.timestamp > _gracePeriodStartTimestamp + uint256(_gracePeriodDuration);
}
/// @notice Determine if a membership is expired (has exceeded the grace period)
/// @notice Determine if a membership is expired
/// @param _idCommitment the idCommitment of the membership
function isExpired(uint256 _idCommitment) public view returns (bool) {
MembershipInfo memory m = memberships[_idCommitment];
return _isExpired(m.gracePeriodStartDate, m.gracePeriod);
MembershipInfo memory membership = memberships[_idCommitment];
return _isExpired(membership.gracePeriodStartTimestamp, membership.gracePeriodDuration);
}
/// @notice Returns the timestamp on which a membership can be considered expired
/// @param _idCommitment the idCommitment of the membership
function expirationDate(uint256 _idCommitment) public view returns (uint256) {
MembershipInfo memory m = memberships[_idCommitment];
return m.gracePeriodStartDate + uint256(m.gracePeriod) + 1;
function membershipExpirationTimestamp(uint256 _idCommitment) public view returns (uint256) {
MembershipInfo memory membership = memberships[_idCommitment];
return membership.gracePeriodStartTimestamp + uint256(membership.gracePeriodDuration) + 1;
}
/// @dev Determine whether a timestamp is considered to be in grace period or not
/// @param _gracePeriodStartDate timestamp in which the grace period starts
/// @param _gracePeriod duration of the grace period
function _isGracePeriod(uint256 _gracePeriodStartDate, uint32 _gracePeriod) internal view returns (bool) {
/// @dev Determine whether the current timestamp is in a given grace period
/// @param _gracePeriodStartTimestamp timestamp in which the grace period starts
/// @param _gracePeriodDuration duration of the grace period
function _isInGracePeriodNow(
uint256 _gracePeriodStartTimestamp,
uint32 _gracePeriodDuration
)
internal
view
returns (bool)
{
uint256 blockTimestamp = block.timestamp;
return
blockTimestamp >= _gracePeriodStartDate && blockTimestamp <= _gracePeriodStartDate + uint256(_gracePeriod);
return blockTimestamp >= _gracePeriodStartTimestamp
&& blockTimestamp <= _gracePeriodStartTimestamp + uint256(_gracePeriodDuration);
}
/// @notice Determine if a membership is in grace period
/// @notice Determine if a membership is in grace period now
/// @param _idCommitment the idCommitment of the membership
function isGracePeriod(uint256 _idCommitment) public view returns (bool) {
MembershipInfo memory m = memberships[_idCommitment];
return _isGracePeriod(m.gracePeriodStartDate, m.gracePeriod);
function isInGracePeriodNow(uint256 _idCommitment) public view returns (bool) {
MembershipInfo memory membership = memberships[_idCommitment];
return _isInGracePeriodNow(membership.gracePeriodStartTimestamp, membership.gracePeriodDuration);
}
/// @dev Erase expired memberships or owned memberships in grace period.
/// @dev Erase expired memberships or owned grace-period memberships.
/// @param _sender address of the sender of transaction (will be used to check memberships in grace period)
/// @param _idCommitment IDCommitment of the membership to erase
function _eraseMembership(address _sender, uint256 _idCommitment, MembershipInfo memory _mdetails) internal {
bool membershipExpired = _isExpired(_mdetails.gracePeriodStartDate, _mdetails.gracePeriod);
bool isGracePeriodAndOwned =
_isGracePeriod(_mdetails.gracePeriodStartDate, _mdetails.gracePeriod) && _mdetails.holder == _sender;
/// @param _idCommitment idCommitment of the membership to erase
function _eraseMembership(address _sender, uint256 _idCommitment, MembershipInfo memory _membership) internal {
bool membershipExpired = _isExpired(_membership.gracePeriodStartTimestamp, _membership.gracePeriodDuration);
bool isInGracePeriodAndOwned = // FIXME: separate into two checks? cf. short-circuit
_isInGracePeriodNow(_membership.gracePeriodStartTimestamp, _membership.gracePeriodDuration)
&& _membership.holder == _sender;
// FIXME: we already had a non-holder check: reuse it here as a modifier
if (!membershipExpired && !isInGracePeriodAndOwned) revert CantEraseMembership(_idCommitment);
if (!membershipExpired && !isGracePeriodAndOwned) revert CantEraseMembership(_idCommitment);
emit MemberExpired(_idCommitment, _mdetails.rateLimit, _mdetails.index);
emit MembershipExpired(_idCommitment, _membership.rateLimit, _membership.index);
// Move balance from expired membership to holder balance
balancesToWithdraw[_mdetails.holder][_mdetails.token] += _mdetails.amount;
balancesToWithdraw[_membership.holder][_membership.token] += _membership.depositAmount;
// Deduct the expired membership rate limit
totalRateLimitPerEpoch -= _mdetails.rateLimit;
totalRateLimit -= _membership.rateLimit;
availableExpiredIndices.push(_mdetails.index);
// Note: the Merkle tree data will be erased lazily later // FIXME: when?
availableExpiredMembershipsIndices.push(_membership.index);
delete memberships[_idCommitment];
}
/// @dev Withdraw any available balance in tokens after a membership is erased.
/// @param _sender the address of the owner of the tokens
/// @param _token the address of the token to withdraw.
/// @param _token the address of the token to withdraw
function _withdraw(address _sender, address _token) internal {
require(_token != address(0), "ETH is not allowed");

View File

@ -62,15 +62,15 @@ contract WakuRlnV2 is Initializable, Ownable2StepUpgradeable, UUPSUpgradeable, M
/// @dev contract initializer
/// @param _priceCalculator Address of an instance of IPriceCalculator
/// @param _maxTotalRateLimit Maximum total rate limit of all memberships FIXME: clarify: excl expired?
/// @param _minRateLimitPerMembership Minimum rate limit of one membership
/// @param _maxRateLimitPerMembership Maximum rate limit of one membership
/// @param _minMembershipRateLimit Minimum rate limit of one membership
/// @param _maxMembershipRateLimit Maximum rate limit of one membership
/// @param _expirationTerm Membership expiration term
/// @param _gracePeriod Membership grace period
function initialize(
address _priceCalculator,
uint32 _maxTotalRateLimit,
uint32 _minRateLimitPerMembership,
uint32 _maxRateLimitPerMembership,
uint32 _minMembershipRateLimit,
uint32 _maxMembershipRateLimit,
uint32 _expirationTerm,
uint32 _gracePeriod
)
@ -82,8 +82,8 @@ contract WakuRlnV2 is Initializable, Ownable2StepUpgradeable, UUPSUpgradeable, M
__MembershipUpgradeable_init(
_priceCalculator,
_maxTotalRateLimit,
_minRateLimitPerMembership,
_maxRateLimitPerMembership,
_minMembershipRateLimit,
_maxMembershipRateLimit,
_expirationTerm,
_gracePeriod
);
@ -137,10 +137,10 @@ contract WakuRlnV2 is Initializable, Ownable2StepUpgradeable, UUPSUpgradeable, M
if (membershipExists(idCommitment)) revert DuplicateIdCommitment();
uint32 index;
bool reuseIndex;
(index, reuseIndex) = _acquireMembership(_msgSender(), idCommitment, rateLimit);
bool indexReused;
(index, indexReused) = _acquireMembership(_msgSender(), idCommitment, rateLimit);
_register(idCommitment, rateLimit, index, reuseIndex);
_register(idCommitment, rateLimit, index, indexReused);
}
/// @notice Register a membership
@ -166,23 +166,23 @@ contract WakuRlnV2 is Initializable, Ownable2StepUpgradeable, UUPSUpgradeable, M
}
uint32 index;
bool reuseIndex;
(index, reuseIndex) = _acquireMembership(_msgSender(), idCommitment, rateLimit);
bool indexReused;
(index, indexReused) = _acquireMembership(_msgSender(), idCommitment, rateLimit);
_register(idCommitment, rateLimit, index, reuseIndex);
_register(idCommitment, rateLimit, index, indexReused);
}
/// @dev Registers a membership
/// @param idCommitment The idCommitment of the membership
/// @param rateLimit The rate limit of the membership
/// @param index The index of the membership in the membership set
/// @param reuseIndex Indicates whether we're inserting a new element in the Merkle tree or updating a existing
/// @param indexReused Indicates whether we're inserting a new element in the Merkle tree or updating a existing
/// element
function _register(uint256 idCommitment, uint32 rateLimit, uint32 index, bool reuseIndex) internal {
function _register(uint256 idCommitment, uint32 rateLimit, uint32 index, bool indexReused) internal {
if (nextFreeIndex >= MAX_MEMBERSHIP_SET_SIZE) revert FullMembershipSet();
uint256 rateCommitment = PoseidonT3.hash([idCommitment, rateLimit]);
if (reuseIndex) {
if (indexReused) {
LazyIMT.update(merkleTree, rateCommitment, index);
} else {
LazyIMT.insert(merkleTree, rateCommitment);
@ -241,7 +241,8 @@ contract WakuRlnV2 is Initializable, Ownable2StepUpgradeable, UUPSUpgradeable, M
/// The user (i.e. the transaction sender) can then withdraw the deposited tokens.
/// @param idCommitments list of idCommitments of the memberships to erase
function eraseMemberships(uint256[] calldata idCommitments) external {
for (uint256 i = 0; i < idCommitments.length; i++) { // FIXME: not DRY: see register()
for (uint256 i = 0; i < idCommitments.length; i++) {
// FIXME: not DRY: see register()
uint256 idCommitmentToErase = idCommitments[i];
MembershipInfo memory membershipToErase = memberships[idCommitmentToErase];
if (membershipToErase.rateLimit == 0) revert InvalidIdCommitment(idCommitmentToErase);
@ -264,23 +265,23 @@ contract WakuRlnV2 is Initializable, Ownable2StepUpgradeable, UUPSUpgradeable, M
/// @notice Set the maximum total rate limit of all (FIXME: excl expired?) memberships in the membership set
/// @param _maxTotalRateLimit new maximum total rate limit (messages per epoch)
function setmaxTotalRateLimit(uint32 _maxTotalRateLimit) external onlyOwner {
require(_maxTotalRateLimit >= maxRateLimitPerMembership);
function setMaxTotalRateLimit(uint32 _maxTotalRateLimit) external onlyOwner {
require(_maxTotalRateLimit >= maxMembershipRateLimit);
maxTotalRateLimit = _maxTotalRateLimit;
}
/// @notice Set the maximum rate limit of one membership
/// @param _maxRateLimitPerMembership new maximum rate limit per membership (messages per epoch)
function setMaxRateLimitPerMembership(uint32 _maxRateLimitPerMembership) external onlyOwner {
require(_maxRateLimitPerMembership >= minRateLimitPerMembership);
maxRateLimitPerMembership = _maxRateLimitPerMembership;
/// @param _maxMembershipRateLimit new maximum rate limit per membership (messages per epoch)
function setMaxMembershipRateLimit(uint32 _maxMembershipRateLimit) external onlyOwner {
require(_maxMembershipRateLimit >= minMembershipRateLimit);
maxMembershipRateLimit = _maxMembershipRateLimit;
}
/// @notice Set the minimum rate limit of one membership
/// @param _minRateLimitPerMembership new minimum rate limit per membership (messages per epoch)
function setMinRateLimitPerMembership(uint32 _minRateLimitPerMembership) external onlyOwner {
require(_minRateLimitPerMembership > 0); // FIXME: we must also check here that min rate <= max rate
minRateLimitPerMembership = _minRateLimitPerMembership;
/// @param _minMembershipRateLimit new minimum rate limit per membership (messages per epoch)
function setMinMembershipRateLimit(uint32 _minMembershipRateLimit) external onlyOwner {
require(_minMembershipRateLimit > 0); // FIXME: we must also check here that min rate <= max rate
minMembershipRateLimit = _minMembershipRateLimit;
}
/// @notice Set the expiration term for new memberships (expiration dates of existing memberships don't change)
@ -292,7 +293,8 @@ contract WakuRlnV2 is Initializable, Ownable2StepUpgradeable, UUPSUpgradeable, M
/// @notice Set the grace period for new memberships (grace periods of existing memberships don't change)
/// @param _gracePeriod new grace period term
function setGracePeriod(uint32 _gracePeriod) external onlyOwner { // FIXME: shall we check that _gracePeriod > 0?
gracePeriod = _gracePeriod;
function setGracePeriod(uint32 _gracePeriod) external onlyOwner {
// FIXME: shall we check that _gracePeriod > 0?
gracePeriodDuration = _gracePeriod;
}
}

View File

@ -37,7 +37,7 @@ contract WakuRlnV2Test is Test {
vm.pauseGasMetering();
// Merkle tree leaves are calculated using 2 as rateLimit
vm.prank(w.owner());
w.setMinRateLimitPerMembership(2);
w.setMinMembershipRateLimit(2);
uint256 idCommitment = 2;
uint32 membershipRateLimit = 2;
@ -59,8 +59,7 @@ contract WakuRlnV2Test is Test {
w.root(),
13_801_897_483_540_040_307_162_267_952_866_411_686_127_372_014_953_358_983_481_592_640_000_001_877_295
);
(uint32 fetchedMembershipRateLimit2, uint32 index2, uint256 rateCommitment2) =
w.getMembershipInfo(idCommitment);
(uint32 fetchedMembershipRateLimit2, uint32 index2, uint256 rateCommitment2) = w.getMembershipInfo(idCommitment);
assertEq(fetchedMembershipRateLimit2, membershipRateLimit);
assertEq(index2, 0);
assertEq(rateCommitment2, rateCommitment);
@ -97,8 +96,8 @@ contract WakuRlnV2Test is Test {
vm.pauseGasMetering();
uint256 idCommitment = 2;
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
uint256 minMembershipRateLimit = w.minRateLimitPerMembership();
uint256 maxMembershipRateLimit = w.maxRateLimitPerMembership();
uint256 minMembershipRateLimit = w.minMembershipRateLimit();
uint256 maxMembershipRateLimit = w.maxMembershipRateLimit();
vm.assume(membershipRateLimit >= minMembershipRateLimit && membershipRateLimit <= maxMembershipRateLimit);
vm.assume(w.isValidMembershipRateLimit(membershipRateLimit));
vm.resumeGasMetering();
@ -115,7 +114,7 @@ contract WakuRlnV2Test is Test {
assertEq(fetchedRateCommitment, rateCommitment);
assertEq(token.balanceOf(address(w)), price);
assertEq(w.totalRateLimitPerEpoch(), membershipRateLimit);
assertEq(w.totalRateLimit(), membershipRateLimit);
}
function test__LinearPriceCalculation(uint32 membershipRateLimit) external view {
@ -129,8 +128,8 @@ contract WakuRlnV2Test is Test {
function test__InvalidTokenAmount(uint256 idCommitment, uint32 membershipRateLimit) external {
vm.pauseGasMetering();
uint256 minMembershipRateLimit = w.minRateLimitPerMembership();
uint256 maxMembershipRateLimit = w.maxRateLimitPerMembership();
uint256 minMembershipRateLimit = w.minMembershipRateLimit();
uint256 maxMembershipRateLimit = w.maxMembershipRateLimit();
vm.assume(membershipRateLimit >= minMembershipRateLimit && membershipRateLimit <= maxMembershipRateLimit);
vm.assume(w.isValidIdCommitment(idCommitment) && w.isValidMembershipRateLimit(membershipRateLimit));
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
@ -176,8 +175,8 @@ contract WakuRlnV2Test is Test {
function test__InvalidRegistration__InvalidUserMessageLimit__MinMax() external {
uint256 idCommitment = 2;
uint32 invalidMin = w.minRateLimitPerMembership() - 1;
uint32 invalidMax = w.maxRateLimitPerMembership() + 1;
uint32 invalidMin = w.minMembershipRateLimit() - 1;
uint32 invalidMax = w.maxMembershipRateLimit() + 1;
vm.expectRevert(abi.encodeWithSelector(InvalidRateLimit.selector));
w.register(idCommitment, invalidMin);
@ -191,21 +190,21 @@ contract WakuRlnV2Test is Test {
uint256 idCommitment = 2;
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
vm.assume(
membershipRateLimit >= w.minRateLimitPerMembership() && membershipRateLimit <= w.maxRateLimitPerMembership()
membershipRateLimit >= w.minMembershipRateLimit() && membershipRateLimit <= w.maxMembershipRateLimit()
);
vm.assume(w.isValidMembershipRateLimit(membershipRateLimit));
vm.resumeGasMetering();
token.approve(address(w), price);
w.register(idCommitment, membershipRateLimit);
(, uint256 gracePeriodStartDate,,,,,) = w.memberships(idCommitment);
(, uint256 gracePeriodStartTimestamp,,,,,) = w.memberships(idCommitment);
assertFalse(w.isGracePeriod(idCommitment));
assertFalse(w.isInGracePeriodNow(idCommitment));
assertFalse(w.isExpired(idCommitment));
vm.warp(gracePeriodStartDate);
vm.warp(gracePeriodStartTimestamp);
assertTrue(w.isGracePeriod(idCommitment));
assertTrue(w.isInGracePeriodNow(idCommitment));
assertFalse(w.isExpired(idCommitment));
uint256[] memory commitmentsToExtend = new uint256[](1);
@ -214,18 +213,18 @@ contract WakuRlnV2Test is Test {
// Attempt to extend the membership (but it is not owned by us)
address randomAddress = vm.addr(block.timestamp);
vm.prank(randomAddress);
vm.expectRevert(abi.encodeWithSelector(NotHolder.selector, commitmentsToExtend[0]));
vm.expectRevert(abi.encodeWithSelector(AttemptedExtensionByNonHolder.selector, commitmentsToExtend[0]));
w.extendMemberships(commitmentsToExtend);
// Attempt to extend the membership (but now we are the owner)
vm.expectEmit(true, false, false, false); // only check the first parameter of the event (the idCommitment)
emit MembershipUpgradeable.MemberExtended(idCommitment, 0, 0, 0);
emit MembershipUpgradeable.MembershipExtended(idCommitment, 0, 0, 0);
w.extendMemberships(commitmentsToExtend);
(, uint256 newGracePeriodStartDate,,,,,) = w.memberships(idCommitment);
(, uint256 newgracePeriodStartTimestamp,,,,,) = w.memberships(idCommitment);
assertEq(block.timestamp + uint256(w.expirationTerm()), newGracePeriodStartDate);
assertFalse(w.isGracePeriod(idCommitment));
assertEq(block.timestamp + uint256(w.expirationTerm()), newgracePeriodStartTimestamp);
assertFalse(w.isInGracePeriodNow(idCommitment));
assertFalse(w.isExpired(idCommitment));
// Attempt to extend a non grace period membership
@ -241,31 +240,31 @@ contract WakuRlnV2Test is Test {
uint256 idCommitment = 2;
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
vm.assume(
membershipRateLimit >= w.minRateLimitPerMembership() && membershipRateLimit <= w.maxRateLimitPerMembership()
membershipRateLimit >= w.minMembershipRateLimit() && membershipRateLimit <= w.maxMembershipRateLimit()
);
vm.assume(w.isValidMembershipRateLimit(membershipRateLimit));
vm.resumeGasMetering();
token.approve(address(w), price);
w.register(idCommitment, membershipRateLimit);
uint256 ogExpirationDate = w.expirationDate(idCommitment);
(, uint256 gracePeriodStartDate,,,,,) = w.memberships(idCommitment);
uint256 ogExpirationTimestamp = w.membershipExpirationTimestamp(idCommitment);
(, uint256 gracePeriodStartTimestamp,,,,,) = w.memberships(idCommitment);
vm.warp(gracePeriodStartDate);
vm.warp(gracePeriodStartTimestamp);
uint256[] memory commitmentsToExtend = new uint256[](1);
commitmentsToExtend[0] = idCommitment;
// Extend the membership
vm.expectEmit(true, false, false, false); // only check the first parameter of the event (the idCommitment)
emit MembershipUpgradeable.MemberExtended(idCommitment, 0, 0, 0);
emit MembershipUpgradeable.MembershipExtended(idCommitment, 0, 0, 0);
w.extendMemberships(commitmentsToExtend);
(, uint256 newGracePeriodStartDate, uint32 newGracePeriod,,,,) = w.memberships(idCommitment);
uint256 expectedExpirationDate = newGracePeriodStartDate + uint256(newGracePeriod) + 1;
uint256 expirationDate = w.expirationDate(idCommitment);
assertEq(expectedExpirationDate, expirationDate);
assertTrue(expectedExpirationDate > ogExpirationDate);
(, uint256 newgracePeriodStartTimestamp, uint32 newGracePeriod,,,,) = w.memberships(idCommitment);
uint256 expectedExpirationTimestamp = newgracePeriodStartTimestamp + uint256(newGracePeriod) + 1;
uint256 membershipExpirationTimestamp = w.membershipExpirationTimestamp(idCommitment);
assertEq(expectedExpirationTimestamp, membershipExpirationTimestamp);
assertTrue(expectedExpirationTimestamp > ogExpirationTimestamp);
}
function test__ValidRegistrationExpiry(uint32 membershipRateLimit) external {
@ -273,7 +272,7 @@ contract WakuRlnV2Test is Test {
uint256 idCommitment = 2;
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
vm.assume(
membershipRateLimit >= w.minRateLimitPerMembership() && membershipRateLimit <= w.maxRateLimitPerMembership()
membershipRateLimit >= w.minMembershipRateLimit() && membershipRateLimit <= w.maxMembershipRateLimit()
);
vm.assume(w.isValidMembershipRateLimit(membershipRateLimit));
vm.resumeGasMetering();
@ -281,25 +280,25 @@ contract WakuRlnV2Test is Test {
token.approve(address(w), price);
w.register(idCommitment, membershipRateLimit);
(, uint256 fetchedGracePeriodStartDate, uint32 fetchedGracePeriod,,,,) = w.memberships(idCommitment);
(, uint256 fetchedgracePeriodStartTimestamp, uint32 fetchedGracePeriod,,,,) = w.memberships(idCommitment);
uint256 expectedExpirationDate = fetchedGracePeriodStartDate + uint256(fetchedGracePeriod) + 1;
uint256 expirationDate = w.expirationDate(idCommitment);
uint256 expectedExpirationTimestamp = fetchedgracePeriodStartTimestamp + uint256(fetchedGracePeriod) + 1;
uint256 membershipExpirationTimestamp = w.membershipExpirationTimestamp(idCommitment);
assertEq(expectedExpirationDate, expirationDate);
assertEq(expectedExpirationTimestamp, membershipExpirationTimestamp);
vm.warp(expirationDate);
vm.warp(membershipExpirationTimestamp);
assertFalse(w.isGracePeriod(idCommitment));
assertFalse(w.isInGracePeriodNow(idCommitment));
assertTrue(w.isExpired(idCommitment));
}
function test__ValidRegistrationWithEraseList() external {
vm.pauseGasMetering();
vm.startPrank(w.owner());
w.setMinRateLimitPerMembership(20);
w.setMaxRateLimitPerMembership(100);
w.setmaxTotalRateLimit(100);
w.setMinMembershipRateLimit(20);
w.setMaxMembershipRateLimit(100);
w.setMaxTotalRateLimit(100);
vm.stopPrank();
vm.resumeGasMetering();
@ -309,23 +308,23 @@ contract WakuRlnV2Test is Test {
token.approve(address(w), priceA);
w.register(i, 20);
// Make sure they're expired
vm.warp(w.expirationDate(i));
vm.warp(w.membershipExpirationTimestamp(i));
}
// Time travel to a point in which the last membership is active
(, uint256 gracePeriodStartDate,,,,,) = w.memberships(5);
vm.warp(gracePeriodStartDate - 1);
(, uint256 gracePeriodStartTimestamp,,,,,) = w.memberships(5);
vm.warp(gracePeriodStartTimestamp - 1);
// Ensure that this is the case
assertTrue(w.isExpired(4));
assertFalse(w.isExpired(5));
assertFalse(w.isGracePeriod(5));
assertFalse(w.isInGracePeriodNow(5));
(, uint256 priceB) = w.priceCalculator().calculate(60);
token.approve(address(w), priceB);
// Should fail. There's not enough free rate limit
vm.expectRevert(abi.encodeWithSelector(ExceedAvailableMaxRateLimitPerEpoch.selector));
vm.expectRevert(abi.encodeWithSelector(ExceededMaxTotalRateLimit.selector));
w.register(6, 60);
// Attempt to expire 3 commitments including one that can't be erased (the last one)
@ -340,11 +339,11 @@ contract WakuRlnV2Test is Test {
// Attempt to expire 3 commitments that can be erased
commitmentsToErase[2] = 4;
vm.expectEmit(true, false, false, false);
emit MembershipUpgradeable.MemberExpired(1, 0, 0);
emit MembershipUpgradeable.MembershipExpired(1, 0, 0);
vm.expectEmit(true, false, false, false);
emit MembershipUpgradeable.MemberExpired(2, 0, 0);
emit MembershipUpgradeable.MembershipExpired(2, 0, 0);
vm.expectEmit(true, false, false, false);
emit MembershipUpgradeable.MemberExpired(4, 0, 0);
emit MembershipUpgradeable.MembershipExpired(4, 0, 0);
w.register(6, 60, commitmentsToErase);
// Ensure that the chosen memberships were erased and others unaffected
@ -370,9 +369,9 @@ contract WakuRlnV2Test is Test {
function test__RegistrationWhenMaxRateLimitIsReached() external {
vm.pauseGasMetering();
vm.startPrank(w.owner());
w.setMinRateLimitPerMembership(1);
w.setMaxRateLimitPerMembership(5);
w.setmaxTotalRateLimit(5);
w.setMinMembershipRateLimit(1);
w.setMaxMembershipRateLimit(5);
w.setMaxTotalRateLimit(5);
vm.stopPrank();
vm.resumeGasMetering();
@ -396,7 +395,7 @@ contract WakuRlnV2Test is Test {
membershipRateLimit = 2;
(, price) = w.priceCalculator().calculate(membershipRateLimit);
token.approve(address(w), price);
vm.expectRevert(abi.encodeWithSelector(ExceedAvailableMaxRateLimitPerEpoch.selector));
vm.expectRevert(abi.encodeWithSelector(ExceededMaxTotalRateLimit.selector));
w.register(3, membershipRateLimit);
// Should register succesfully
@ -409,7 +408,7 @@ contract WakuRlnV2Test is Test {
membershipRateLimit = 1;
(, price) = w.priceCalculator().calculate(membershipRateLimit);
token.approve(address(w), price);
vm.expectRevert(abi.encodeWithSelector(ExceedAvailableMaxRateLimitPerEpoch.selector));
vm.expectRevert(abi.encodeWithSelector(ExceededMaxTotalRateLimit.selector));
w.register(4, membershipRateLimit);
}
@ -428,34 +427,34 @@ contract WakuRlnV2Test is Test {
}
// time travel to the moment we can erase all expired memberships
uint256 expirationDate = w.expirationDate(idCommitmentsLength);
vm.warp(expirationDate);
uint256 membershipExpirationTimestamp = w.membershipExpirationTimestamp(idCommitmentsLength);
vm.warp(membershipExpirationTimestamp);
w.eraseMemberships(commitmentsToErase);
// Verify that expired indices match what we expect
for (uint32 i = 0; i < idCommitmentsLength; i++) {
assertEq(i, w.availableExpiredIndices(i));
assertEq(i, w.availableExpiredMembershipsIndices(i));
}
uint32 currnextCommitmentIndex = w.nextFreeIndex();
for (uint256 i = 1; i <= idCommitmentsLength; i++) {
uint256 idCommitment = i + 10;
uint256 expectedReusedIndexPos = idCommitmentsLength - i;
uint32 expectedIndex = w.availableExpiredIndices(expectedReusedIndexPos);
uint256 expectedindexReusedPos = idCommitmentsLength - i;
uint32 expectedIndex = w.availableExpiredMembershipsIndices(expectedindexReusedPos);
token.approve(address(w), price);
w.register(idCommitment, 20);
(,,,, index,,) = w.memberships(idCommitment);
assertEq(expectedIndex, index);
// Should have been removed from the list
vm.expectRevert();
w.availableExpiredIndices(expectedReusedIndexPos);
w.availableExpiredMembershipsIndices(expectedindexReusedPos);
// Should not have been affected
assertEq(currnextCommitmentIndex, w.nextFreeIndex());
}
// No indexes should be available for reuse
vm.expectRevert();
w.availableExpiredIndices(0);
w.availableExpiredMembershipsIndices(0);
// Should use a new index since we got rid of all available indexes
token.approve(address(w), price);
@ -470,7 +469,7 @@ contract WakuRlnV2Test is Test {
uint256 idCommitment = 2;
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
vm.assume(
membershipRateLimit >= w.minRateLimitPerMembership() && membershipRateLimit <= w.maxRateLimitPerMembership()
membershipRateLimit >= w.minMembershipRateLimit() && membershipRateLimit <= w.maxMembershipRateLimit()
);
vm.assume(w.isValidMembershipRateLimit(membershipRateLimit));
vm.resumeGasMetering();
@ -484,8 +483,8 @@ contract WakuRlnV2Test is Test {
}
// Expiring the first 3
uint256 expirationDate = w.expirationDate(idCommitment + 2);
vm.warp(expirationDate);
uint256 membershipExpirationTimestamp = w.membershipExpirationTimestamp(idCommitment + 2);
vm.warp(membershipExpirationTimestamp);
for (uint256 i = 0; i < 5; i++) {
if (i <= 2) {
assertTrue(w.isExpired(idCommitment + i));
@ -499,9 +498,9 @@ contract WakuRlnV2Test is Test {
commitmentsToErase[1] = idCommitment + 2;
vm.expectEmit(true, false, false, false); // only check the first parameter of the event (the idCommitment)
emit MembershipUpgradeable.MemberExpired(commitmentsToErase[0], 0, 0);
emit MembershipUpgradeable.MembershipExpired(commitmentsToErase[0], 0, 0);
vm.expectEmit(true, false, false, false); // only check the first parameter of the event (the idCommitment)
emit MembershipUpgradeable.MemberExpired(commitmentsToErase[0], 0, 0);
emit MembershipUpgradeable.MembershipExpired(commitmentsToErase[0], 0, 0);
w.eraseMemberships(commitmentsToErase);
address holder;
@ -514,8 +513,8 @@ contract WakuRlnV2Test is Test {
// Attempting to call erase when some of the commitments can't be erased yet
// idCommitment can be erased (in grace period), but idCommitment + 4 is still active
(, uint256 gracePeriodStartDate,,,,,) = w.memberships(idCommitment + 4);
vm.warp(gracePeriodStartDate - 1);
(, uint256 gracePeriodStartTimestamp,,,,,) = w.memberships(idCommitment + 4);
vm.warp(gracePeriodStartTimestamp - 1);
commitmentsToErase[0] = idCommitment;
commitmentsToErase[1] = idCommitment + 4;
vm.expectRevert(abi.encodeWithSelector(CantEraseMembership.selector, idCommitment + 4));
@ -525,7 +524,7 @@ contract WakuRlnV2Test is Test {
function test__RemoveAllExpiredMemberships(uint32 idCommitmentsLength) external {
vm.pauseGasMetering();
vm.assume(idCommitmentsLength > 1 && idCommitmentsLength <= 100);
uint32 membershipRateLimit = w.minRateLimitPerMembership();
uint32 membershipRateLimit = w.minMembershipRateLimit();
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
vm.resumeGasMetering();
@ -537,8 +536,8 @@ contract WakuRlnV2Test is Test {
vm.warp(time);
}
uint256 expirationDate = w.expirationDate(idCommitmentsLength);
vm.warp(expirationDate);
uint256 membershipExpirationTimestamp = w.membershipExpirationTimestamp(idCommitmentsLength);
vm.warp(membershipExpirationTimestamp);
for (uint256 i = 1; i <= 5; i++) {
assertTrue(w.isExpired(i));
}
@ -547,7 +546,7 @@ contract WakuRlnV2Test is Test {
for (uint256 i = 0; i < idCommitmentsLength; i++) {
commitmentsToErase[i] = i + 1;
vm.expectEmit(true, false, false, false); // only check the first parameter of the event (the idCommitment)
emit MembershipUpgradeable.MemberExpired(i + 1, 0, 0);
emit MembershipUpgradeable.MembershipExpired(i + 1, 0, 0);
}
w.eraseMemberships(commitmentsToErase);
@ -568,7 +567,7 @@ contract WakuRlnV2Test is Test {
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
token.mint(address(this), price);
vm.assume(
membershipRateLimit >= w.minRateLimitPerMembership() && membershipRateLimit <= w.maxRateLimitPerMembership()
membershipRateLimit >= w.minMembershipRateLimit() && membershipRateLimit <= w.maxMembershipRateLimit()
);
vm.assume(w.isValidMembershipRateLimit(membershipRateLimit));
vm.resumeGasMetering();
@ -576,9 +575,9 @@ contract WakuRlnV2Test is Test {
token.approve(address(w), price);
w.register(idCommitment, membershipRateLimit);
(, uint256 gracePeriodStartDate,,,,,) = w.memberships(idCommitment);
(, uint256 gracePeriodStartTimestamp,,,,,) = w.memberships(idCommitment);
vm.warp(gracePeriodStartDate);
vm.warp(gracePeriodStartTimestamp);
uint256[] memory commitmentsToErase = new uint256[](1);
commitmentsToErase[0] = idCommitment;
@ -604,7 +603,7 @@ contract WakuRlnV2Test is Test {
function test__InvalidRegistration__DuplicateIdCommitment() external {
vm.pauseGasMetering();
uint256 idCommitment = 2;
uint32 membershipRateLimit = w.minRateLimitPerMembership();
uint32 membershipRateLimit = w.minMembershipRateLimit();
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
vm.resumeGasMetering();
@ -664,7 +663,7 @@ contract WakuRlnV2Test is Test {
function test__ValidPaginationQuery__OneElement() external {
vm.pauseGasMetering();
uint256 idCommitment = 1;
uint32 membershipRateLimit = w.minRateLimitPerMembership();
uint32 membershipRateLimit = w.minMembershipRateLimit();
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
vm.resumeGasMetering();
@ -679,7 +678,7 @@ contract WakuRlnV2Test is Test {
function test__ValidPaginationQuery(uint32 idCommitmentsLength) external {
vm.pauseGasMetering();
vm.assume(idCommitmentsLength > 0 && idCommitmentsLength <= 100);
uint32 membershipRateLimit = w.minRateLimitPerMembership();
uint32 membershipRateLimit = w.minMembershipRateLimit();
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
for (uint256 i = 0; i < idCommitmentsLength; i++) {