mirror of
https://github.com/logos-messaging/logos-messaging-rlnv2-contract.git
synced 2026-01-07 08:23:09 +00:00
chore: improve terminology consistency
This commit is contained in:
parent
4fdcdbc73c
commit
4b3f608bee
@ -29,7 +29,7 @@ abstract contract MembershipUpgradeable is Initializable {
|
||||
IPriceCalculator public priceCalculator;
|
||||
|
||||
/// @notice Maximum total rate limit of all memberships in the tree
|
||||
uint32 public maxTotalRateLimitPerEpoch;
|
||||
uint32 public maxTotalRateLimit;
|
||||
|
||||
/// @notice Maximum rate limit of one membership
|
||||
uint32 public maxRateLimitPerMembership;
|
||||
@ -50,10 +50,10 @@ abstract contract MembershipUpgradeable is Initializable {
|
||||
uint256 public totalRateLimitPerEpoch;
|
||||
|
||||
/// @notice List of registered memberships
|
||||
mapping(uint256 idCommitment => MembershipInfo member) public members;
|
||||
mapping(uint256 idCommitment => MembershipInfo member) public memberships;
|
||||
|
||||
/// @notice The index on the merkle tree for the next member to be registered
|
||||
uint32 public nextCommitmentIndex;
|
||||
/// @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;
|
||||
@ -65,9 +65,9 @@ abstract contract MembershipUpgradeable is Initializable {
|
||||
uint256 gracePeriodStartDate;
|
||||
/// @notice duration of the grace period
|
||||
uint32 gracePeriod;
|
||||
/// @notice the user message limit of each member
|
||||
uint32 userMessageLimit;
|
||||
/// @notice the index of the member in the set
|
||||
/// @notice the membership rate limit
|
||||
uint32 rateLimit;
|
||||
/// @notice the index of the member in the membership set
|
||||
uint32 index;
|
||||
/// @notice address of the owner of this membership
|
||||
address holder;
|
||||
@ -78,27 +78,27 @@ abstract contract MembershipUpgradeable is Initializable {
|
||||
/// @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
|
||||
/// @param userMessageLimit the rate limit of this 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 userMessageLimit, uint32 index);
|
||||
event MemberExpired(uint256 idCommitment, uint32 membershipRateLimit, uint32 index);
|
||||
|
||||
/// @notice Emitted when a membership in grace period is extended
|
||||
/// @param idCommitment the idCommitment of the member
|
||||
/// @param userMessageLimit the rate limit of this 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 userMessageLimit, uint32 index, uint256 newExpirationDate);
|
||||
event MemberExtended(uint256 idCommitment, uint32 membershipRateLimit, uint32 index, uint256 newExpirationDate);
|
||||
|
||||
/// @dev contract initializer
|
||||
/// @param _priceCalculator Address of an instance of IPriceCalculator
|
||||
/// @param _maxTotalRateLimitPerEpoch Maximum total rate limit of all memberships in the tree
|
||||
/// @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
|
||||
function __MembershipUpgradeable_init(
|
||||
address _priceCalculator,
|
||||
uint32 _maxTotalRateLimitPerEpoch,
|
||||
uint32 _maxTotalRateLimit,
|
||||
uint32 _minRateLimitPerMembership,
|
||||
uint32 _maxRateLimitPerMembership,
|
||||
uint32 _expirationTerm,
|
||||
@ -109,7 +109,7 @@ abstract contract MembershipUpgradeable is Initializable {
|
||||
{
|
||||
__MembershipUpgradeable_init_unchained(
|
||||
_priceCalculator,
|
||||
_maxTotalRateLimitPerEpoch,
|
||||
_maxTotalRateLimit,
|
||||
_minRateLimitPerMembership,
|
||||
_maxRateLimitPerMembership,
|
||||
_expirationTerm,
|
||||
@ -119,7 +119,7 @@ abstract contract MembershipUpgradeable is Initializable {
|
||||
|
||||
function __MembershipUpgradeable_init_unchained(
|
||||
address _priceCalculator,
|
||||
uint32 _maxTotalRateLimitPerEpoch,
|
||||
uint32 _maxTotalRateLimit,
|
||||
uint32 _minRateLimitPerMembership,
|
||||
uint32 _maxRateLimitPerMembership,
|
||||
uint32 _expirationTerm,
|
||||
@ -128,43 +128,43 @@ abstract contract MembershipUpgradeable is Initializable {
|
||||
internal
|
||||
onlyInitializing
|
||||
{
|
||||
require(_maxTotalRateLimitPerEpoch >= maxRateLimitPerMembership);
|
||||
require(_maxTotalRateLimit >= maxRateLimitPerMembership);
|
||||
require(_maxRateLimitPerMembership > minRateLimitPerMembership);
|
||||
require(_minRateLimitPerMembership > 0);
|
||||
require(_expirationTerm > 0);
|
||||
|
||||
priceCalculator = IPriceCalculator(_priceCalculator);
|
||||
maxTotalRateLimitPerEpoch = _maxTotalRateLimitPerEpoch;
|
||||
maxTotalRateLimit = _maxTotalRateLimit;
|
||||
maxRateLimitPerMembership = _maxRateLimitPerMembership;
|
||||
minRateLimitPerMembership = _minRateLimitPerMembership;
|
||||
expirationTerm = _expirationTerm;
|
||||
gracePeriod = _gracePeriod;
|
||||
}
|
||||
|
||||
/// @notice Checks if a user message limit is valid. This does not take into account whether we the total
|
||||
/// memberships have reached already the `maxTotalRateLimitPerEpoch`
|
||||
/// @param userMessageLimit The user message limit
|
||||
/// @return true if the user message limit is valid, false otherwise
|
||||
function isValidUserMessageLimit(uint32 userMessageLimit) external view returns (bool) {
|
||||
return userMessageLimit >= minRateLimitPerMembership && userMessageLimit <= maxRateLimitPerMembership;
|
||||
/// @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`
|
||||
/// @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;
|
||||
}
|
||||
|
||||
/// @dev acquire a membership and trasnfer the fees to the contract
|
||||
/// @param _sender address of the owner of the new membership
|
||||
/// @param _idCommitment the idcommitment of the new membership
|
||||
/// @param _rateLimit the user message limit
|
||||
/// @param _rateLimit the membership rate limit
|
||||
/// @return index the index in the merkle tree
|
||||
/// @return reusedIndex indicates whether a new leaf is being used or if using an existing leaf in the merkle tree
|
||||
/// @return reuseIndex indicates whether a new leaf is being used or if using an existing leaf in the merkle tree
|
||||
function _acquireMembership(
|
||||
address _sender,
|
||||
uint256 _idCommitment,
|
||||
uint32 _rateLimit
|
||||
)
|
||||
internal
|
||||
returns (uint32 index, bool reusedIndex)
|
||||
returns (uint32 index, bool reuseIndex)
|
||||
{
|
||||
(address token, uint256 amount) = priceCalculator.calculate(_rateLimit);
|
||||
(index, reusedIndex) = _setupMembershipDetails(_sender, _idCommitment, _rateLimit, token, amount);
|
||||
(index, reuseIndex) = _setupMembershipDetails(_sender, _idCommitment, _rateLimit, token, amount);
|
||||
_transferFees(_sender, token, amount);
|
||||
}
|
||||
|
||||
@ -177,11 +177,11 @@ abstract contract MembershipUpgradeable is Initializable {
|
||||
/// slots helds by the membership
|
||||
/// @param _sender holder of the membership. Generally `msg.sender`
|
||||
/// @param _idCommitment IDCommitment
|
||||
/// @param _rateLimit User message limit
|
||||
/// @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 reusedIndex indicates whether the index returned was a reused slot on the tree or not
|
||||
/// @return reuseIndex indicates whether the index returned was a reused slot on the tree or not
|
||||
function _setupMembershipDetails(
|
||||
address _sender,
|
||||
uint256 _idCommitment,
|
||||
@ -190,7 +190,7 @@ abstract contract MembershipUpgradeable is Initializable {
|
||||
uint256 _amount
|
||||
)
|
||||
internal
|
||||
returns (uint32 index, bool reusedIndex)
|
||||
returns (uint32 index, bool reuseIndex)
|
||||
{
|
||||
if (_rateLimit < minRateLimitPerMembership || _rateLimit > maxRateLimitPerMembership) {
|
||||
revert InvalidRateLimit();
|
||||
@ -198,36 +198,36 @@ abstract contract MembershipUpgradeable is Initializable {
|
||||
|
||||
// Determine if we exceed the total rate limit
|
||||
totalRateLimitPerEpoch += _rateLimit;
|
||||
if (totalRateLimitPerEpoch > maxTotalRateLimitPerEpoch) {
|
||||
if (totalRateLimitPerEpoch > maxTotalRateLimit) {
|
||||
revert ExceedAvailableMaxRateLimitPerEpoch(); // List is empty or can't
|
||||
}
|
||||
|
||||
// Reuse available slots from previously removed expired memberships
|
||||
(index, reusedIndex) = _nextIndex();
|
||||
(index, reuseIndex) = _nextIndex();
|
||||
|
||||
members[_idCommitment] = MembershipInfo({
|
||||
memberships[_idCommitment] = MembershipInfo({
|
||||
holder: _sender,
|
||||
gracePeriodStartDate: block.timestamp + uint256(expirationTerm),
|
||||
gracePeriod: gracePeriod,
|
||||
token: _token,
|
||||
amount: _amount,
|
||||
userMessageLimit: _rateLimit,
|
||||
rateLimit: _rateLimit,
|
||||
index: index
|
||||
});
|
||||
}
|
||||
|
||||
/// @dev reuse available slots from previously removed expired memberships
|
||||
/// @return index index to use
|
||||
/// @return reusedIndex indicates whether it is reusing an existing index, or using a new one
|
||||
function _nextIndex() internal returns (uint32 index, bool reusedIndex) {
|
||||
/// @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;
|
||||
if (arrLen != 0) {
|
||||
index = availableExpiredIndices[arrLen - 1];
|
||||
availableExpiredIndices.pop();
|
||||
reusedIndex = true;
|
||||
reuseIndex = true;
|
||||
} else {
|
||||
index = nextCommitmentIndex;
|
||||
index = nextFreeIndex;
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,7 +235,7 @@ abstract contract MembershipUpgradeable is Initializable {
|
||||
/// @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 = members[_idCommitment];
|
||||
MembershipInfo storage mdetails = memberships[_idCommitment];
|
||||
|
||||
if (!_isGracePeriod(mdetails.gracePeriodStartDate, mdetails.gracePeriod)) {
|
||||
revert NotInGracePeriod(_idCommitment);
|
||||
@ -248,7 +248,7 @@ abstract contract MembershipUpgradeable is Initializable {
|
||||
mdetails.gracePeriodStartDate = gracePeriodStartDate;
|
||||
mdetails.gracePeriod = gracePeriod;
|
||||
|
||||
emit MemberExtended(_idCommitment, mdetails.userMessageLimit, mdetails.index, gracePeriodStartDate);
|
||||
emit MemberExtended(_idCommitment, mdetails.rateLimit, mdetails.index, gracePeriodStartDate);
|
||||
}
|
||||
|
||||
/// @dev Determine whether a timestamp is considered to be expired or not after exceeding the grace period
|
||||
@ -261,14 +261,14 @@ abstract contract MembershipUpgradeable is Initializable {
|
||||
/// @notice Determine if a membership is expired (has exceeded the grace period)
|
||||
/// @param _idCommitment the idCommitment of the membership
|
||||
function isExpired(uint256 _idCommitment) public view returns (bool) {
|
||||
MembershipInfo memory m = members[_idCommitment];
|
||||
MembershipInfo memory m = memberships[_idCommitment];
|
||||
return _isExpired(m.gracePeriodStartDate, m.gracePeriod);
|
||||
}
|
||||
|
||||
/// @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 = members[_idCommitment];
|
||||
MembershipInfo memory m = memberships[_idCommitment];
|
||||
return m.gracePeriodStartDate + uint256(m.gracePeriod) + 1;
|
||||
}
|
||||
|
||||
@ -284,11 +284,11 @@ abstract contract MembershipUpgradeable is Initializable {
|
||||
/// @notice Determine if a membership is in grace period
|
||||
/// @param _idCommitment the idCommitment of the membership
|
||||
function isGracePeriod(uint256 _idCommitment) public view returns (bool) {
|
||||
MembershipInfo memory m = members[_idCommitment];
|
||||
MembershipInfo memory m = memberships[_idCommitment];
|
||||
return _isGracePeriod(m.gracePeriodStartDate, m.gracePeriod);
|
||||
}
|
||||
|
||||
/// @dev Remove expired memberships or owned memberships in grace period.
|
||||
/// @dev Erase expired memberships or owned memberships in grace period.
|
||||
/// @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 {
|
||||
@ -298,17 +298,17 @@ abstract contract MembershipUpgradeable is Initializable {
|
||||
|
||||
if (!membershipExpired && !isGracePeriodAndOwned) revert CantEraseMembership(_idCommitment);
|
||||
|
||||
emit MemberExpired(_idCommitment, _mdetails.userMessageLimit, _mdetails.index);
|
||||
emit MemberExpired(_idCommitment, _mdetails.rateLimit, _mdetails.index);
|
||||
|
||||
// Move balance from expired membership to holder balance
|
||||
balancesToWithdraw[_mdetails.holder][_mdetails.token] += _mdetails.amount;
|
||||
|
||||
// Deduct the expired membership rate limit
|
||||
totalRateLimitPerEpoch -= _mdetails.userMessageLimit;
|
||||
totalRateLimitPerEpoch -= _mdetails.rateLimit;
|
||||
|
||||
availableExpiredIndices.push(_mdetails.index);
|
||||
|
||||
delete members[_idCommitment];
|
||||
delete memberships[_idCommitment];
|
||||
}
|
||||
|
||||
/// @dev Withdraw any available balance in tokens after a membership is erased.
|
||||
|
||||
@ -11,17 +11,17 @@ import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils
|
||||
import { MembershipUpgradeable } from "./Membership.sol";
|
||||
import { IPriceCalculator } from "./IPriceCalculator.sol";
|
||||
|
||||
/// The tree is full
|
||||
error FullTree();
|
||||
/// The membership set is full
|
||||
error FullMembershipSet();
|
||||
|
||||
/// Member is already registered
|
||||
/// A membership with this idCommitment is already registered
|
||||
error DuplicateIdCommitment();
|
||||
|
||||
/// Invalid idCommitment
|
||||
error InvalidIdCommitment(uint256 idCommitment);
|
||||
|
||||
/// Invalid userMessageLimit
|
||||
error InvalidUserMessageLimit(uint32 messageLimit);
|
||||
/// Invalid membership rate limit // FIXME: this is not used - remove?
|
||||
error InvalidMembershipRateLimit(uint32 rateLimit);
|
||||
|
||||
/// Invalid pagination query
|
||||
error InvalidPaginationQuery(uint256 startIndex, uint256 endIndex);
|
||||
@ -31,27 +31,27 @@ contract WakuRlnV2 is Initializable, Ownable2StepUpgradeable, UUPSUpgradeable, M
|
||||
uint256 public constant Q =
|
||||
21_888_242_871_839_275_222_246_405_745_257_275_088_548_364_400_416_034_343_698_204_186_575_808_495_617;
|
||||
|
||||
/// @notice The depth of the merkle tree
|
||||
uint8 public constant DEPTH = 20;
|
||||
/// @notice The depth of the Merkle tree that stores rate commitments of memberships
|
||||
uint8 public constant MERKLE_TREE_DEPTH = 20;
|
||||
|
||||
/// @notice The size of the merkle tree, i.e 2^depth
|
||||
uint32 public SET_SIZE;
|
||||
/// @notice The maximum membership set size is the size of the Merkle tree (2 ^ depth)
|
||||
uint32 public MAX_MEMBERSHIP_SET_SIZE;
|
||||
|
||||
/// @notice the deployed block number
|
||||
/// @notice The block number at which this contract was deployed
|
||||
uint32 public deployedBlockNumber;
|
||||
|
||||
/// @notice the stored imt data
|
||||
LazyIMTData public imtData;
|
||||
/// @notice The Merkle tree that stores rate commitments of memberships
|
||||
LazyIMTData public merkleTree;
|
||||
|
||||
/// Emitted when a new member is added to the set
|
||||
/// @param rateCommitment the rateCommitment of the member
|
||||
/// @param index The index of the member in the set
|
||||
event MemberRegistered(uint256 rateCommitment, uint32 index);
|
||||
/// Emitted when a new membership is added to the membership set
|
||||
/// @param rateCommitment The rateCommitment of the membership
|
||||
/// @param index The index of the membership in the membership set
|
||||
event MembershipRegistered(uint256 rateCommitment, uint32 index);
|
||||
|
||||
/// @notice the modifier to check if the idCommitment is valid
|
||||
/// @param idCommitment The idCommitment of the member
|
||||
/// @param idCommitment The idCommitment of the membership
|
||||
modifier onlyValidIdCommitment(uint256 idCommitment) {
|
||||
if (!isValidCommitment(idCommitment)) revert InvalidIdCommitment(idCommitment);
|
||||
if (!isValidIdCommitment(idCommitment)) revert InvalidIdCommitment(idCommitment);
|
||||
_;
|
||||
}
|
||||
|
||||
@ -61,14 +61,14 @@ contract WakuRlnV2 is Initializable, Ownable2StepUpgradeable, UUPSUpgradeable, M
|
||||
|
||||
/// @dev contract initializer
|
||||
/// @param _priceCalculator Address of an instance of IPriceCalculator
|
||||
/// @param _maxTotalRateLimitPerEpoch Maximum total rate limit of all memberships in the tree
|
||||
/// @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 _expirationTerm Membership expiration term
|
||||
/// @param _gracePeriod Membership grace period
|
||||
function initialize(
|
||||
address _priceCalculator,
|
||||
uint32 _maxTotalRateLimitPerEpoch,
|
||||
uint32 _maxTotalRateLimit,
|
||||
uint32 _minRateLimitPerMembership,
|
||||
uint32 _maxRateLimitPerMembership,
|
||||
uint32 _expirationTerm,
|
||||
@ -81,176 +81,176 @@ contract WakuRlnV2 is Initializable, Ownable2StepUpgradeable, UUPSUpgradeable, M
|
||||
__UUPSUpgradeable_init();
|
||||
__MembershipUpgradeable_init(
|
||||
_priceCalculator,
|
||||
_maxTotalRateLimitPerEpoch,
|
||||
_maxTotalRateLimit,
|
||||
_minRateLimitPerMembership,
|
||||
_maxRateLimitPerMembership,
|
||||
_expirationTerm,
|
||||
_gracePeriod
|
||||
);
|
||||
|
||||
SET_SIZE = uint32(1 << DEPTH);
|
||||
MAX_MEMBERSHIP_SET_SIZE = uint32(1 << MERKLE_TREE_DEPTH);
|
||||
deployedBlockNumber = uint32(block.number);
|
||||
LazyIMT.init(imtData, DEPTH);
|
||||
nextCommitmentIndex = 0;
|
||||
LazyIMT.init(merkleTree, MERKLE_TREE_DEPTH);
|
||||
nextFreeIndex = 0;
|
||||
}
|
||||
|
||||
function _authorizeUpgrade(address newImplementation) internal override onlyOwner { } // solhint-disable-line
|
||||
|
||||
/// @notice Checks if a commitment is valid
|
||||
/// @param idCommitment The idCommitment of the member
|
||||
/// @return true if the commitment is valid, false otherwise
|
||||
function isValidCommitment(uint256 idCommitment) public pure returns (bool) {
|
||||
/// @notice Checks if an idCommitment is valid
|
||||
/// @param idCommitment The idCommitment of the membership
|
||||
/// @return true if the idCommitment is valid, false otherwise
|
||||
function isValidIdCommitment(uint256 idCommitment) public pure returns (bool) {
|
||||
return idCommitment != 0 && idCommitment < Q;
|
||||
}
|
||||
|
||||
/// @notice Returns the rateCommitment of a member
|
||||
/// @param index The index of the member
|
||||
/// @return The rateCommitment of the member
|
||||
function indexToCommitment(uint32 index) internal view returns (uint256) {
|
||||
return imtData.elements[LazyIMT.indexForElement(0, index)];
|
||||
/// @notice Returns the rateCommitment of a membership at a given index
|
||||
/// @param index The index of the membership in the membership set
|
||||
/// @return The rateCommitment of the membership
|
||||
function getRateCommmitment(uint32 index) internal view returns (uint256) {
|
||||
return merkleTree.elements[LazyIMT.indexForElement(0, index)];
|
||||
}
|
||||
|
||||
/// @notice Returns the metadata of a member
|
||||
/// @param idCommitment The idCommitment of the member
|
||||
/// @return The metadata of the member (userMessageLimit, index, rateCommitment)
|
||||
function idCommitmentToMetadata(uint256 idCommitment) public view returns (uint32, uint32, uint256) {
|
||||
MembershipInfo memory mdetails = members[idCommitment];
|
||||
// we cannot call indexToCommitment for 0 index if the member doesn't exist
|
||||
if (mdetails.userMessageLimit == 0) {
|
||||
/// @notice Returns the membership info (rate limit, index, rateCommitment) by its idCommitment
|
||||
/// @param idCommitment The idCommitment of the membership
|
||||
/// @return The membership info (rateLimit, index, rateCommitment)
|
||||
function getMembershipInfo(uint256 idCommitment) public view returns (uint32, uint32, uint256) {
|
||||
MembershipInfo memory membership = memberships[idCommitment];
|
||||
// we cannot call getRateCommmitment for 0 index if the membership doesn't exist
|
||||
if (membership.rateLimit == 0) {
|
||||
return (0, 0, 0);
|
||||
}
|
||||
return (mdetails.userMessageLimit, mdetails.index, indexToCommitment(mdetails.index));
|
||||
return (membership.rateLimit, membership.index, getRateCommmitment(membership.index));
|
||||
}
|
||||
|
||||
/// @notice Checks if a member exists
|
||||
/// @param idCommitment The idCommitment of the member
|
||||
/// @return true if the member exists, false otherwise
|
||||
function memberExists(uint256 idCommitment) public view returns (bool) {
|
||||
(,, uint256 rateCommitment) = idCommitmentToMetadata(idCommitment);
|
||||
/// @notice Checks if a membership exists
|
||||
/// @param idCommitment The idCommitment of the membership
|
||||
/// @return true if the membership exists, false otherwise
|
||||
function membershipExists(uint256 idCommitment) public view returns (bool) {
|
||||
(,, uint256 rateCommitment) = getMembershipInfo(idCommitment);
|
||||
return rateCommitment != 0;
|
||||
}
|
||||
|
||||
/// @notice Allows a user to register as a member
|
||||
/// @param idCommitment The idCommitment of the member
|
||||
/// @param userMessageLimit The message limit of the member
|
||||
function register(uint256 idCommitment, uint32 userMessageLimit) external onlyValidIdCommitment(idCommitment) {
|
||||
if (memberExists(idCommitment)) revert DuplicateIdCommitment();
|
||||
/// @notice Register a membership
|
||||
/// @param idCommitment The idCommitment of the new membership
|
||||
/// @param rateLimit The rate limit of the new membership
|
||||
function register(uint256 idCommitment, uint32 rateLimit) external onlyValidIdCommitment(idCommitment) {
|
||||
if (membershipExists(idCommitment)) revert DuplicateIdCommitment();
|
||||
|
||||
uint32 index;
|
||||
bool reusedIndex;
|
||||
(index, reusedIndex) = _acquireMembership(_msgSender(), idCommitment, userMessageLimit);
|
||||
bool reuseIndex;
|
||||
(index, reuseIndex) = _acquireMembership(_msgSender(), idCommitment, rateLimit);
|
||||
|
||||
_register(idCommitment, userMessageLimit, index, reusedIndex);
|
||||
_register(idCommitment, rateLimit, index, reuseIndex);
|
||||
}
|
||||
|
||||
/// @notice Allows a user to register as a member
|
||||
/// @param idCommitment The idCommitment of the member
|
||||
/// @param userMessageLimit The message limit of the member
|
||||
/// @param membershipsToErase List of expired idCommitments to erase
|
||||
/// @notice Register a membership
|
||||
/// @param idCommitment The idCommitment of the new membership
|
||||
/// @param rateLimit The rate limit of the new membership
|
||||
/// @param idCommitmentsToErase List of idCommitments of expired memberships to erase
|
||||
function register(
|
||||
uint256 idCommitment,
|
||||
uint32 userMessageLimit,
|
||||
uint256[] calldata membershipsToErase
|
||||
uint32 rateLimit,
|
||||
uint256[] calldata idCommitmentsToErase
|
||||
)
|
||||
external
|
||||
onlyValidIdCommitment(idCommitment)
|
||||
{
|
||||
if (memberExists(idCommitment)) revert DuplicateIdCommitment();
|
||||
if (membershipExists(idCommitment)) revert DuplicateIdCommitment();
|
||||
|
||||
for (uint256 i = 0; i < membershipsToErase.length; i++) {
|
||||
uint256 idCommitmentToErase = membershipsToErase[i];
|
||||
MembershipInfo memory mdetails = members[idCommitmentToErase];
|
||||
if (mdetails.userMessageLimit == 0) revert InvalidIdCommitment(idCommitmentToErase);
|
||||
_eraseMembership(_msgSender(), idCommitmentToErase, mdetails);
|
||||
LazyIMT.update(imtData, 0, mdetails.index);
|
||||
for (uint256 i = 0; i < idCommitmentsToErase.length; i++) {
|
||||
uint256 idCommitmentToErase = idCommitmentsToErase[i];
|
||||
MembershipInfo memory membershipToErase = memberships[idCommitmentToErase];
|
||||
if (membershipToErase.rateLimit == 0) revert InvalidIdCommitment(idCommitmentToErase);
|
||||
_eraseMembership(_msgSender(), idCommitmentToErase, membershipToErase);
|
||||
LazyIMT.update(merkleTree, 0, membershipToErase.index);
|
||||
}
|
||||
|
||||
uint32 index;
|
||||
bool reusedIndex;
|
||||
(index, reusedIndex) = _acquireMembership(_msgSender(), idCommitment, userMessageLimit);
|
||||
bool reuseIndex;
|
||||
(index, reuseIndex) = _acquireMembership(_msgSender(), idCommitment, rateLimit);
|
||||
|
||||
_register(idCommitment, userMessageLimit, index, reusedIndex);
|
||||
_register(idCommitment, rateLimit, index, reuseIndex);
|
||||
}
|
||||
|
||||
/// @dev Registers a member
|
||||
/// @param idCommitment The idCommitment of the member
|
||||
/// @param userMessageLimit The message limit of the member
|
||||
/// @param index Indicates the index in the merkle tree
|
||||
/// @param reusedIndex indicates whether we're inserting a new element in the merkle tree or updating a existing
|
||||
/// leaf
|
||||
function _register(uint256 idCommitment, uint32 userMessageLimit, uint32 index, bool reusedIndex) internal {
|
||||
if (nextCommitmentIndex >= SET_SIZE) revert FullTree();
|
||||
/// @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
|
||||
/// element
|
||||
function _register(uint256 idCommitment, uint32 rateLimit, uint32 index, bool reuseIndex) internal {
|
||||
if (nextFreeIndex >= MAX_MEMBERSHIP_SET_SIZE) revert FullMembershipSet();
|
||||
|
||||
uint256 rateCommitment = PoseidonT3.hash([idCommitment, userMessageLimit]);
|
||||
if (reusedIndex) {
|
||||
LazyIMT.update(imtData, rateCommitment, index);
|
||||
uint256 rateCommitment = PoseidonT3.hash([idCommitment, rateLimit]);
|
||||
if (reuseIndex) {
|
||||
LazyIMT.update(merkleTree, rateCommitment, index);
|
||||
} else {
|
||||
LazyIMT.insert(imtData, rateCommitment);
|
||||
nextCommitmentIndex += 1;
|
||||
LazyIMT.insert(merkleTree, rateCommitment);
|
||||
nextFreeIndex += 1;
|
||||
}
|
||||
|
||||
emit MemberRegistered(rateCommitment, index);
|
||||
emit MembershipRegistered(rateCommitment, index);
|
||||
}
|
||||
|
||||
/// @notice Returns the commitments of a range of members
|
||||
/// @param startIndex The start index of the range
|
||||
/// @param endIndex The end index of the range
|
||||
/// @return The commitments of the members
|
||||
function getCommitments(uint32 startIndex, uint32 endIndex) public view returns (uint256[] memory) {
|
||||
/// @notice Returns the rateCommitments of memberships within an index range
|
||||
/// @param startIndex The start index of the range (inclusive)
|
||||
/// @param endIndex The end index of the range (inclusive)
|
||||
/// @return The rateCommitments of the memberships
|
||||
function getRateCommitmentsInRange(uint32 startIndex, uint32 endIndex) public view returns (uint256[] memory) {
|
||||
if (startIndex > endIndex) revert InvalidPaginationQuery(startIndex, endIndex);
|
||||
if (endIndex > nextCommitmentIndex) revert InvalidPaginationQuery(startIndex, endIndex);
|
||||
if (endIndex > nextFreeIndex) revert InvalidPaginationQuery(startIndex, endIndex); //FIXME: should it be >=?
|
||||
|
||||
uint256[] memory commitments = new uint256[](endIndex - startIndex + 1);
|
||||
uint256[] memory rateCommitments = new uint256[](endIndex - startIndex + 1);
|
||||
for (uint32 i = startIndex; i <= endIndex; i++) {
|
||||
commitments[i - startIndex] = indexToCommitment(i);
|
||||
rateCommitments[i - startIndex] = getRateCommmitment(i);
|
||||
}
|
||||
return commitments;
|
||||
return rateCommitments;
|
||||
}
|
||||
|
||||
/// @notice Returns the root of the IMT
|
||||
/// @return The root of the IMT
|
||||
/// @notice Returns the root of the Merkle tree that stores rate commitments of memberships
|
||||
/// @return The root of the Merkle tree that stores rate commitments of memberships
|
||||
function root() external view returns (uint256) {
|
||||
return LazyIMT.root(imtData, DEPTH);
|
||||
return LazyIMT.root(merkleTree, MERKLE_TREE_DEPTH);
|
||||
}
|
||||
|
||||
/// @notice Returns the merkle proof elements of a given membership
|
||||
/// @param index The index of the member
|
||||
/// @return The merkle proof elements of the member
|
||||
function merkleProofElements(uint40 index) public view returns (uint256[DEPTH] memory) {
|
||||
uint256[DEPTH] memory castedProof;
|
||||
uint256[] memory proof = LazyIMT.merkleProofElements(imtData, index, DEPTH);
|
||||
for (uint8 i = 0; i < DEPTH; i++) {
|
||||
castedProof[i] = proof[i];
|
||||
/// @notice Returns the Merkle proof that a given membership is in the membership set
|
||||
/// @param index The index of the membership
|
||||
/// @return The Merkle proof (an array of MERKLE_TREE_DEPTH elements)
|
||||
function getMerkleProof(uint40 index) public view returns (uint256[MERKLE_TREE_DEPTH] memory) {
|
||||
uint256[] memory dynamicSizeProof = LazyIMT.merkleProofElements(merkleTree, index, MERKLE_TREE_DEPTH);
|
||||
uint256[MERKLE_TREE_DEPTH] memory fixedSizeProof;
|
||||
for (uint8 i = 0; i < MERKLE_TREE_DEPTH; i++) {
|
||||
fixedSizeProof[i] = dynamicSizeProof[i];
|
||||
}
|
||||
return castedProof;
|
||||
return fixedSizeProof;
|
||||
}
|
||||
|
||||
/// @notice Extend a membership expiration date. Memberships must be on grace period
|
||||
/// @param idCommitments list of idcommitments
|
||||
function extend(uint256[] calldata idCommitments) external {
|
||||
/// @notice Extend a grace-period membership
|
||||
/// @param idCommitments list of idCommitments of memberships to extend
|
||||
function extendMemberships(uint256[] calldata idCommitments) external {
|
||||
for (uint256 i = 0; i < idCommitments.length; i++) {
|
||||
uint256 idCommitment = idCommitments[i];
|
||||
_extendMembership(_msgSender(), idCommitment);
|
||||
uint256 idCommitmentToExtend = idCommitments[i];
|
||||
_extendMembership(_msgSender(), idCommitmentToExtend);
|
||||
}
|
||||
}
|
||||
|
||||
/// @notice Remove expired memberships or owned memberships in grace period.
|
||||
/// The user can determine offchain which expired memberships slots
|
||||
/// are available, and proceed to free them.
|
||||
/// This is also used to erase memberships in grace period if they're
|
||||
/// held by the sender. The sender can then withdraw the tokens.
|
||||
/// @param idCommitments list of idcommitments of the memberships
|
||||
/// @notice Erase expired memberships or owned grace-period memberships
|
||||
/// The user can select expired memberships offchain,
|
||||
/// and proceed to erase them.
|
||||
/// This function is also used to erase the user's own grace-period memberships.
|
||||
/// 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++) {
|
||||
uint256 idCommitment = idCommitments[i];
|
||||
MembershipInfo memory mdetails = members[idCommitment];
|
||||
if (mdetails.userMessageLimit == 0) revert InvalidIdCommitment(idCommitment);
|
||||
_eraseMembership(_msgSender(), idCommitment, mdetails);
|
||||
LazyIMT.update(imtData, 0, mdetails.index);
|
||||
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);
|
||||
_eraseMembership(_msgSender(), idCommitmentToErase, membershipToErase);
|
||||
LazyIMT.update(merkleTree, 0, membershipToErase.index);
|
||||
}
|
||||
}
|
||||
|
||||
/// @notice Withdraw any available balance in tokens after a membership is erased.
|
||||
/// @notice Withdraw any available deposit balance in tokens after a membership is erased.
|
||||
/// @param token The address of the token to withdraw. Use 0x000...000 to withdraw ETH
|
||||
function withdraw(address token) external {
|
||||
_withdraw(_msgSender(), token);
|
||||
@ -262,37 +262,37 @@ contract WakuRlnV2 is Initializable, Ownable2StepUpgradeable, UUPSUpgradeable, M
|
||||
priceCalculator = IPriceCalculator(_priceCalculator);
|
||||
}
|
||||
|
||||
/// @notice Set the maximum total rate limit of all memberships in the tree
|
||||
/// @param _maxTotalRateLimitPerEpoch new value
|
||||
function setMaxTotalRateLimitPerEpoch(uint32 _maxTotalRateLimitPerEpoch) external onlyOwner {
|
||||
require(_maxTotalRateLimitPerEpoch >= maxRateLimitPerMembership);
|
||||
maxTotalRateLimitPerEpoch = _maxTotalRateLimitPerEpoch;
|
||||
/// @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);
|
||||
maxTotalRateLimit = _maxTotalRateLimit;
|
||||
}
|
||||
|
||||
/// @notice Set the maximum rate limit of one membership
|
||||
/// @param _maxRateLimitPerMembership new value
|
||||
/// @param _maxRateLimitPerMembership new maximum rate limit per membership (messages per epoch)
|
||||
function setMaxRateLimitPerMembership(uint32 _maxRateLimitPerMembership) external onlyOwner {
|
||||
require(_maxRateLimitPerMembership >= minRateLimitPerMembership);
|
||||
maxRateLimitPerMembership = _maxRateLimitPerMembership;
|
||||
}
|
||||
|
||||
/// @notice Set the minimum rate limit of one membership
|
||||
/// @param _minRateLimitPerMembership new value
|
||||
/// @param _minRateLimitPerMembership new minimum rate limit per membership (messages per epoch)
|
||||
function setMinRateLimitPerMembership(uint32 _minRateLimitPerMembership) external onlyOwner {
|
||||
require(_minRateLimitPerMembership > 0);
|
||||
require(_minRateLimitPerMembership > 0); // FIXME: we must also check here that min rate <= max rate
|
||||
minRateLimitPerMembership = _minRateLimitPerMembership;
|
||||
}
|
||||
|
||||
/// @notice Set the membership expiration term
|
||||
/// @param _expirationTerm new value
|
||||
/// @notice Set the expiration term for new memberships (expiration dates of existing memberships don't change)
|
||||
/// @param _expirationTerm new expiration term
|
||||
function setExpirationTerm(uint32 _expirationTerm) external onlyOwner {
|
||||
require(_expirationTerm > 0);
|
||||
expirationTerm = _expirationTerm;
|
||||
}
|
||||
|
||||
/// @notice Set the membership grace period
|
||||
/// @param _gracePeriod new value
|
||||
function setGracePeriod(uint32 _gracePeriod) external onlyOwner {
|
||||
/// @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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,16 +40,16 @@ contract WakuRlnV2Test is Test {
|
||||
w.setMinRateLimitPerMembership(2);
|
||||
|
||||
uint256 idCommitment = 2;
|
||||
uint32 userMessageLimit = 2;
|
||||
(, uint256 price) = w.priceCalculator().calculate(userMessageLimit);
|
||||
uint32 membershipRateLimit = 2;
|
||||
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
|
||||
vm.resumeGasMetering();
|
||||
token.approve(address(w), price);
|
||||
w.register(idCommitment, userMessageLimit);
|
||||
w.register(idCommitment, membershipRateLimit);
|
||||
vm.pauseGasMetering();
|
||||
assertEq(w.nextCommitmentIndex(), 1);
|
||||
assertEq(w.memberExists(idCommitment), true);
|
||||
(,,, uint32 fetchedUserMessageLimit, uint32 index, address holder,) = w.members(idCommitment);
|
||||
assertEq(fetchedUserMessageLimit, userMessageLimit);
|
||||
assertEq(w.nextFreeIndex(), 1);
|
||||
assertEq(w.membershipExists(idCommitment), true);
|
||||
(,,, uint32 fetchedMembershipRateLimit, uint32 index, address holder,) = w.memberships(idCommitment);
|
||||
assertEq(fetchedMembershipRateLimit, membershipRateLimit);
|
||||
assertEq(holder, address(this));
|
||||
assertEq(index, 0);
|
||||
// kats from zerokit
|
||||
@ -59,12 +59,12 @@ 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 fetchedUserMessageLimit2, uint32 index2, uint256 rateCommitment2) =
|
||||
w.idCommitmentToMetadata(idCommitment);
|
||||
assertEq(fetchedUserMessageLimit2, userMessageLimit);
|
||||
(uint32 fetchedMembershipRateLimit2, uint32 index2, uint256 rateCommitment2) =
|
||||
w.getMembershipInfo(idCommitment);
|
||||
assertEq(fetchedMembershipRateLimit2, membershipRateLimit);
|
||||
assertEq(index2, 0);
|
||||
assertEq(rateCommitment2, rateCommitment);
|
||||
uint256[20] memory proof = w.merkleProofElements(0);
|
||||
uint256[20] memory proof = w.getMerkleProof(0);
|
||||
uint256[20] memory expectedProof = [
|
||||
0,
|
||||
14_744_269_619_966_411_208_579_211_824_598_458_697_587_494_354_926_760_081_771_325_075_741_142_829_156,
|
||||
@ -93,58 +93,58 @@ contract WakuRlnV2Test is Test {
|
||||
vm.resumeGasMetering();
|
||||
}
|
||||
|
||||
function test__ValidRegistration(uint32 userMessageLimit) external {
|
||||
function test__ValidRegistration(uint32 membershipRateLimit) external {
|
||||
vm.pauseGasMetering();
|
||||
uint256 idCommitment = 2;
|
||||
(, uint256 price) = w.priceCalculator().calculate(userMessageLimit);
|
||||
uint256 minUserMessageLimit = w.minRateLimitPerMembership();
|
||||
uint256 maxUserMessageLimit = w.maxRateLimitPerMembership();
|
||||
vm.assume(userMessageLimit >= minUserMessageLimit && userMessageLimit <= maxUserMessageLimit);
|
||||
vm.assume(w.isValidUserMessageLimit(userMessageLimit));
|
||||
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
|
||||
uint256 minMembershipRateLimit = w.minRateLimitPerMembership();
|
||||
uint256 maxMembershipRateLimit = w.maxRateLimitPerMembership();
|
||||
vm.assume(membershipRateLimit >= minMembershipRateLimit && membershipRateLimit <= maxMembershipRateLimit);
|
||||
vm.assume(w.isValidMembershipRateLimit(membershipRateLimit));
|
||||
vm.resumeGasMetering();
|
||||
|
||||
assertEq(w.memberExists(idCommitment), false);
|
||||
assertEq(w.membershipExists(idCommitment), false);
|
||||
token.approve(address(w), price);
|
||||
w.register(idCommitment, userMessageLimit);
|
||||
uint256 rateCommitment = PoseidonT3.hash([idCommitment, userMessageLimit]);
|
||||
w.register(idCommitment, membershipRateLimit);
|
||||
uint256 rateCommitment = PoseidonT3.hash([idCommitment, membershipRateLimit]);
|
||||
|
||||
(uint32 fetchedUserMessageLimit, uint32 index, uint256 fetchedRateCommitment) =
|
||||
w.idCommitmentToMetadata(idCommitment);
|
||||
assertEq(fetchedUserMessageLimit, userMessageLimit);
|
||||
(uint32 fetchedMembershipRateLimit, uint32 index, uint256 fetchedRateCommitment) =
|
||||
w.getMembershipInfo(idCommitment);
|
||||
assertEq(fetchedMembershipRateLimit, membershipRateLimit);
|
||||
assertEq(index, 0);
|
||||
assertEq(fetchedRateCommitment, rateCommitment);
|
||||
|
||||
assertEq(token.balanceOf(address(w)), price);
|
||||
assertEq(w.totalRateLimitPerEpoch(), userMessageLimit);
|
||||
assertEq(w.totalRateLimitPerEpoch(), membershipRateLimit);
|
||||
}
|
||||
|
||||
function test__LinearPriceCalculation(uint32 userMessageLimit) external view {
|
||||
function test__LinearPriceCalculation(uint32 membershipRateLimit) external view {
|
||||
IPriceCalculator priceCalculator = w.priceCalculator();
|
||||
uint256 pricePerMessagePerPeriod = LinearPriceCalculator(address(priceCalculator)).pricePerMessagePerEpoch();
|
||||
assertNotEq(pricePerMessagePerPeriod, 0);
|
||||
uint256 expectedPrice = uint256(userMessageLimit) * pricePerMessagePerPeriod;
|
||||
(, uint256 price) = w.priceCalculator().calculate(userMessageLimit);
|
||||
uint256 expectedPrice = uint256(membershipRateLimit) * pricePerMessagePerPeriod;
|
||||
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
|
||||
assertEq(price, expectedPrice);
|
||||
}
|
||||
|
||||
function test__InvalidTokenAmount(uint256 idCommitment, uint32 userMessageLimit) external {
|
||||
function test__InvalidTokenAmount(uint256 idCommitment, uint32 membershipRateLimit) external {
|
||||
vm.pauseGasMetering();
|
||||
uint256 minUserMessageLimit = w.minRateLimitPerMembership();
|
||||
uint256 maxUserMessageLimit = w.maxRateLimitPerMembership();
|
||||
vm.assume(userMessageLimit >= minUserMessageLimit && userMessageLimit <= maxUserMessageLimit);
|
||||
vm.assume(w.isValidCommitment(idCommitment) && w.isValidUserMessageLimit(userMessageLimit));
|
||||
(, uint256 price) = w.priceCalculator().calculate(userMessageLimit);
|
||||
uint256 minMembershipRateLimit = w.minRateLimitPerMembership();
|
||||
uint256 maxMembershipRateLimit = w.maxRateLimitPerMembership();
|
||||
vm.assume(membershipRateLimit >= minMembershipRateLimit && membershipRateLimit <= maxMembershipRateLimit);
|
||||
vm.assume(w.isValidIdCommitment(idCommitment) && w.isValidMembershipRateLimit(membershipRateLimit));
|
||||
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
|
||||
vm.resumeGasMetering();
|
||||
|
||||
token.approve(address(w), price - 1);
|
||||
vm.expectRevert(bytes("ERC20: insufficient allowance"));
|
||||
w.register(idCommitment, userMessageLimit);
|
||||
w.register(idCommitment, membershipRateLimit);
|
||||
}
|
||||
|
||||
function test__IdCommitmentToMetadata__DoesntExist() external view {
|
||||
uint256 idCommitment = 2;
|
||||
(uint32 userMessageLimit, uint32 index, uint256 rateCommitment) = w.idCommitmentToMetadata(idCommitment);
|
||||
assertEq(userMessageLimit, 0);
|
||||
(uint32 membershipRateLimit, uint32 index, uint256 rateCommitment) = w.getMembershipInfo(idCommitment);
|
||||
assertEq(membershipRateLimit, 0);
|
||||
assertEq(index, 0);
|
||||
assertEq(rateCommitment, 0);
|
||||
}
|
||||
@ -152,25 +152,25 @@ contract WakuRlnV2Test is Test {
|
||||
function test__InvalidRegistration__InvalidIdCommitment__Zero() external {
|
||||
vm.pauseGasMetering();
|
||||
uint256 idCommitment = 0;
|
||||
uint32 userMessageLimit = 2;
|
||||
(, uint256 price) = w.priceCalculator().calculate(userMessageLimit);
|
||||
uint32 membershipRateLimit = 2;
|
||||
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
|
||||
vm.resumeGasMetering();
|
||||
|
||||
token.approve(address(w), price);
|
||||
vm.expectRevert(abi.encodeWithSelector(InvalidIdCommitment.selector, 0));
|
||||
w.register(idCommitment, userMessageLimit);
|
||||
w.register(idCommitment, membershipRateLimit);
|
||||
}
|
||||
|
||||
function test__InvalidRegistration__InvalidIdCommitment__LargerThanField() external {
|
||||
vm.pauseGasMetering();
|
||||
uint32 userMessageLimit = 20;
|
||||
(, uint256 price) = w.priceCalculator().calculate(userMessageLimit);
|
||||
uint32 membershipRateLimit = 20;
|
||||
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
|
||||
vm.resumeGasMetering();
|
||||
|
||||
uint256 idCommitment = w.Q() + 1;
|
||||
token.approve(address(w), price);
|
||||
vm.expectRevert(abi.encodeWithSelector(InvalidIdCommitment.selector, idCommitment));
|
||||
w.register(idCommitment, userMessageLimit);
|
||||
w.register(idCommitment, membershipRateLimit);
|
||||
}
|
||||
|
||||
function test__InvalidRegistration__InvalidUserMessageLimit__MinMax() external {
|
||||
@ -186,19 +186,19 @@ contract WakuRlnV2Test is Test {
|
||||
w.register(idCommitment, invalidMax);
|
||||
}
|
||||
|
||||
function test__ValidRegistrationExtend(uint32 userMessageLimit) external {
|
||||
function test__ValidRegistrationExtend(uint32 membershipRateLimit) external {
|
||||
vm.pauseGasMetering();
|
||||
uint256 idCommitment = 2;
|
||||
(, uint256 price) = w.priceCalculator().calculate(userMessageLimit);
|
||||
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
|
||||
vm.assume(
|
||||
userMessageLimit >= w.minRateLimitPerMembership() && userMessageLimit <= w.maxRateLimitPerMembership()
|
||||
membershipRateLimit >= w.minRateLimitPerMembership() && membershipRateLimit <= w.maxRateLimitPerMembership()
|
||||
);
|
||||
vm.assume(w.isValidUserMessageLimit(userMessageLimit));
|
||||
vm.assume(w.isValidMembershipRateLimit(membershipRateLimit));
|
||||
vm.resumeGasMetering();
|
||||
|
||||
token.approve(address(w), price);
|
||||
w.register(idCommitment, userMessageLimit);
|
||||
(, uint256 gracePeriodStartDate,,,,,) = w.members(idCommitment);
|
||||
w.register(idCommitment, membershipRateLimit);
|
||||
(, uint256 gracePeriodStartDate,,,,,) = w.memberships(idCommitment);
|
||||
|
||||
assertFalse(w.isGracePeriod(idCommitment));
|
||||
assertFalse(w.isExpired(idCommitment));
|
||||
@ -215,14 +215,14 @@ contract WakuRlnV2Test is Test {
|
||||
address randomAddress = vm.addr(block.timestamp);
|
||||
vm.prank(randomAddress);
|
||||
vm.expectRevert(abi.encodeWithSelector(NotHolder.selector, commitmentsToExtend[0]));
|
||||
w.extend(commitmentsToExtend);
|
||||
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);
|
||||
w.extend(commitmentsToExtend);
|
||||
w.extendMemberships(commitmentsToExtend);
|
||||
|
||||
(, uint256 newGracePeriodStartDate,,,,,) = w.members(idCommitment);
|
||||
(, uint256 newGracePeriodStartDate,,,,,) = w.memberships(idCommitment);
|
||||
|
||||
assertEq(block.timestamp + uint256(w.expirationTerm()), newGracePeriodStartDate);
|
||||
assertFalse(w.isGracePeriod(idCommitment));
|
||||
@ -230,26 +230,26 @@ contract WakuRlnV2Test is Test {
|
||||
|
||||
// Attempt to extend a non grace period membership
|
||||
token.approve(address(w), price);
|
||||
w.register(idCommitment + 1, userMessageLimit);
|
||||
w.register(idCommitment + 1, membershipRateLimit);
|
||||
commitmentsToExtend[0] = idCommitment + 1;
|
||||
vm.expectRevert(abi.encodeWithSelector(NotInGracePeriod.selector, commitmentsToExtend[0]));
|
||||
w.extend(commitmentsToExtend);
|
||||
w.extendMemberships(commitmentsToExtend);
|
||||
}
|
||||
|
||||
function test__ValidRegistrationExtendSingleMembership(uint32 userMessageLimit) external {
|
||||
function test__ValidRegistrationExtendSingleMembership(uint32 membershipRateLimit) external {
|
||||
vm.pauseGasMetering();
|
||||
uint256 idCommitment = 2;
|
||||
(, uint256 price) = w.priceCalculator().calculate(userMessageLimit);
|
||||
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
|
||||
vm.assume(
|
||||
userMessageLimit >= w.minRateLimitPerMembership() && userMessageLimit <= w.maxRateLimitPerMembership()
|
||||
membershipRateLimit >= w.minRateLimitPerMembership() && membershipRateLimit <= w.maxRateLimitPerMembership()
|
||||
);
|
||||
vm.assume(w.isValidUserMessageLimit(userMessageLimit));
|
||||
vm.assume(w.isValidMembershipRateLimit(membershipRateLimit));
|
||||
vm.resumeGasMetering();
|
||||
|
||||
token.approve(address(w), price);
|
||||
w.register(idCommitment, userMessageLimit);
|
||||
w.register(idCommitment, membershipRateLimit);
|
||||
uint256 ogExpirationDate = w.expirationDate(idCommitment);
|
||||
(, uint256 gracePeriodStartDate,,,,,) = w.members(idCommitment);
|
||||
(, uint256 gracePeriodStartDate,,,,,) = w.memberships(idCommitment);
|
||||
|
||||
vm.warp(gracePeriodStartDate);
|
||||
|
||||
@ -259,29 +259,29 @@ contract WakuRlnV2Test is Test {
|
||||
// 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);
|
||||
w.extend(commitmentsToExtend);
|
||||
w.extendMemberships(commitmentsToExtend);
|
||||
|
||||
(, uint256 newGracePeriodStartDate, uint32 newGracePeriod,,,,) = w.members(idCommitment);
|
||||
(, uint256 newGracePeriodStartDate, uint32 newGracePeriod,,,,) = w.memberships(idCommitment);
|
||||
uint256 expectedExpirationDate = newGracePeriodStartDate + uint256(newGracePeriod) + 1;
|
||||
uint256 expirationDate = w.expirationDate(idCommitment);
|
||||
assertEq(expectedExpirationDate, expirationDate);
|
||||
assertTrue(expectedExpirationDate > ogExpirationDate);
|
||||
}
|
||||
|
||||
function test__ValidRegistrationExpiry(uint32 userMessageLimit) external {
|
||||
function test__ValidRegistrationExpiry(uint32 membershipRateLimit) external {
|
||||
vm.pauseGasMetering();
|
||||
uint256 idCommitment = 2;
|
||||
(, uint256 price) = w.priceCalculator().calculate(userMessageLimit);
|
||||
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
|
||||
vm.assume(
|
||||
userMessageLimit >= w.minRateLimitPerMembership() && userMessageLimit <= w.maxRateLimitPerMembership()
|
||||
membershipRateLimit >= w.minRateLimitPerMembership() && membershipRateLimit <= w.maxRateLimitPerMembership()
|
||||
);
|
||||
vm.assume(w.isValidUserMessageLimit(userMessageLimit));
|
||||
vm.assume(w.isValidMembershipRateLimit(membershipRateLimit));
|
||||
vm.resumeGasMetering();
|
||||
|
||||
token.approve(address(w), price);
|
||||
w.register(idCommitment, userMessageLimit);
|
||||
w.register(idCommitment, membershipRateLimit);
|
||||
|
||||
(, uint256 fetchedGracePeriodStartDate, uint32 fetchedGracePeriod,,,,) = w.members(idCommitment);
|
||||
(, uint256 fetchedGracePeriodStartDate, uint32 fetchedGracePeriod,,,,) = w.memberships(idCommitment);
|
||||
|
||||
uint256 expectedExpirationDate = fetchedGracePeriodStartDate + uint256(fetchedGracePeriod) + 1;
|
||||
uint256 expirationDate = w.expirationDate(idCommitment);
|
||||
@ -299,7 +299,7 @@ contract WakuRlnV2Test is Test {
|
||||
vm.startPrank(w.owner());
|
||||
w.setMinRateLimitPerMembership(20);
|
||||
w.setMaxRateLimitPerMembership(100);
|
||||
w.setMaxTotalRateLimitPerEpoch(100);
|
||||
w.setmaxTotalRateLimit(100);
|
||||
vm.stopPrank();
|
||||
vm.resumeGasMetering();
|
||||
|
||||
@ -312,8 +312,8 @@ contract WakuRlnV2Test is Test {
|
||||
vm.warp(w.expirationDate(i));
|
||||
}
|
||||
|
||||
// Time travel to a point in which the last commitment is active
|
||||
(, uint256 gracePeriodStartDate,,,,,) = w.members(5);
|
||||
// Time travel to a point in which the last membership is active
|
||||
(, uint256 gracePeriodStartDate,,,,,) = w.memberships(5);
|
||||
vm.warp(gracePeriodStartDate - 1);
|
||||
|
||||
// Ensure that this is the case
|
||||
@ -349,17 +349,17 @@ contract WakuRlnV2Test is Test {
|
||||
|
||||
// Ensure that the chosen memberships were erased and others unaffected
|
||||
address holder;
|
||||
(,,,,, holder,) = w.members(1);
|
||||
(,,,,, holder,) = w.memberships(1);
|
||||
assertEq(holder, address(0));
|
||||
(,,,,, holder,) = w.members(2);
|
||||
(,,,,, holder,) = w.memberships(2);
|
||||
assertEq(holder, address(0));
|
||||
(,,,,, holder,) = w.members(3);
|
||||
(,,,,, holder,) = w.memberships(3);
|
||||
assertEq(holder, address(this));
|
||||
(,,,,, holder,) = w.members(4);
|
||||
(,,,,, holder,) = w.memberships(4);
|
||||
assertEq(holder, address(0));
|
||||
(,,,,, holder,) = w.members(5);
|
||||
(,,,,, holder,) = w.memberships(5);
|
||||
assertEq(holder, address(this));
|
||||
(,,,,, holder,) = w.members(6);
|
||||
(,,,,, holder,) = w.memberships(6);
|
||||
assertEq(holder, address(this));
|
||||
|
||||
// The balance available for withdrawal should match the amount of the expired membership
|
||||
@ -372,45 +372,45 @@ contract WakuRlnV2Test is Test {
|
||||
vm.startPrank(w.owner());
|
||||
w.setMinRateLimitPerMembership(1);
|
||||
w.setMaxRateLimitPerMembership(5);
|
||||
w.setMaxTotalRateLimitPerEpoch(5);
|
||||
w.setmaxTotalRateLimit(5);
|
||||
vm.stopPrank();
|
||||
vm.resumeGasMetering();
|
||||
|
||||
bool isValid = w.isValidUserMessageLimit(6);
|
||||
bool isValid = w.isValidMembershipRateLimit(6);
|
||||
assertFalse(isValid);
|
||||
|
||||
// Exceeds the max rate limit per user
|
||||
uint32 userMessageLimit = 10;
|
||||
(, uint256 price) = w.priceCalculator().calculate(userMessageLimit);
|
||||
uint32 membershipRateLimit = 10;
|
||||
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
|
||||
token.approve(address(w), price);
|
||||
vm.expectRevert(abi.encodeWithSelector(InvalidRateLimit.selector));
|
||||
w.register(1, userMessageLimit);
|
||||
w.register(1, membershipRateLimit);
|
||||
|
||||
// Should register succesfully
|
||||
userMessageLimit = 4;
|
||||
(, price) = w.priceCalculator().calculate(userMessageLimit);
|
||||
membershipRateLimit = 4;
|
||||
(, price) = w.priceCalculator().calculate(membershipRateLimit);
|
||||
token.approve(address(w), price);
|
||||
w.register(2, userMessageLimit);
|
||||
w.register(2, membershipRateLimit);
|
||||
|
||||
// Exceeds the rate limit
|
||||
userMessageLimit = 2;
|
||||
(, price) = w.priceCalculator().calculate(userMessageLimit);
|
||||
membershipRateLimit = 2;
|
||||
(, price) = w.priceCalculator().calculate(membershipRateLimit);
|
||||
token.approve(address(w), price);
|
||||
vm.expectRevert(abi.encodeWithSelector(ExceedAvailableMaxRateLimitPerEpoch.selector));
|
||||
w.register(3, userMessageLimit);
|
||||
w.register(3, membershipRateLimit);
|
||||
|
||||
// Should register succesfully
|
||||
userMessageLimit = 1;
|
||||
(, price) = w.priceCalculator().calculate(userMessageLimit);
|
||||
membershipRateLimit = 1;
|
||||
(, price) = w.priceCalculator().calculate(membershipRateLimit);
|
||||
token.approve(address(w), price);
|
||||
w.register(3, userMessageLimit);
|
||||
w.register(3, membershipRateLimit);
|
||||
|
||||
// We ran out of rate limit again
|
||||
userMessageLimit = 1;
|
||||
(, price) = w.priceCalculator().calculate(userMessageLimit);
|
||||
membershipRateLimit = 1;
|
||||
(, price) = w.priceCalculator().calculate(membershipRateLimit);
|
||||
token.approve(address(w), price);
|
||||
vm.expectRevert(abi.encodeWithSelector(ExceedAvailableMaxRateLimitPerEpoch.selector));
|
||||
w.register(4, userMessageLimit);
|
||||
w.register(4, membershipRateLimit);
|
||||
}
|
||||
|
||||
function test__indexReuse_eraseMemberships(uint32 idCommitmentsLength) external {
|
||||
@ -422,8 +422,8 @@ contract WakuRlnV2Test is Test {
|
||||
for (uint256 i = 1; i <= idCommitmentsLength; i++) {
|
||||
token.approve(address(w), price);
|
||||
w.register(i, 20);
|
||||
(,,,, index,,) = w.members(i);
|
||||
assertEq(index, w.nextCommitmentIndex() - 1);
|
||||
(,,,, index,,) = w.memberships(i);
|
||||
assertEq(index, w.nextFreeIndex() - 1);
|
||||
commitmentsToErase[i - 1] = i;
|
||||
}
|
||||
|
||||
@ -437,20 +437,20 @@ contract WakuRlnV2Test is Test {
|
||||
assertEq(i, w.availableExpiredIndices(i));
|
||||
}
|
||||
|
||||
uint32 currnextCommitmentIndex = w.nextCommitmentIndex();
|
||||
uint32 currnextCommitmentIndex = w.nextFreeIndex();
|
||||
for (uint256 i = 1; i <= idCommitmentsLength; i++) {
|
||||
uint256 idCommitment = i + 10;
|
||||
uint256 expectedReusedIndexPos = idCommitmentsLength - i;
|
||||
uint32 expectedIndex = w.availableExpiredIndices(expectedReusedIndexPos);
|
||||
token.approve(address(w), price);
|
||||
w.register(idCommitment, 20);
|
||||
(,,,, index,,) = w.members(idCommitment);
|
||||
(,,,, index,,) = w.memberships(idCommitment);
|
||||
assertEq(expectedIndex, index);
|
||||
// Should have been removed from the list
|
||||
vm.expectRevert();
|
||||
w.availableExpiredIndices(expectedReusedIndexPos);
|
||||
// Should not have been affected
|
||||
assertEq(currnextCommitmentIndex, w.nextCommitmentIndex());
|
||||
assertEq(currnextCommitmentIndex, w.nextFreeIndex());
|
||||
}
|
||||
|
||||
// No indexes should be available for reuse
|
||||
@ -460,25 +460,25 @@ contract WakuRlnV2Test is Test {
|
||||
// Should use a new index since we got rid of all available indexes
|
||||
token.approve(address(w), price);
|
||||
w.register(100, 20);
|
||||
(,,,, index,,) = w.members(100);
|
||||
(,,,, index,,) = w.memberships(100);
|
||||
assertEq(index, currnextCommitmentIndex);
|
||||
assertEq(currnextCommitmentIndex + 1, w.nextCommitmentIndex());
|
||||
assertEq(currnextCommitmentIndex + 1, w.nextFreeIndex());
|
||||
}
|
||||
|
||||
function test__RemoveExpiredMemberships(uint32 userMessageLimit) external {
|
||||
function test__RemoveExpiredMemberships(uint32 membershipRateLimit) external {
|
||||
vm.pauseGasMetering();
|
||||
uint256 idCommitment = 2;
|
||||
(, uint256 price) = w.priceCalculator().calculate(userMessageLimit);
|
||||
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
|
||||
vm.assume(
|
||||
userMessageLimit >= w.minRateLimitPerMembership() && userMessageLimit <= w.maxRateLimitPerMembership()
|
||||
membershipRateLimit >= w.minRateLimitPerMembership() && membershipRateLimit <= w.maxRateLimitPerMembership()
|
||||
);
|
||||
vm.assume(w.isValidUserMessageLimit(userMessageLimit));
|
||||
vm.assume(w.isValidMembershipRateLimit(membershipRateLimit));
|
||||
vm.resumeGasMetering();
|
||||
|
||||
uint256 time = block.timestamp;
|
||||
for (uint256 i = 0; i < 5; i++) {
|
||||
token.approve(address(w), price);
|
||||
w.register(idCommitment + i, userMessageLimit);
|
||||
w.register(idCommitment + i, membershipRateLimit);
|
||||
time += 100;
|
||||
vm.warp(time);
|
||||
}
|
||||
@ -506,15 +506,15 @@ contract WakuRlnV2Test is Test {
|
||||
|
||||
address holder;
|
||||
|
||||
(,,,,, holder,) = w.members(idCommitment + 1);
|
||||
(,,,,, holder,) = w.memberships(idCommitment + 1);
|
||||
assertEq(holder, address(0));
|
||||
|
||||
(,,,,, holder,) = w.members(idCommitment + 2);
|
||||
(,,,,, holder,) = w.memberships(idCommitment + 2);
|
||||
assertEq(holder, address(0));
|
||||
|
||||
// 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.members(idCommitment + 4);
|
||||
(, uint256 gracePeriodStartDate,,,,,) = w.memberships(idCommitment + 4);
|
||||
vm.warp(gracePeriodStartDate - 1);
|
||||
commitmentsToErase[0] = idCommitment;
|
||||
commitmentsToErase[1] = idCommitment + 4;
|
||||
@ -525,14 +525,14 @@ contract WakuRlnV2Test is Test {
|
||||
function test__RemoveAllExpiredMemberships(uint32 idCommitmentsLength) external {
|
||||
vm.pauseGasMetering();
|
||||
vm.assume(idCommitmentsLength > 1 && idCommitmentsLength <= 100);
|
||||
uint32 userMessageLimit = w.minRateLimitPerMembership();
|
||||
(, uint256 price) = w.priceCalculator().calculate(userMessageLimit);
|
||||
uint32 membershipRateLimit = w.minRateLimitPerMembership();
|
||||
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
|
||||
vm.resumeGasMetering();
|
||||
|
||||
uint256 time = block.timestamp;
|
||||
for (uint256 i = 1; i <= idCommitmentsLength; i++) {
|
||||
token.approve(address(w), price);
|
||||
w.register(i, userMessageLimit);
|
||||
w.register(i, membershipRateLimit);
|
||||
time += 100;
|
||||
vm.warp(time);
|
||||
}
|
||||
@ -554,29 +554,29 @@ contract WakuRlnV2Test is Test {
|
||||
|
||||
// Erased memberships are gone!
|
||||
for (uint256 i = 0; i < commitmentsToErase.length; i++) {
|
||||
(,,, uint32 fetchedUserMessageLimit,,,) = w.members(commitmentsToErase[i]);
|
||||
assertEq(fetchedUserMessageLimit, 0);
|
||||
(,,, uint32 fetchedMembershipRateLimit,,,) = w.memberships(commitmentsToErase[i]);
|
||||
assertEq(fetchedMembershipRateLimit, 0);
|
||||
}
|
||||
}
|
||||
|
||||
function test__WithdrawToken(uint32 userMessageLimit) external {
|
||||
function test__WithdrawToken(uint32 membershipRateLimit) external {
|
||||
vm.pauseGasMetering();
|
||||
uint256 idCommitment = 2;
|
||||
LinearPriceCalculator priceCalculator = LinearPriceCalculator(address(w.priceCalculator()));
|
||||
vm.prank(priceCalculator.owner());
|
||||
priceCalculator.setTokenAndPrice(address(token), 5 wei);
|
||||
(, uint256 price) = w.priceCalculator().calculate(userMessageLimit);
|
||||
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
|
||||
token.mint(address(this), price);
|
||||
vm.assume(
|
||||
userMessageLimit >= w.minRateLimitPerMembership() && userMessageLimit <= w.maxRateLimitPerMembership()
|
||||
membershipRateLimit >= w.minRateLimitPerMembership() && membershipRateLimit <= w.maxRateLimitPerMembership()
|
||||
);
|
||||
vm.assume(w.isValidUserMessageLimit(userMessageLimit));
|
||||
vm.assume(w.isValidMembershipRateLimit(membershipRateLimit));
|
||||
vm.resumeGasMetering();
|
||||
|
||||
token.approve(address(w), price);
|
||||
w.register(idCommitment, userMessageLimit);
|
||||
w.register(idCommitment, membershipRateLimit);
|
||||
|
||||
(, uint256 gracePeriodStartDate,,,,,) = w.members(idCommitment);
|
||||
(, uint256 gracePeriodStartDate,,,,,) = w.memberships(idCommitment);
|
||||
|
||||
vm.warp(gracePeriodStartDate);
|
||||
|
||||
@ -604,29 +604,29 @@ contract WakuRlnV2Test is Test {
|
||||
function test__InvalidRegistration__DuplicateIdCommitment() external {
|
||||
vm.pauseGasMetering();
|
||||
uint256 idCommitment = 2;
|
||||
uint32 userMessageLimit = w.minRateLimitPerMembership();
|
||||
(, uint256 price) = w.priceCalculator().calculate(userMessageLimit);
|
||||
uint32 membershipRateLimit = w.minRateLimitPerMembership();
|
||||
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
|
||||
vm.resumeGasMetering();
|
||||
|
||||
token.approve(address(w), price);
|
||||
w.register(idCommitment, userMessageLimit);
|
||||
w.register(idCommitment, membershipRateLimit);
|
||||
|
||||
token.approve(address(w), price);
|
||||
vm.expectRevert(DuplicateIdCommitment.selector);
|
||||
w.register(idCommitment, userMessageLimit);
|
||||
w.register(idCommitment, membershipRateLimit);
|
||||
}
|
||||
|
||||
function test__InvalidRegistration__FullTree() external {
|
||||
vm.pauseGasMetering();
|
||||
uint32 userMessageLimit = 20;
|
||||
(, uint256 price) = w.priceCalculator().calculate(userMessageLimit);
|
||||
uint32 membershipRateLimit = 20;
|
||||
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
|
||||
vm.resumeGasMetering();
|
||||
|
||||
// we progress the tree to the last leaf
|
||||
|
||||
/*| Name | Type | Slot | Offset | Bytes |
|
||||
|---------------------|-----------------------------------------------------|------|--------|-------|
|
||||
| nextCommitmentIndex | uint32 | 256 | 0 | 4 | */
|
||||
| nextFreeIndex | uint32 | 256 | 0 | 4 | */
|
||||
|
||||
/*
|
||||
Pro tip: to easily find the storage slot of a variable, without having to calculate the storage layout
|
||||
@ -644,54 +644,54 @@ contract WakuRlnV2Test is Test {
|
||||
If the storage layout changes, update the next line accordingly
|
||||
*/
|
||||
|
||||
// we set nextCommitmentIndex to 4294967295 (1 << 20) = 0x00100000
|
||||
// we set nextFreeIndex to 4294967295 (1 << 20) = 0x00100000
|
||||
vm.store(address(w), bytes32(uint256(256)), 0x0000000000000000000000000000000000000000000000000000000000100000);
|
||||
token.approve(address(w), price);
|
||||
vm.expectRevert(FullTree.selector);
|
||||
w.register(1, userMessageLimit);
|
||||
vm.expectRevert(FullMembershipSet.selector);
|
||||
w.register(1, membershipRateLimit);
|
||||
}
|
||||
|
||||
function test__InvalidPaginationQuery__StartIndexGTEndIndex() external {
|
||||
vm.expectRevert(abi.encodeWithSelector(InvalidPaginationQuery.selector, 1, 0));
|
||||
w.getCommitments(1, 0);
|
||||
w.getRateCommitmentsInRange(1, 0);
|
||||
}
|
||||
|
||||
function test__InvalidPaginationQuery__EndIndexGTnextCommitmentIndex() external {
|
||||
vm.expectRevert(abi.encodeWithSelector(InvalidPaginationQuery.selector, 0, 2));
|
||||
w.getCommitments(0, 2);
|
||||
w.getRateCommitmentsInRange(0, 2);
|
||||
}
|
||||
|
||||
function test__ValidPaginationQuery__OneElement() external {
|
||||
vm.pauseGasMetering();
|
||||
uint256 idCommitment = 1;
|
||||
uint32 userMessageLimit = w.minRateLimitPerMembership();
|
||||
(, uint256 price) = w.priceCalculator().calculate(userMessageLimit);
|
||||
uint32 membershipRateLimit = w.minRateLimitPerMembership();
|
||||
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
|
||||
vm.resumeGasMetering();
|
||||
|
||||
token.approve(address(w), price);
|
||||
w.register(idCommitment, userMessageLimit);
|
||||
uint256[] memory commitments = w.getCommitments(0, 0);
|
||||
w.register(idCommitment, membershipRateLimit);
|
||||
uint256[] memory commitments = w.getRateCommitmentsInRange(0, 0);
|
||||
assertEq(commitments.length, 1);
|
||||
uint256 rateCommitment = PoseidonT3.hash([idCommitment, userMessageLimit]);
|
||||
uint256 rateCommitment = PoseidonT3.hash([idCommitment, membershipRateLimit]);
|
||||
assertEq(commitments[0], rateCommitment);
|
||||
}
|
||||
|
||||
function test__ValidPaginationQuery(uint32 idCommitmentsLength) external {
|
||||
vm.pauseGasMetering();
|
||||
vm.assume(idCommitmentsLength > 0 && idCommitmentsLength <= 100);
|
||||
uint32 userMessageLimit = w.minRateLimitPerMembership();
|
||||
(, uint256 price) = w.priceCalculator().calculate(userMessageLimit);
|
||||
uint32 membershipRateLimit = w.minRateLimitPerMembership();
|
||||
(, uint256 price) = w.priceCalculator().calculate(membershipRateLimit);
|
||||
|
||||
for (uint256 i = 0; i < idCommitmentsLength; i++) {
|
||||
token.approve(address(w), price);
|
||||
w.register(i + 1, userMessageLimit);
|
||||
w.register(i + 1, membershipRateLimit);
|
||||
}
|
||||
vm.resumeGasMetering();
|
||||
|
||||
uint256[] memory commitments = w.getCommitments(0, idCommitmentsLength);
|
||||
uint256[] memory commitments = w.getRateCommitmentsInRange(0, idCommitmentsLength);
|
||||
assertEq(commitments.length, idCommitmentsLength + 1);
|
||||
for (uint256 i = 0; i < idCommitmentsLength; i++) {
|
||||
uint256 rateCommitment = PoseidonT3.hash([i + 1, userMessageLimit]);
|
||||
uint256 rateCommitment = PoseidonT3.hash([i + 1, membershipRateLimit]);
|
||||
assertEq(commitments[i], rateCommitment);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user