mirror of
https://github.com/vacp2p/rln-interep-contract.git
synced 2025-02-28 14:10:35 +00:00
feat: withdrawals/slashing implemented on interep
This commit is contained in:
parent
ac21cfd698
commit
430b040043
@ -10,15 +10,16 @@ contract RLN {
|
|||||||
uint256 public immutable DEPTH;
|
uint256 public immutable DEPTH;
|
||||||
uint256 public immutable SET_SIZE;
|
uint256 public immutable SET_SIZE;
|
||||||
|
|
||||||
uint256 public pubkeyIndex = 0;
|
uint256 public idCommitmentIndex;
|
||||||
mapping(uint256 => uint256) public members;
|
mapping(uint256 => uint256) public stakedAmounts;
|
||||||
|
mapping(uint256 => bool) public members;
|
||||||
|
|
||||||
IPoseidonHasher public poseidonHasher;
|
IPoseidonHasher public poseidonHasher;
|
||||||
IValidGroupStorage public validGroupStorage;
|
IValidGroupStorage public validGroupStorage;
|
||||||
IInterep public interep;
|
IInterep public interep;
|
||||||
|
|
||||||
event MemberRegistered(uint256 pubkey, uint256 index);
|
event MemberRegistered(uint256 idCommitment, uint256 index);
|
||||||
event MemberWithdrawn(uint256 pubkey, uint256 index);
|
event MemberWithdrawn(uint256 idCommitment);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
uint256 membershipDeposit,
|
uint256 membershipDeposit,
|
||||||
@ -34,13 +35,12 @@ contract RLN {
|
|||||||
interep = IInterep(validGroupStorage.interep());
|
interep = IInterep(validGroupStorage.interep());
|
||||||
}
|
}
|
||||||
|
|
||||||
function register(uint256 pubkey) external payable {
|
function register(uint256 idCommitment) external payable {
|
||||||
require(pubkeyIndex < SET_SIZE, "RLN, register: set is full");
|
|
||||||
require(
|
require(
|
||||||
msg.value == MEMBERSHIP_DEPOSIT,
|
msg.value == MEMBERSHIP_DEPOSIT,
|
||||||
"RLN, register: membership deposit is not satisfied"
|
"RLN, register: membership deposit is not satisfied"
|
||||||
);
|
);
|
||||||
_register(pubkey);
|
_register(idCommitment, msg.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Registers a member via a valid Interep Semaphore group.
|
/// @dev Registers a member via a valid Interep Semaphore group.
|
||||||
@ -49,20 +49,19 @@ contract RLN {
|
|||||||
/// @param nullifierHash: Nullifier hash.
|
/// @param nullifierHash: Nullifier hash.
|
||||||
/// @param externalNullifier: External nullifier.
|
/// @param externalNullifier: External nullifier.
|
||||||
/// @param proof: Zero-knowledge proof.
|
/// @param proof: Zero-knowledge proof.
|
||||||
/// @param pubkey: Public key of the member.
|
/// @param idCommitment: ID Commitment of the member.
|
||||||
function register(
|
function register(
|
||||||
uint256 groupId,
|
uint256 groupId,
|
||||||
bytes32 signal,
|
bytes32 signal,
|
||||||
uint256 nullifierHash,
|
uint256 nullifierHash,
|
||||||
uint256 externalNullifier,
|
uint256 externalNullifier,
|
||||||
uint256[8] calldata proof,
|
uint256[8] calldata proof,
|
||||||
uint256 pubkey
|
uint256 idCommitment
|
||||||
) external {
|
) external {
|
||||||
require(
|
require(
|
||||||
validGroupStorage.isValidGroup(groupId),
|
validGroupStorage.isValidGroup(groupId),
|
||||||
"RLN, register: invalid interep group"
|
"RLN, register: invalid interep group"
|
||||||
);
|
);
|
||||||
require(pubkeyIndex < SET_SIZE, "RLN, register: set is full");
|
|
||||||
interep.verifyProof(
|
interep.verifyProof(
|
||||||
groupId,
|
groupId,
|
||||||
signal,
|
signal,
|
||||||
@ -70,93 +69,110 @@ contract RLN {
|
|||||||
externalNullifier,
|
externalNullifier,
|
||||||
proof
|
proof
|
||||||
);
|
);
|
||||||
_register(pubkey);
|
_register(idCommitment, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerBatch(uint256[] calldata pubkeys) external payable {
|
function registerBatch(uint256[] calldata idCommitments) external payable {
|
||||||
uint256 pubkeylen = pubkeys.length;
|
uint256 idCommitmentlen = idCommitments.length;
|
||||||
require(
|
require(
|
||||||
pubkeyIndex + pubkeylen <= SET_SIZE,
|
idCommitmentIndex + idCommitmentlen <= SET_SIZE,
|
||||||
"RLN, registerBatch: set is full"
|
"RLN, registerBatch: set is full"
|
||||||
);
|
);
|
||||||
require(
|
require(
|
||||||
msg.value == MEMBERSHIP_DEPOSIT * pubkeylen,
|
msg.value == MEMBERSHIP_DEPOSIT * idCommitmentlen,
|
||||||
"RLN, registerBatch: membership deposit is not satisfied"
|
"RLN, registerBatch: membership deposit is not satisfied"
|
||||||
);
|
);
|
||||||
for (uint256 i = 0; i < pubkeylen; i++) {
|
for (uint256 i = 0; i < idCommitmentlen; i++) {
|
||||||
_register(pubkeys[i]);
|
_register(idCommitments[i], msg.value / idCommitmentlen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function _register(uint256 pubkey) internal {
|
function _register(uint256 idCommitment, uint256 stake) internal {
|
||||||
members[pubkeyIndex] = pubkey;
|
require(
|
||||||
emit MemberRegistered(pubkey, pubkeyIndex);
|
!members[idCommitment],
|
||||||
pubkeyIndex += 1;
|
"RLN, _register: member already registered"
|
||||||
|
);
|
||||||
|
require(idCommitmentIndex < SET_SIZE, "RLN, register: set is full");
|
||||||
|
if (stake != 0) {
|
||||||
|
members[idCommitment] = true;
|
||||||
|
stakedAmounts[idCommitment] = stake;
|
||||||
|
} else {
|
||||||
|
members[idCommitment] = true;
|
||||||
|
stakedAmounts[idCommitment] = 0;
|
||||||
|
}
|
||||||
|
emit MemberRegistered(idCommitment, idCommitmentIndex);
|
||||||
|
idCommitmentIndex += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
function withdrawBatch(
|
function withdrawBatch(
|
||||||
uint256[] calldata secrets,
|
uint256[] calldata secrets,
|
||||||
uint256[] calldata pubkeyIndexes,
|
|
||||||
address payable[] calldata receivers
|
address payable[] calldata receivers
|
||||||
) external {
|
) external {
|
||||||
uint256 batchSize = secrets.length;
|
uint256 batchSize = secrets.length;
|
||||||
require(batchSize != 0, "RLN, withdrawBatch: batch size zero");
|
require(batchSize != 0, "RLN, withdrawBatch: batch size zero");
|
||||||
require(
|
require(
|
||||||
batchSize == pubkeyIndexes.length,
|
batchSize == secrets.length,
|
||||||
"RLN, withdrawBatch: batch size mismatch pubkey indexes"
|
"RLN, withdrawBatch: batch size mismatch secrets"
|
||||||
);
|
);
|
||||||
require(
|
require(
|
||||||
batchSize == receivers.length,
|
batchSize == receivers.length,
|
||||||
"RLN, withdrawBatch: batch size mismatch receivers"
|
"RLN, withdrawBatch: batch size mismatch receivers"
|
||||||
);
|
);
|
||||||
for (uint256 i = 0; i < batchSize; i++) {
|
for (uint256 i = 0; i < batchSize; i++) {
|
||||||
_withdraw(secrets[i], pubkeyIndexes[i], receivers[i]);
|
_withdraw(secrets[i], receivers[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function withdraw(
|
function withdraw(uint256 secret, address payable receiver) external {
|
||||||
uint256 secret,
|
_withdraw(secret, receiver);
|
||||||
uint256 _pubkeyIndex,
|
|
||||||
address payable receiver
|
|
||||||
) external {
|
|
||||||
_withdraw(secret, _pubkeyIndex, receiver);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function _withdraw(
|
function withdraw(uint256 secret) external {
|
||||||
uint256 secret,
|
_withdraw(secret);
|
||||||
uint256 _pubkeyIndex,
|
}
|
||||||
address payable receiver
|
|
||||||
) internal {
|
function _withdraw(uint256 secret, address payable receiver) internal {
|
||||||
|
// derive idCommitment
|
||||||
|
uint256 idCommitment = hash(secret);
|
||||||
|
|
||||||
|
// check if member is registered
|
||||||
|
require(members[idCommitment], "RLN, _withdraw: member not registered");
|
||||||
|
|
||||||
|
// check if member has stake
|
||||||
require(
|
require(
|
||||||
_pubkeyIndex < SET_SIZE,
|
stakedAmounts[idCommitment] != 0,
|
||||||
"RLN, _withdraw: invalid pubkey index"
|
"RLN, _withdraw: member has no stake"
|
||||||
);
|
|
||||||
require(
|
|
||||||
members[_pubkeyIndex] != 0,
|
|
||||||
"RLN, _withdraw: member doesn't exist"
|
|
||||||
);
|
);
|
||||||
|
|
||||||
require(
|
require(
|
||||||
receiver != address(0),
|
receiver != address(0),
|
||||||
"RLN, _withdraw: empty receiver address"
|
"RLN, _withdraw: empty receiver address"
|
||||||
);
|
);
|
||||||
|
|
||||||
// derive public key
|
|
||||||
uint256 pubkey = hash(secret);
|
|
||||||
require(
|
|
||||||
members[_pubkeyIndex] == pubkey,
|
|
||||||
"RLN, _withdraw: not verified"
|
|
||||||
);
|
|
||||||
|
|
||||||
// delete member
|
|
||||||
members[_pubkeyIndex] = 0;
|
|
||||||
|
|
||||||
// refund deposit
|
// refund deposit
|
||||||
(bool sent, bytes memory data) = receiver.call{
|
(bool sent, ) = receiver.call{value: stakedAmounts[idCommitment]}("");
|
||||||
value: MEMBERSHIP_DEPOSIT
|
|
||||||
}("");
|
|
||||||
require(sent, "transfer failed");
|
require(sent, "transfer failed");
|
||||||
|
|
||||||
emit MemberWithdrawn(pubkey, _pubkeyIndex);
|
// delete member
|
||||||
|
members[idCommitment] = false;
|
||||||
|
stakedAmounts[idCommitment] = 0;
|
||||||
|
|
||||||
|
emit MemberWithdrawn(idCommitment);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _withdraw(uint256 secret) internal {
|
||||||
|
// derive idCommitment
|
||||||
|
uint256 idCommitment = hash(secret);
|
||||||
|
|
||||||
|
// check if member is registered
|
||||||
|
require(members[idCommitment], "RLN, _withdraw: member not registered");
|
||||||
|
|
||||||
|
require(stakedAmounts[idCommitment] == 0, "RLN, _withdraw: staked");
|
||||||
|
|
||||||
|
// delete member
|
||||||
|
members[idCommitment] = false;
|
||||||
|
|
||||||
|
emit MemberWithdrawn(idCommitment);
|
||||||
}
|
}
|
||||||
|
|
||||||
function hash(uint256 input) internal view returns (uint256) {
|
function hash(uint256 input) internal view returns (uint256) {
|
||||||
|
208
test/rln.ts
208
test/rln.ts
@ -30,7 +30,7 @@ describe("RLN", () => {
|
|||||||
});
|
});
|
||||||
const txRegisterReceipt = await registerTx.wait();
|
const txRegisterReceipt = await registerTx.wait();
|
||||||
|
|
||||||
const pubkey = txRegisterReceipt.events[0].args.pubkey;
|
const pubkey = txRegisterReceipt.events[0].args.idCommitment;
|
||||||
|
|
||||||
// We ensure the registered id_commitment is the one we passed
|
// We ensure the registered id_commitment is the one we passed
|
||||||
expect(
|
expect(
|
||||||
@ -53,31 +53,85 @@ describe("RLN", () => {
|
|||||||
const registerTx = await rln["register(uint256)"](idCommitment, {
|
const registerTx = await rln["register(uint256)"](idCommitment, {
|
||||||
value: price,
|
value: price,
|
||||||
});
|
});
|
||||||
const txRegisterReceipt = await registerTx.wait();
|
await registerTx.wait();
|
||||||
|
|
||||||
const treeIndex = txRegisterReceipt.events[0].args.index;
|
|
||||||
|
|
||||||
// We withdraw our id_commitment
|
// We withdraw our id_commitment
|
||||||
const receiverAddress = "0x000000000000000000000000000000000000dead";
|
const receiverAddress = "0x000000000000000000000000000000000000dead";
|
||||||
const withdrawTx = await rln.withdraw(idSecret, treeIndex, receiverAddress);
|
const withdrawTx = await rln["withdraw(uint256,address)"](
|
||||||
|
idSecret,
|
||||||
|
receiverAddress
|
||||||
|
);
|
||||||
|
|
||||||
const txWithdrawReceipt = await withdrawTx.wait();
|
const txWithdrawReceipt = await withdrawTx.wait();
|
||||||
|
|
||||||
const withdrawalPk = txWithdrawReceipt.events[0].args.pubkey;
|
const withdrawalPk = txWithdrawReceipt.events[0].args.idCommitment;
|
||||||
const withdrawalTreeIndex = txWithdrawReceipt.events[0].args.index;
|
|
||||||
|
|
||||||
// We ensure the registered id_commitment is the one we passed and that the index is the same
|
// We ensure the registered id_commitment is the one we passed and that the index is the same
|
||||||
expect(
|
expect(
|
||||||
withdrawalPk.toHexString() === idCommitment,
|
withdrawalPk.toHexString() === idCommitment,
|
||||||
"withdraw commitment doesn't match registered commitment"
|
"withdraw commitment doesn't match registered commitment"
|
||||||
);
|
);
|
||||||
expect(
|
});
|
||||||
withdrawalTreeIndex.toHexString() === treeIndex.toHexString(),
|
|
||||||
"withdraw index doesn't match registered index"
|
it("should not withdraw stake without address", 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 idSecret =
|
||||||
|
"0x2a09a9fd93c590c26b91effbb2499f07e8f7aa12e2b4940a3aed2411cb65e11c";
|
||||||
|
const idCommitment =
|
||||||
|
"0x0c3ac305f6a4fe9bfeb3eba978bc876e2a99208b8b56c80160cfb54ba8f02368";
|
||||||
|
|
||||||
|
const registerTx = await rln["register(uint256)"](idCommitment, {
|
||||||
|
value: price,
|
||||||
|
});
|
||||||
|
await registerTx.wait();
|
||||||
|
|
||||||
|
// We withdraw our id_commitment
|
||||||
|
const withdrawTx = rln["withdraw(uint256)"](idSecret);
|
||||||
|
|
||||||
|
await expect(withdrawTx).to.be.revertedWith("RLN, _withdraw: staked");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not withdraw withdraw stake if no stake exists", async () => {
|
||||||
|
const rln = await ethers.getContract("RLN", ethers.provider.getSigner(0));
|
||||||
|
|
||||||
|
const validGroupId = createGroupId("github", "silver");
|
||||||
|
const dummySignal = sToBytes32("foo");
|
||||||
|
const dummyNullifierHash = BigNumber.from(0);
|
||||||
|
const dummyExternalNullifier = BigNumber.from(0);
|
||||||
|
const dummyProof = Array(8).fill(BigNumber.from(0));
|
||||||
|
|
||||||
|
const idCommitment = BigNumber.from(
|
||||||
|
"0x0c3ac305f6a4fe9bfeb3eba978bc876e2a99208b8b56c80160cfb54ba8f02368"
|
||||||
|
);
|
||||||
|
const secret =
|
||||||
|
"0x2a09a9fd93c590c26b91effbb2499f07e8f7aa12e2b4940a3aed2411cb65e11c";
|
||||||
|
|
||||||
|
const registerTx = await rln[
|
||||||
|
"register(uint256,bytes32,uint256,uint256,uint256[8],uint256)"
|
||||||
|
](
|
||||||
|
validGroupId,
|
||||||
|
dummySignal,
|
||||||
|
dummyNullifierHash,
|
||||||
|
dummyExternalNullifier,
|
||||||
|
dummyProof,
|
||||||
|
idCommitment
|
||||||
|
);
|
||||||
|
|
||||||
|
await registerTx.wait();
|
||||||
|
|
||||||
|
const address = "0x000000000000000000000000000000000000dead";
|
||||||
|
const withdrawTx = rln["withdraw(uint256,address)"](secret, address);
|
||||||
|
|
||||||
|
await expect(withdrawTx).to.be.revertedWith(
|
||||||
|
"RLN, _withdraw: member has no stake"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip("should not allow multiple registrations with same pubkey", async () => {
|
it("should not allow multiple registrations with same pubkey", async () => {
|
||||||
const rln = await ethers.getContract("RLN", ethers.provider.getSigner(0));
|
const rln = await ethers.getContract("RLN", ethers.provider.getSigner(0));
|
||||||
|
|
||||||
const price = await rln.MEMBERSHIP_DEPOSIT();
|
const price = await rln.MEMBERSHIP_DEPOSIT();
|
||||||
@ -89,22 +143,16 @@ describe("RLN", () => {
|
|||||||
const registerTx = await rln["register(uint256)"](idCommitment, {
|
const registerTx = await rln["register(uint256)"](idCommitment, {
|
||||||
value: price,
|
value: price,
|
||||||
});
|
});
|
||||||
const txRegisterReceipt = await registerTx.wait();
|
await registerTx.wait();
|
||||||
const index1 = txRegisterReceipt.events[0].args.index;
|
|
||||||
|
|
||||||
// Send the same tx again
|
// Send the same tx again
|
||||||
const registerTx2 = await rln["register(uint256)"](idCommitment, {
|
const registerTx2 = rln["register(uint256)"](idCommitment, {
|
||||||
value: price,
|
value: price,
|
||||||
});
|
});
|
||||||
const txRegisterReceipt2 = await registerTx2.wait();
|
|
||||||
const index2 = txRegisterReceipt2.events[0].args.index;
|
|
||||||
|
|
||||||
const pk1 = await rln.members(index1);
|
await expect(registerTx2).to.be.revertedWith(
|
||||||
const pk2 = await rln.members(index2);
|
"RLN, _register: member already registered"
|
||||||
const samePk = pk1.toHexString() === pk2.toHexString();
|
);
|
||||||
if (samePk) {
|
|
||||||
assert(false, "same pubkey registered twice");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("[interep] should register new memberships", async () => {
|
it("[interep] should register new memberships", async () => {
|
||||||
@ -138,7 +186,7 @@ describe("RLN", () => {
|
|||||||
);
|
);
|
||||||
expect(event.args.signal).to.equal(dummySignal);
|
expect(event.args.signal).to.equal(dummySignal);
|
||||||
|
|
||||||
const pubkey = txRegisterReceipt.events[1].args.pubkey;
|
const pubkey = txRegisterReceipt.events[1].args.idCommitment;
|
||||||
expect(pubkey.toHexString() === dummyPubkey.toHexString());
|
expect(pubkey.toHexString() === dummyPubkey.toHexString());
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -254,8 +302,120 @@ describe("RLN", () => {
|
|||||||
|
|
||||||
const txRegisterReceipt = await registerTx.wait();
|
const txRegisterReceipt = await registerTx.wait();
|
||||||
|
|
||||||
expect(txRegisterReceipt.events[1].args.pubkey.toHexString()).to.eql(
|
expect(txRegisterReceipt.events[1].args.idCommitment.toHexString()).to.eql(
|
||||||
BigNumber.from(identity.getCommitment()).toHexString()
|
BigNumber.from(identity.getCommitment()).toHexString()
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("[interep] should revert with invalid proof", async () => {
|
||||||
|
// need to create new fixtures for this test
|
||||||
|
const { PoseidonHasher } = await deployments.fixture("PoseidonHasher");
|
||||||
|
const verifier20Factory = await ethers.getContractFactory("Verifier20");
|
||||||
|
const verifier20 = await verifier20Factory.deploy();
|
||||||
|
await verifier20.deployed();
|
||||||
|
const interepFactory = await ethers.getContractFactory(
|
||||||
|
"Interep",
|
||||||
|
ethers.provider.getSigner(0)
|
||||||
|
);
|
||||||
|
const interep = await interepFactory.deploy([
|
||||||
|
{
|
||||||
|
contractAddress: verifier20.address,
|
||||||
|
merkleTreeDepth: merkleTreeDepth,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
await interep.deployed();
|
||||||
|
const groupTx = await interep.updateGroups(getGroups());
|
||||||
|
await groupTx.wait();
|
||||||
|
|
||||||
|
const validGroupStorageFactory = await ethers.getContractFactory(
|
||||||
|
"ValidGroupStorage"
|
||||||
|
);
|
||||||
|
const validGroupStorage = await validGroupStorageFactory.deploy(
|
||||||
|
interep.address,
|
||||||
|
getValidGroups()
|
||||||
|
);
|
||||||
|
await validGroupStorage.deployed();
|
||||||
|
|
||||||
|
const rlnFactory = await ethers.getContractFactory(
|
||||||
|
"RLN",
|
||||||
|
ethers.provider.getSigner(0)
|
||||||
|
);
|
||||||
|
const rln = await rlnFactory.deploy(
|
||||||
|
1000000000000000,
|
||||||
|
20,
|
||||||
|
PoseidonHasher.address,
|
||||||
|
validGroupStorage.address
|
||||||
|
);
|
||||||
|
|
||||||
|
await rln.deployed();
|
||||||
|
|
||||||
|
const identity = await createInterepIdentity(
|
||||||
|
ethers.provider.getSigner(0),
|
||||||
|
"github"
|
||||||
|
);
|
||||||
|
|
||||||
|
// create a proof to test
|
||||||
|
const proof = await createInterepProof({
|
||||||
|
identity,
|
||||||
|
members: [identity.getCommitment()],
|
||||||
|
groupProvider: "github",
|
||||||
|
groupTier: "silver",
|
||||||
|
signal: sToBytes32("foo"),
|
||||||
|
externalNullifier: 1,
|
||||||
|
snarkArtifacts: {
|
||||||
|
wasmFilePath: "./test/snarkArtifacts/semaphore.wasm",
|
||||||
|
zkeyFilePath: "./test/snarkArtifacts/semaphore.zkey",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// do not update root of group
|
||||||
|
|
||||||
|
const registerTx = rln[
|
||||||
|
"register(uint256,bytes32,uint256,uint256,uint256[8],uint256)"
|
||||||
|
](
|
||||||
|
proof.groupId,
|
||||||
|
proof.signal,
|
||||||
|
proof.publicSignals.nullifierHash,
|
||||||
|
proof.publicSignals.externalNullifier,
|
||||||
|
proof.solidityProof,
|
||||||
|
identity.getCommitment()
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(registerTx).to.be.revertedWith("InvalidProof()");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("[interep] should withdraw a registration", async () => {
|
||||||
|
const rln = await ethers.getContract("RLN", ethers.provider.getSigner(0));
|
||||||
|
|
||||||
|
const validGroupId = createGroupId("github", "silver");
|
||||||
|
const dummySignal = sToBytes32("foo");
|
||||||
|
const dummyNullifierHash = BigNumber.from(0);
|
||||||
|
const dummyExternalNullifier = BigNumber.from(0);
|
||||||
|
const dummyProof = Array(8).fill(BigNumber.from(0));
|
||||||
|
|
||||||
|
const idCommitment = BigNumber.from(
|
||||||
|
"0x0c3ac305f6a4fe9bfeb3eba978bc876e2a99208b8b56c80160cfb54ba8f02368"
|
||||||
|
);
|
||||||
|
const secret =
|
||||||
|
"0x2a09a9fd93c590c26b91effbb2499f07e8f7aa12e2b4940a3aed2411cb65e11c";
|
||||||
|
|
||||||
|
const registerTx = await rln[
|
||||||
|
"register(uint256,bytes32,uint256,uint256,uint256[8],uint256)"
|
||||||
|
](
|
||||||
|
validGroupId,
|
||||||
|
dummySignal,
|
||||||
|
dummyNullifierHash,
|
||||||
|
dummyExternalNullifier,
|
||||||
|
dummyProof,
|
||||||
|
idCommitment
|
||||||
|
);
|
||||||
|
|
||||||
|
await registerTx.wait();
|
||||||
|
|
||||||
|
const withdrawTx = await rln["withdraw(uint256)"](secret);
|
||||||
|
|
||||||
|
const txWithdrawReceipt = await withdrawTx.wait();
|
||||||
|
|
||||||
|
expect(txWithdrawReceipt.events[0].args.idCommitment).to.eql(idCommitment);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user