chore: update tests
This commit is contained in:
parent
d25d19b3ed
commit
58e09dcb80
195
test/RLN.t.sol
195
test/RLN.t.sol
|
@ -3,221 +3,30 @@ pragma solidity ^0.8.15;
|
||||||
|
|
||||||
import "../contracts/PoseidonHasher.sol";
|
import "../contracts/PoseidonHasher.sol";
|
||||||
import "../contracts/Rln.sol";
|
import "../contracts/Rln.sol";
|
||||||
import "./Verifier.sol";
|
|
||||||
import "forge-std/Test.sol";
|
import "forge-std/Test.sol";
|
||||||
import "forge-std/StdCheats.sol";
|
import "forge-std/StdCheats.sol";
|
||||||
import "forge-std/console.sol";
|
import "forge-std/console.sol";
|
||||||
|
|
||||||
|
|
||||||
contract RLNTest is Test {
|
contract RLNTest is Test {
|
||||||
using stdStorage for StdStorage;
|
using stdStorage for StdStorage;
|
||||||
|
|
||||||
RLN public rln;
|
RLN public rln;
|
||||||
PoseidonHasher public poseidon;
|
PoseidonHasher public poseidon;
|
||||||
TrueVerifier public trueVerifier;
|
|
||||||
FalseVerifier public falseVerifier;
|
|
||||||
|
|
||||||
uint256 public constant MEMBERSHIP_DEPOSIT = 1000000000000000;
|
uint256 public constant MEMBERSHIP_DEPOSIT = 1000000000000000;
|
||||||
uint256 public constant DEPTH = 20;
|
uint256 public constant DEPTH = 20;
|
||||||
uint256 public constant SET_SIZE = 1048576;
|
uint256 public constant SET_SIZE = 1048576;
|
||||||
uint256[8] public zeroedProof = [0, 0, 0, 0, 0, 0, 0, 0];
|
|
||||||
|
|
||||||
|
|
||||||
/// @dev Setup the testing environment.
|
/// @dev Setup the testing environment.
|
||||||
function setUp() public {
|
function setUp() public {
|
||||||
poseidon = new PoseidonHasher();
|
poseidon = new PoseidonHasher();
|
||||||
trueVerifier = new TrueVerifier();
|
uint256[] memory constructMembers = new uint256[](0);
|
||||||
falseVerifier = new FalseVerifier();
|
rln = new RLN(constructMembers, address(poseidon));
|
||||||
rln = new RLN(MEMBERSHIP_DEPOSIT, DEPTH, address(poseidon), address(trueVerifier));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Ensure that you can hash a value.
|
/// @dev Ensure that you can hash a value.
|
||||||
function test__Constants() public {
|
function test__Constants() public {
|
||||||
assertEq(rln.MEMBERSHIP_DEPOSIT(), MEMBERSHIP_DEPOSIT);
|
|
||||||
assertEq(rln.DEPTH(), DEPTH);
|
assertEq(rln.DEPTH(), DEPTH);
|
||||||
assertEq(rln.SET_SIZE(), SET_SIZE);
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,74 +5,4 @@ describe("RLN", () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await deployments.fixture(["RLN"]);
|
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()");
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue