chore: tests (#5)
* chore: tests * fix: add helper to get all metadata from idCommitment * fix: max runs * fix: full tree test * fix: refactor, reuse function for memberExists * fix: getCommitments range and cut scope from other tests * fix: range for assert on pagination * fix: duped conditionals
This commit is contained in:
parent
6d028a1308
commit
4c6b8fb253
|
@ -1 +1,13 @@
|
|||
WakuRlnV2Test:test__ValidRegistration() (gas: 108661)
|
||||
WakuRlnV2Test:test__IdCommitmentToMetadata__DoesntExist() (gas: 8299)
|
||||
WakuRlnV2Test:test__InvalidPaginationQuery__EndIndexGTIdCommitmentIndex() (gas: 13351)
|
||||
WakuRlnV2Test:test__InvalidPaginationQuery__StartIndexGTEndIndex() (gas: 11184)
|
||||
WakuRlnV2Test:test__InvalidRegistration__DuplicateIdCommitment() (gas: 111313)
|
||||
WakuRlnV2Test:test__InvalidRegistration__FullTree() (gas: 97043)
|
||||
WakuRlnV2Test:test__InvalidRegistration__InvalidIdCommitment__LargerThanField() (gas: 9926)
|
||||
WakuRlnV2Test:test__InvalidRegistration__InvalidIdCommitment__Zero() (gas: 9139)
|
||||
WakuRlnV2Test:test__InvalidRegistration__InvalidUserMessageLimit__LargerThanMax() (gas: 10147)
|
||||
WakuRlnV2Test:test__InvalidRegistration__InvalidUserMessageLimit__Zero() (gas: 9242)
|
||||
WakuRlnV2Test:test__ValidPaginationQuery(uint32) (runs: 1002, μ: 403497, ~: 136269)
|
||||
WakuRlnV2Test:test__ValidPaginationQuery__OneElement() (gas: 128461)
|
||||
WakuRlnV2Test:test__ValidRegistration(uint256,uint32) (runs: 1001, μ: 133518, ~: 133518)
|
||||
WakuRlnV2Test:test__ValidRegistration__kats() (gas: 108902)
|
|
@ -17,6 +17,9 @@
|
|||
src = "src"
|
||||
test = "test"
|
||||
|
||||
[fuzz]
|
||||
max_test_rejects = 128_000
|
||||
|
||||
[profile.ci]
|
||||
fuzz = { runs = 10_000 }
|
||||
verbosity = 4
|
||||
|
|
|
@ -37,6 +37,7 @@ contract WakuRlnV2 {
|
|||
/// @notice The index of the next member to be registered
|
||||
uint32 public idCommitmentIndex = 0;
|
||||
|
||||
/// @notice the membership metadata of the member
|
||||
struct MembershipInfo {
|
||||
/// @notice the user message limit of each member
|
||||
uint32 userMessageLimit;
|
||||
|
@ -59,17 +60,21 @@ contract WakuRlnV2 {
|
|||
/// @param index The index of the member in the set
|
||||
event MemberRegistered(uint256 idCommitment, uint32 userMessageLimit, uint32 index);
|
||||
|
||||
/// @notice the modifier to check if the idCommitment is valid
|
||||
/// @param idCommitment The idCommitment of the member
|
||||
modifier onlyValidIdCommitment(uint256 idCommitment) {
|
||||
if (!isValidCommitment(idCommitment)) revert InvalidIdCommitment(idCommitment);
|
||||
_;
|
||||
}
|
||||
|
||||
modifier onlyValidUserMessageLimit(uint32 messageLimit) {
|
||||
if (messageLimit > MAX_MESSAGE_LIMIT) revert InvalidUserMessageLimit(messageLimit);
|
||||
if (messageLimit == 0) revert InvalidUserMessageLimit(messageLimit);
|
||||
/// @notice the modifier to check if the userMessageLimit is valid
|
||||
/// @param userMessageLimit The user message limit
|
||||
modifier onlyValidUserMessageLimit(uint32 userMessageLimit) {
|
||||
if (!isValidUserMessageLimit(userMessageLimit)) revert InvalidUserMessageLimit(userMessageLimit);
|
||||
_;
|
||||
}
|
||||
|
||||
/// @notice the constructor of the contract
|
||||
constructor(uint32 maxMessageLimit) {
|
||||
MAX_MESSAGE_LIMIT = maxMessageLimit;
|
||||
SET_SIZE = uint32(1 << DEPTH);
|
||||
|
@ -77,9 +82,45 @@ contract WakuRlnV2 {
|
|||
LazyIMT.init(imtData, DEPTH);
|
||||
}
|
||||
|
||||
function memberExists(uint256 idCommitment) public view returns (bool) {
|
||||
/// @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) {
|
||||
return idCommitment != 0 && idCommitment < Q;
|
||||
}
|
||||
|
||||
/// @notice Checks if a user message limit is valid
|
||||
/// @param userMessageLimit The user message limit
|
||||
/// @return true if the user message limit is valid, false otherwise
|
||||
function isValidUserMessageLimit(uint32 userMessageLimit) public view returns (bool) {
|
||||
return userMessageLimit > 0 && userMessageLimit <= MAX_MESSAGE_LIMIT;
|
||||
}
|
||||
|
||||
/// @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 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 member = memberInfo[idCommitment];
|
||||
return member.userMessageLimit > 0 && member.index >= 0;
|
||||
// we cannot call indexToCommitment for 0 index if the member doesn't exist
|
||||
if (member.userMessageLimit == 0) {
|
||||
return (0, 0, 0);
|
||||
}
|
||||
return (member.userMessageLimit, member.index, indexToCommitment(member.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);
|
||||
return rateCommitment != 0;
|
||||
}
|
||||
|
||||
/// Allows a user to register as a member
|
||||
|
@ -112,29 +153,30 @@ contract WakuRlnV2 {
|
|||
idCommitmentIndex += 1;
|
||||
}
|
||||
|
||||
function isValidCommitment(uint256 idCommitment) public pure returns (bool) {
|
||||
return idCommitment != 0 && idCommitment < Q;
|
||||
}
|
||||
|
||||
function indexToCommitment(uint32 index) public view returns (uint256) {
|
||||
return imtData.elements[LazyIMT.indexForElement(0, 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) {
|
||||
if (startIndex >= endIndex) revert InvalidPaginationQuery(startIndex, endIndex);
|
||||
if (startIndex > endIndex) revert InvalidPaginationQuery(startIndex, endIndex);
|
||||
if (endIndex > idCommitmentIndex) revert InvalidPaginationQuery(startIndex, endIndex);
|
||||
|
||||
uint256[] memory commitments = new uint256[](endIndex - startIndex);
|
||||
for (uint32 i = startIndex; i < endIndex; i++) {
|
||||
uint256[] memory commitments = new uint256[](endIndex - startIndex + 1);
|
||||
for (uint32 i = startIndex; i <= endIndex; i++) {
|
||||
commitments[i - startIndex] = indexToCommitment(i);
|
||||
}
|
||||
return commitments;
|
||||
}
|
||||
|
||||
/// @notice Returns the root of the IMT
|
||||
/// @return The root of the IMT
|
||||
function root() external view returns (uint256) {
|
||||
return LazyIMT.root(imtData, 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[] memory) {
|
||||
return LazyIMT.merkleProofElements(imtData, index, DEPTH);
|
||||
}
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity >=0.8.19 <0.9.0;
|
||||
|
||||
import { Test, console } from "forge-std/Test.sol";
|
||||
import { Test } from "forge-std/Test.sol";
|
||||
import { stdStorage, StdStorage } from "forge-std/Test.sol";
|
||||
|
||||
import { Deploy } from "../script/Deploy.s.sol";
|
||||
import { DeploymentConfig } from "../script/DeploymentConfig.s.sol";
|
||||
import { WakuRlnV2 } from "../src/WakuRlnV2.sol";
|
||||
import "../src/WakuRlnV2.sol";
|
||||
import { PoseidonT3 } from "poseidon-solidity/PoseidonT3.sol";
|
||||
import { LazyIMT } from "@zk-kit/imt.sol/LazyIMT.sol";
|
||||
|
||||
contract WakuRlnV2Test is Test {
|
||||
using stdStorage for StdStorage;
|
||||
|
||||
WakuRlnV2 internal w;
|
||||
DeploymentConfig internal deploymentConfig;
|
||||
|
||||
|
@ -20,7 +23,7 @@ contract WakuRlnV2Test is Test {
|
|||
(w, deploymentConfig) = deployment.run();
|
||||
}
|
||||
|
||||
function test__ValidRegistration() external {
|
||||
function test__ValidRegistration__kats() external {
|
||||
vm.pauseGasMetering();
|
||||
uint256 idCommitment = 2;
|
||||
uint32 userMessageLimit = 2;
|
||||
|
@ -35,14 +38,119 @@ contract WakuRlnV2Test is Test {
|
|||
// kats from zerokit
|
||||
uint256 rateCommitment =
|
||||
4_699_387_056_273_519_054_140_667_386_511_343_037_709_699_938_246_587_880_795_929_666_834_307_503_001;
|
||||
assertEq(w.indexToCommitment(0), rateCommitment);
|
||||
uint256[] memory commitments = w.getCommitments(0, 1);
|
||||
assertEq(commitments.length, 1);
|
||||
assertEq(commitments[index], rateCommitment);
|
||||
assertEq(
|
||||
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);
|
||||
assertEq(index2, 0);
|
||||
assertEq(rateCommitment2, rateCommitment);
|
||||
vm.resumeGasMetering();
|
||||
}
|
||||
|
||||
function test__ValidRegistration(uint256 idCommitment, uint32 userMessageLimit) external {
|
||||
vm.assume(w.isValidCommitment(idCommitment) && w.isValidUserMessageLimit(userMessageLimit));
|
||||
|
||||
assertEq(w.memberExists(idCommitment), false);
|
||||
w.register(idCommitment, userMessageLimit);
|
||||
uint256 rateCommitment = PoseidonT3.hash([idCommitment, userMessageLimit]);
|
||||
|
||||
(uint32 fetchedUserMessageLimit, uint32 index, uint256 fetchedRateCommitment) =
|
||||
w.idCommitmentToMetadata(idCommitment);
|
||||
assertEq(fetchedUserMessageLimit, userMessageLimit);
|
||||
assertEq(index, 0);
|
||||
assertEq(fetchedRateCommitment, rateCommitment);
|
||||
}
|
||||
|
||||
function test__IdCommitmentToMetadata__DoesntExist() external {
|
||||
uint256 idCommitment = 2;
|
||||
(uint32 userMessageLimit, uint32 index, uint256 rateCommitment) = w.idCommitmentToMetadata(idCommitment);
|
||||
assertEq(userMessageLimit, 0);
|
||||
assertEq(index, 0);
|
||||
assertEq(rateCommitment, 0);
|
||||
}
|
||||
|
||||
function test__InvalidRegistration__InvalidIdCommitment__Zero() external {
|
||||
uint256 idCommitment = 0;
|
||||
uint32 userMessageLimit = 2;
|
||||
vm.expectRevert(abi.encodeWithSelector(InvalidIdCommitment.selector, 0));
|
||||
w.register(idCommitment, userMessageLimit);
|
||||
}
|
||||
|
||||
function test__InvalidRegistration__InvalidIdCommitment__LargerThanField() external {
|
||||
uint256 idCommitment = w.Q() + 1;
|
||||
uint32 userMessageLimit = 2;
|
||||
vm.expectRevert(abi.encodeWithSelector(InvalidIdCommitment.selector, idCommitment));
|
||||
w.register(idCommitment, userMessageLimit);
|
||||
}
|
||||
|
||||
function test__InvalidRegistration__InvalidUserMessageLimit__Zero() external {
|
||||
uint256 idCommitment = 2;
|
||||
uint32 userMessageLimit = 0;
|
||||
vm.expectRevert(abi.encodeWithSelector(InvalidUserMessageLimit.selector, 0));
|
||||
w.register(idCommitment, userMessageLimit);
|
||||
}
|
||||
|
||||
function test__InvalidRegistration__InvalidUserMessageLimit__LargerThanMax() external {
|
||||
uint256 idCommitment = 2;
|
||||
uint32 userMessageLimit = w.MAX_MESSAGE_LIMIT() + 1;
|
||||
vm.expectRevert(abi.encodeWithSelector(InvalidUserMessageLimit.selector, userMessageLimit));
|
||||
w.register(idCommitment, userMessageLimit);
|
||||
}
|
||||
|
||||
function test__InvalidRegistration__DuplicateIdCommitment() external {
|
||||
uint256 idCommitment = 2;
|
||||
uint32 userMessageLimit = 2;
|
||||
w.register(idCommitment, userMessageLimit);
|
||||
vm.expectRevert(DuplicateIdCommitment.selector);
|
||||
w.register(idCommitment, userMessageLimit);
|
||||
}
|
||||
|
||||
function test__InvalidRegistration__FullTree() external {
|
||||
uint32 userMessageLimit = 2;
|
||||
// we progress the tree to the last leaf
|
||||
stdstore.target(address(w)).sig("idCommitmentIndex()").checked_write(1 << w.DEPTH());
|
||||
vm.expectRevert(FullTree.selector);
|
||||
w.register(1, userMessageLimit);
|
||||
}
|
||||
|
||||
function test__InvalidPaginationQuery__StartIndexGTEndIndex() external {
|
||||
vm.expectRevert(abi.encodeWithSelector(InvalidPaginationQuery.selector, 1, 0));
|
||||
w.getCommitments(1, 0);
|
||||
}
|
||||
|
||||
function test__InvalidPaginationQuery__EndIndexGTIdCommitmentIndex() external {
|
||||
vm.expectRevert(abi.encodeWithSelector(InvalidPaginationQuery.selector, 0, 2));
|
||||
w.getCommitments(0, 2);
|
||||
}
|
||||
|
||||
function test__ValidPaginationQuery__OneElement() external {
|
||||
uint32 userMessageLimit = 2;
|
||||
uint256 idCommitment = 1;
|
||||
w.register(idCommitment, userMessageLimit);
|
||||
uint256[] memory commitments = w.getCommitments(0, 0);
|
||||
assertEq(commitments.length, 1);
|
||||
uint256 rateCommitment = PoseidonT3.hash([idCommitment, userMessageLimit]);
|
||||
assertEq(commitments[0], rateCommitment);
|
||||
}
|
||||
|
||||
function test__ValidPaginationQuery(uint32 idCommitmentsLength) external {
|
||||
vm.assume(idCommitmentsLength > 0 && idCommitmentsLength <= 100);
|
||||
uint32 userMessageLimit = 2;
|
||||
|
||||
vm.pauseGasMetering();
|
||||
for (uint256 i = 0; i < idCommitmentsLength; i++) {
|
||||
w.register(i + 1, userMessageLimit);
|
||||
}
|
||||
vm.resumeGasMetering();
|
||||
|
||||
uint256[] memory commitments = w.getCommitments(0, idCommitmentsLength);
|
||||
assertEq(commitments.length, idCommitmentsLength + 1);
|
||||
for (uint256 i = 0; i < idCommitmentsLength; i++) {
|
||||
uint256 rateCommitment = PoseidonT3.hash([i + 1, userMessageLimit]);
|
||||
assertEq(commitments[i], rateCommitment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue