diff --git a/test/RLN.t.sol b/test/RLN.t.sol index 5f6e90f..1070786 100644 --- a/test/RLN.t.sol +++ b/test/RLN.t.sol @@ -3,221 +3,30 @@ pragma solidity ^0.8.15; import "../contracts/PoseidonHasher.sol"; import "../contracts/Rln.sol"; -import "./Verifier.sol"; import "forge-std/Test.sol"; import "forge-std/StdCheats.sol"; import "forge-std/console.sol"; - contract RLNTest is Test { using stdStorage for StdStorage; RLN public rln; PoseidonHasher public poseidon; - TrueVerifier public trueVerifier; - FalseVerifier public falseVerifier; uint256 public constant MEMBERSHIP_DEPOSIT = 1000000000000000; uint256 public constant DEPTH = 20; uint256 public constant SET_SIZE = 1048576; - uint256[8] public zeroedProof = [0, 0, 0, 0, 0, 0, 0, 0]; - /// @dev Setup the testing environment. function setUp() public { poseidon = new PoseidonHasher(); - trueVerifier = new TrueVerifier(); - falseVerifier = new FalseVerifier(); - rln = new RLN(MEMBERSHIP_DEPOSIT, DEPTH, address(poseidon), address(trueVerifier)); + uint256[] memory constructMembers = new uint256[](0); + rln = new RLN(constructMembers, address(poseidon)); } /// @dev Ensure that you can hash a value. function test__Constants() public { - assertEq(rln.MEMBERSHIP_DEPOSIT(), MEMBERSHIP_DEPOSIT); assertEq(rln.DEPTH(), DEPTH); assertEq(rln.SET_SIZE(), SET_SIZE); } - - function test__ValidRegistration(uint256 idCommitment) public { - rln.register{value: MEMBERSHIP_DEPOSIT}(idCommitment); - assertEq(rln.stakedAmounts(idCommitment), MEMBERSHIP_DEPOSIT); - assertEq(rln.members(idCommitment), 1); - } - - function test__InvalidRegistration__DuplicateCommitment( - uint256 idCommitment - ) public { - rln.register{value: MEMBERSHIP_DEPOSIT}(idCommitment); - assertEq(rln.stakedAmounts(idCommitment), MEMBERSHIP_DEPOSIT); - assertEq(rln.members(idCommitment), 1); - vm.expectRevert(DuplicateIdCommitment.selector); - rln.register{value: MEMBERSHIP_DEPOSIT}(idCommitment); - } - - function test__InvalidRegistration__InsufficientDeposit( - uint256 idCommitment - ) public { - uint256 badDepositAmount = MEMBERSHIP_DEPOSIT - 1; - vm.expectRevert( - abi.encodeWithSelector( - InsufficientDeposit.selector, - MEMBERSHIP_DEPOSIT, - badDepositAmount - ) - ); - rln.register{value: badDepositAmount}(idCommitment); - } - - function test__InvalidRegistration__FullSet( - uint256 idCommitmentSeed - ) public { - vm.assume(idCommitmentSeed < 2 ** 255 - SET_SIZE); - RLN tempRln = new RLN( - MEMBERSHIP_DEPOSIT, - 2, - address(rln.poseidonHasher()), - address(rln.verifier()) - ); - uint256 setSize = tempRln.SET_SIZE() - 1; - for (uint256 i = 0; i < setSize; i++) { - tempRln.register{value: MEMBERSHIP_DEPOSIT}(idCommitmentSeed + i); - } - assertEq(tempRln.idCommitmentIndex(), 4); - vm.expectRevert(FullTree.selector); - tempRln.register{value: MEMBERSHIP_DEPOSIT}(idCommitmentSeed + setSize); - } - - function test__ValidSlash(uint256 idCommitment, address payable to) public { - // avoid precompiles, etc - // TODO: wrap both of these in a single function - assumePayable(to); - assumeNoPrecompiles(to); - vm.assume(to != address(0)); - - rln.register{value: MEMBERSHIP_DEPOSIT}(idCommitment); - assertEq(rln.stakedAmounts(idCommitment), MEMBERSHIP_DEPOSIT); - - uint256 balanceBefore = to.balance; - rln.slash(idCommitment, to, zeroedProof); - vm.prank(to); - rln.withdraw(); - assertEq(rln.stakedAmounts(idCommitment), 0); - assertEq(rln.members(idCommitment), 0); - assertEq(to.balance, balanceBefore + MEMBERSHIP_DEPOSIT); - } - - function test__InvalidSlash__ToZeroAddress() public { - uint256 idCommitment = 9014214495641488759237505126948346942972912379615652741039992445865937985820; - - rln.register{value: MEMBERSHIP_DEPOSIT}(idCommitment); - assertEq(rln.stakedAmounts(idCommitment), MEMBERSHIP_DEPOSIT); - vm.expectRevert( - abi.encodeWithSelector(InvalidReceiverAddress.selector, address(0)) - ); - rln.slash(idCommitment, payable(address(0)), zeroedProof); - } - - function test__InvalidSlash__ToRlnAddress() public { - uint256 idCommitment = 19014214495641488759237505126948346942972912379615652741039992445865937985820; - rln.register{value: MEMBERSHIP_DEPOSIT}(idCommitment); - assertEq(rln.stakedAmounts(idCommitment), MEMBERSHIP_DEPOSIT); - vm.expectRevert( - abi.encodeWithSelector( - InvalidReceiverAddress.selector, - address(rln) - ) - ); - rln.slash(idCommitment, payable(address(rln)), zeroedProof); - } - - function test__InvalidSlash__InvalidIdCommitment( - uint256 idCommitment - ) public { - vm.expectRevert( - abi.encodeWithSelector(MemberNotRegistered.selector, idCommitment) - ); - rln.slash(idCommitment, payable(address(this)), zeroedProof); - } - - // this shouldn't be possible, but just in case - function test__InvalidSlash__NoStake( - uint256 idCommitment, - address payable to - ) public { - // avoid precompiles, etc - assumePayable(to); - assumeNoPrecompiles(to); - vm.assume(to != address(0)); - - rln.register{value: MEMBERSHIP_DEPOSIT}(idCommitment); - assertEq(rln.stakedAmounts(idCommitment), MEMBERSHIP_DEPOSIT); - - rln.slash(idCommitment, to, zeroedProof); - assertEq(rln.stakedAmounts(idCommitment), 0); - assertEq(rln.members(idCommitment), 0); - - // manually set members[idCommitment] to true using vm - stdstore - .target(address(rln)) - .sig("members(uint256)") - .with_key(idCommitment) - .depth(0) - .checked_write(true); - - vm.expectRevert( - abi.encodeWithSelector(MemberHasNoStake.selector, idCommitment) - ); - rln.slash(idCommitment, to, zeroedProof); - } - - function test__InvalidSlash__InvalidProof() public { - uint256 idCommitment = 19014214495641488759237505126948346942972912379615652741039992445865937985820; - - RLN tempRln = new RLN( - MEMBERSHIP_DEPOSIT, - 2, - address(rln.poseidonHasher()), - address(falseVerifier) - ); - - tempRln.register{value: MEMBERSHIP_DEPOSIT}(idCommitment); - - vm.expectRevert(InvalidProof.selector); - tempRln.slash(idCommitment, payable(address(this)), zeroedProof); - } - - function test__InvalidWithdraw__InsufficientWithdrawalBalance() public { - vm.expectRevert(InsufficientWithdrawalBalance.selector); - rln.withdraw(); - } - - function test__InvalidWithdraw__InsufficientContractBalance() public { - uint256 idCommitment = 19014214495641488759237505126948346942972912379615652741039992445865937985820; - rln.register{value: MEMBERSHIP_DEPOSIT}(idCommitment); - assertEq(rln.stakedAmounts(idCommitment), MEMBERSHIP_DEPOSIT); - rln.slash(idCommitment, payable(address(this)), zeroedProof); - assertEq(rln.stakedAmounts(idCommitment), 0); - assertEq(rln.members(idCommitment), 0); - - vm.deal(address(rln), 0); - vm.expectRevert(InsufficientContractBalance.selector); - rln.withdraw(); - } - - function test__ValidWithdraw(address payable to) public { - assumePayable(to); - assumeNoPrecompiles(to); - - uint256 idCommitment = 19014214495641488759237505126948346942972912379615652741039992445865937985820; - - rln.register{value: MEMBERSHIP_DEPOSIT}(idCommitment); - assertEq(rln.stakedAmounts(idCommitment), MEMBERSHIP_DEPOSIT); - rln.slash(idCommitment, to, zeroedProof); - assertEq(rln.stakedAmounts(idCommitment), 0); - assertEq(rln.members(idCommitment), 0); - - vm.prank(to); - rln.withdraw(); - assertEq(rln.withdrawalBalance(to), 0); - } } diff --git a/test/Verifier.sol b/test/Verifier.sol deleted file mode 100644 index 049993f..0000000 --- a/test/Verifier.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: Unlicense -pragma solidity ^0.8.15; - -import {IVerifier} from "../contracts/IVerifier.sol"; - -contract TrueVerifier is IVerifier { - function verifyProof( - uint256[2] memory a, - uint256[2][2] memory b, - uint256[2] memory c, - uint256[2] memory input - ) external view returns (bool) { - return true; - } -} - -contract FalseVerifier is IVerifier { - function verifyProof( - uint256[2] memory a, - uint256[2][2] memory b, - uint256[2] memory c, - uint256[2] memory input - ) external view returns (bool) { - return false; - } -} \ No newline at end of file diff --git a/test/rln.test.ts b/test/rln.test.ts index 19ea3a2..c987794 100644 --- a/test/rln.test.ts +++ b/test/rln.test.ts @@ -5,74 +5,4 @@ describe("RLN", () => { beforeEach(async () => { await deployments.fixture(["RLN"]); }); - - it("should register new memberships", async () => { - const rln = await ethers.getContract("RLN", ethers.provider.getSigner(0)); - - const price = await rln.MEMBERSHIP_DEPOSIT(); - - // A valid pair of (id_secret, id_commitment) generated in rust - const idCommitment = - "0x0c3ac305f6a4fe9bfeb3eba978bc876e2a99208b8b56c80160cfb54ba8f02368"; - - const registerTx = await rln["register(uint256)"](idCommitment, { - value: price, - }); - const txRegisterReceipt = await registerTx.wait(); - - const pubkey = txRegisterReceipt.events[0].args.idCommitment; - - // We ensure the registered id_commitment is the one we passed - expect( - pubkey.toHexString() === idCommitment, - "registered commitment doesn't match passed commitment" - ); - }); - - it("should slash membership", async () => { - const rln = await ethers.getContract("RLN", ethers.provider.getSigner(0)); - - const price = await rln.MEMBERSHIP_DEPOSIT(); - - // A valid id_commitment generated in zerokit - const idCommitment = - "0x0c3ac305f6a4fe9bfeb3eba978bc876e2a99208b8b56c80160cfb54ba8f02368"; - - const registerTx = await rln["register(uint256)"](idCommitment, { - value: price, - }); - await registerTx.wait(); - - // We slash the id_commitment - const receiverAddress = "0x000000000000000000000000000000000000dead"; - const slashTx = rln["slash(uint256,address,uint256[8])"]( - idCommitment, - receiverAddress, - [0, 0, 0, 0, 0, 0, 0, 0] - ); - - await expect(slashTx).to.be.revertedWith("InvalidProof()"); - }); - - it("should not allow multiple registrations with same pubkey", async () => { - const rln = await ethers.getContract("RLN", ethers.provider.getSigner(0)); - - const price = await rln.MEMBERSHIP_DEPOSIT(); - - // A valid pair of (id_secret, id_commitment) generated in rust - const idCommitment = - "0x0c3ac305f6a4fe9bfeb3eba978bc876e2a99208b8b56c80160cfb54ba8f02368"; - - const registerTx = await rln["register(uint256)"](idCommitment, { - value: price, - }); - await registerTx.wait(); - - // Send the same tx again - const registerTx2 = rln["register(uint256)"](idCommitment, { - value: price, - }); - - await expect(registerTx2).to.be.revertedWith("DuplicateIdCommitment()"); - }); });