From 6b347ff5fba95c7bb5d0b58d55e0c9850c2f484e Mon Sep 17 00:00:00 2001 From: cedoor Date: Wed, 13 Dec 2023 17:56:10 +0000 Subject: [PATCH] refactor(contracts): remove extension contracts --- .../contracts/extensions/SemaphoreVoting.sol | 96 -------- .../extensions/SemaphoreWhistleblowing.sol | 77 ------ .../contracts/interfaces/ISemaphoreVoting.sol | 78 ------ .../interfaces/ISemaphoreWhistleblowing.sol | 53 ----- packages/contracts/hardhat.config.ts | 2 - .../tasks/deploy-semaphore-voting.ts | 78 ------ .../tasks/deploy-semaphore-whistleblowing.ts | 78 ------ packages/contracts/test/SemaphoreVoting.ts | 224 ------------------ .../contracts/test/SemaphoreWhistleblowing.ts | 179 -------------- 9 files changed, 865 deletions(-) delete mode 100644 packages/contracts/contracts/extensions/SemaphoreVoting.sol delete mode 100644 packages/contracts/contracts/extensions/SemaphoreWhistleblowing.sol delete mode 100644 packages/contracts/contracts/interfaces/ISemaphoreVoting.sol delete mode 100644 packages/contracts/contracts/interfaces/ISemaphoreWhistleblowing.sol delete mode 100644 packages/contracts/tasks/deploy-semaphore-voting.ts delete mode 100644 packages/contracts/tasks/deploy-semaphore-whistleblowing.ts delete mode 100644 packages/contracts/test/SemaphoreVoting.ts delete mode 100644 packages/contracts/test/SemaphoreWhistleblowing.ts diff --git a/packages/contracts/contracts/extensions/SemaphoreVoting.sol b/packages/contracts/contracts/extensions/SemaphoreVoting.sol deleted file mode 100644 index 7564fea43..000000000 --- a/packages/contracts/contracts/extensions/SemaphoreVoting.sol +++ /dev/null @@ -1,96 +0,0 @@ -//SPDX-License-Identifier: MIT -pragma solidity 0.8.4; - -import "../interfaces/ISemaphoreVoting.sol"; -import "../interfaces/ISemaphoreVerifier.sol"; -import "../base/SemaphoreGroups.sol"; - -/// @title Semaphore voting contract. -/// @notice It allows users to vote anonymously in a poll. -/// @dev The following code allows you to create polls, add voters and allow them to vote anonymously. -contract SemaphoreVoting is ISemaphoreVoting, SemaphoreGroups { - ISemaphoreVerifier public verifier; - - /// @dev Gets a poll id and returns the poll data. - mapping(uint256 => Poll) internal polls; - - /// @dev Checks if the poll coordinator is the transaction sender. - /// @param pollId: Id of the poll. - modifier onlyCoordinator(uint256 pollId) { - if (polls[pollId].coordinator != _msgSender()) { - revert Semaphore__CallerIsNotThePollCoordinator(); - } - - _; - } - - /// @dev Initializes the Semaphore verifier used to verify the user's ZK proofs. - /// @param _verifier: Semaphore verifier address. - constructor(ISemaphoreVerifier _verifier) { - verifier = _verifier; - } - - /// @dev See {ISemaphoreVoting-createPoll}. - function createPoll(uint256 pollId, address coordinator, uint256 merkleTreeDepth) public override { - if (merkleTreeDepth < 16 || merkleTreeDepth > 32) { - revert Semaphore__MerkleTreeDepthIsNotSupported(); - } - - _createGroup(pollId, merkleTreeDepth); - - polls[pollId].coordinator = coordinator; - - emit PollCreated(pollId, coordinator); - } - - /// @dev See {ISemaphoreVoting-addVoter}. - function addVoter(uint256 pollId, uint256 identityCommitment) public override onlyCoordinator(pollId) { - if (polls[pollId].state != PollState.Created) { - revert Semaphore__PollHasAlreadyBeenStarted(); - } - - _addMember(pollId, identityCommitment); - } - - /// @dev See {ISemaphoreVoting-addVoter}. - function startPoll(uint256 pollId, uint256 encryptionKey) public override onlyCoordinator(pollId) { - if (polls[pollId].state != PollState.Created) { - revert Semaphore__PollHasAlreadyBeenStarted(); - } - - polls[pollId].state = PollState.Ongoing; - - emit PollStarted(pollId, _msgSender(), encryptionKey); - } - - /// @dev See {ISemaphoreVoting-castVote}. - function castVote(uint256 vote, uint256 nullifierHash, uint256 pollId, uint256[8] calldata proof) public override { - if (polls[pollId].state != PollState.Ongoing) { - revert Semaphore__PollIsNotOngoing(); - } - - if (polls[pollId].nullifierHashes[nullifierHash]) { - revert Semaphore__YouAreUsingTheSameNillifierTwice(); - } - - uint256 merkleTreeDepth = getMerkleTreeDepth(pollId); - uint256 merkleTreeRoot = getMerkleTreeRoot(pollId); - - verifier.verifyProof(merkleTreeRoot, nullifierHash, vote, pollId, proof, merkleTreeDepth); - - polls[pollId].nullifierHashes[nullifierHash] = true; - - emit VoteAdded(pollId, vote); - } - - /// @dev See {ISemaphoreVoting-publishDecryptionKey}. - function endPoll(uint256 pollId, uint256 decryptionKey) public override onlyCoordinator(pollId) { - if (polls[pollId].state != PollState.Ongoing) { - revert Semaphore__PollIsNotOngoing(); - } - - polls[pollId].state = PollState.Ended; - - emit PollEnded(pollId, _msgSender(), decryptionKey); - } -} diff --git a/packages/contracts/contracts/extensions/SemaphoreWhistleblowing.sol b/packages/contracts/contracts/extensions/SemaphoreWhistleblowing.sol deleted file mode 100644 index 5a427226e..000000000 --- a/packages/contracts/contracts/extensions/SemaphoreWhistleblowing.sol +++ /dev/null @@ -1,77 +0,0 @@ -//SPDX-License-Identifier: MIT -pragma solidity 0.8.4; - -import "../interfaces/ISemaphoreWhistleblowing.sol"; -import "../interfaces/ISemaphoreVerifier.sol"; -import "../base/SemaphoreGroups.sol"; - -/// @title Semaphore whistleblowing contract. -/// @notice It allows users to leak information anonymously . -/// @dev The following code allows you to create entities for whistleblowers (e.g. non-profit -/// organization, newspaper) and allow them to leak anonymously. -/// Leaks can be IPFS hashes, permanent links or other kinds of references. -contract SemaphoreWhistleblowing is ISemaphoreWhistleblowing, SemaphoreGroups { - ISemaphoreVerifier public verifier; - - /// @dev Gets an entity id and return its editor address. - mapping(uint256 => address) private entities; - - /// @dev Checks if the editor is the transaction sender. - /// @param entityId: Id of the entity. - modifier onlyEditor(uint256 entityId) { - if (entities[entityId] != _msgSender()) { - revert Semaphore__CallerIsNotTheEditor(); - } - - _; - } - - /// @dev Initializes the Semaphore verifier used to verify the user's ZK proofs. - /// @param _verifier: Semaphore verifier address. - constructor(ISemaphoreVerifier _verifier) { - verifier = _verifier; - } - - /// @dev See {ISemaphoreWhistleblowing-createEntity}. - function createEntity(uint256 entityId, address editor, uint256 merkleTreeDepth) public override { - if (merkleTreeDepth < 16 || merkleTreeDepth > 32) { - revert Semaphore__MerkleTreeDepthIsNotSupported(); - } - - _createGroup(entityId, merkleTreeDepth); - - entities[entityId] = editor; - - emit EntityCreated(entityId, editor); - } - - /// @dev See {ISemaphoreWhistleblowing-addWhistleblower}. - function addWhistleblower(uint256 entityId, uint256 identityCommitment) public override onlyEditor(entityId) { - _addMember(entityId, identityCommitment); - } - - /// @dev See {ISemaphoreWhistleblowing-removeWhistleblower}. - function removeWhistleblower( - uint256 entityId, - uint256 identityCommitment, - uint256[] calldata proofSiblings, - uint8[] calldata proofPathIndices - ) public override onlyEditor(entityId) { - _removeMember(entityId, identityCommitment, proofSiblings, proofPathIndices); - } - - /// @dev See {ISemaphoreWhistleblowing-publishLeak}. - function publishLeak( - uint256 leak, - uint256 nullifierHash, - uint256 entityId, - uint256[8] calldata proof - ) public override { - uint256 merkleTreeDepth = getMerkleTreeDepth(entityId); - uint256 merkleTreeRoot = getMerkleTreeRoot(entityId); - - verifier.verifyProof(merkleTreeRoot, nullifierHash, leak, entityId, proof, merkleTreeDepth); - - emit LeakPublished(entityId, leak); - } -} diff --git a/packages/contracts/contracts/interfaces/ISemaphoreVoting.sol b/packages/contracts/contracts/interfaces/ISemaphoreVoting.sol deleted file mode 100644 index f2d15d414..000000000 --- a/packages/contracts/contracts/interfaces/ISemaphoreVoting.sol +++ /dev/null @@ -1,78 +0,0 @@ -//SPDX-License-Identifier: MIT -pragma solidity 0.8.4; - -/// @title SemaphoreVoting contract interface. -interface ISemaphoreVoting { - error Semaphore__CallerIsNotThePollCoordinator(); - error Semaphore__MerkleTreeDepthIsNotSupported(); - error Semaphore__PollHasAlreadyBeenStarted(); - error Semaphore__PollIsNotOngoing(); - error Semaphore__YouAreUsingTheSameNillifierTwice(); - - enum PollState { - Created, - Ongoing, - Ended - } - - struct Verifier { - address contractAddress; - uint256 merkleTreeDepth; - } - - struct Poll { - address coordinator; - PollState state; - mapping(uint256 => bool) nullifierHashes; - } - - /// @dev Emitted when a new poll is created. - /// @param pollId: Id of the poll. - /// @param coordinator: Coordinator of the poll. - event PollCreated(uint256 pollId, address indexed coordinator); - - /// @dev Emitted when a poll is started. - /// @param pollId: Id of the poll. - /// @param coordinator: Coordinator of the poll. - /// @param encryptionKey: Key to encrypt the poll votes. - event PollStarted(uint256 pollId, address indexed coordinator, uint256 encryptionKey); - - /// @dev Emitted when a user votes on a poll. - /// @param pollId: Id of the poll. - /// @param vote: User encrypted vote. - event VoteAdded(uint256 indexed pollId, uint256 vote); - - /// @dev Emitted when a poll is ended. - /// @param pollId: Id of the poll. - /// @param coordinator: Coordinator of the poll. - /// @param decryptionKey: Key to decrypt the poll votes. - event PollEnded(uint256 pollId, address indexed coordinator, uint256 decryptionKey); - - /// @dev Creates a poll and the associated Merkle tree/group. - /// @param pollId: Id of the poll. - /// @param coordinator: Coordinator of the poll. - /// @param merkleTreeDepth: Depth of the tree. - function createPoll(uint256 pollId, address coordinator, uint256 merkleTreeDepth) external; - - /// @dev Adds a voter to a poll. - /// @param pollId: Id of the poll. - /// @param identityCommitment: Identity commitment of the group member. - function addVoter(uint256 pollId, uint256 identityCommitment) external; - - /// @dev Starts a pull and publishes the key to encrypt the votes. - /// @param pollId: Id of the poll. - /// @param encryptionKey: Key to encrypt poll votes. - function startPoll(uint256 pollId, uint256 encryptionKey) external; - - /// @dev Casts an anonymous vote in a poll. - /// @param vote: Encrypted vote. - /// @param nullifierHash: Nullifier hash. - /// @param pollId: Id of the poll. - /// @param proof: Private zk-proof parameters. - function castVote(uint256 vote, uint256 nullifierHash, uint256 pollId, uint256[8] calldata proof) external; - - /// @dev Ends a pull and publishes the key to decrypt the votes. - /// @param pollId: Id of the poll. - /// @param decryptionKey: Key to decrypt poll votes. - function endPoll(uint256 pollId, uint256 decryptionKey) external; -} diff --git a/packages/contracts/contracts/interfaces/ISemaphoreWhistleblowing.sol b/packages/contracts/contracts/interfaces/ISemaphoreWhistleblowing.sol deleted file mode 100644 index 8ff7fcf12..000000000 --- a/packages/contracts/contracts/interfaces/ISemaphoreWhistleblowing.sol +++ /dev/null @@ -1,53 +0,0 @@ -//SPDX-License-Identifier: MIT -pragma solidity 0.8.4; - -/// @title SemaphoreWhistleblowing contract interface. -interface ISemaphoreWhistleblowing { - error Semaphore__CallerIsNotTheEditor(); - error Semaphore__MerkleTreeDepthIsNotSupported(); - - struct Verifier { - address contractAddress; - uint256 merkleTreeDepth; - } - - /// @dev Emitted when a new entity is created. - /// @param entityId: Id of the entity. - /// @param editor: Editor of the entity. - event EntityCreated(uint256 entityId, address indexed editor); - - /// @dev Emitted when a whistleblower publish a new leak. - /// @param entityId: Id of the entity. - /// @param leak: News leak. - event LeakPublished(uint256 indexed entityId, uint256 leak); - - /// @dev Creates an entity and the associated Merkle tree/group. - /// @param entityId: Id of the entity. - /// @param editor: Editor of the entity. - /// @param merkleTreeDepth: Depth of the tree. - function createEntity(uint256 entityId, address editor, uint256 merkleTreeDepth) external; - - /// @dev Adds a whistleblower to an entity. - /// @param entityId: Id of the entity. - /// @param identityCommitment: Identity commitment of the group member. - function addWhistleblower(uint256 entityId, uint256 identityCommitment) external; - - /// @dev Removes a whistleblower from an entity. - /// @param entityId: Id of the entity. - /// @param identityCommitment: Identity commitment of the group member. - /// @param proofSiblings: Array of the sibling nodes of the proof of membership. - /// @param proofPathIndices: Path of the proof of membership. - function removeWhistleblower( - uint256 entityId, - uint256 identityCommitment, - uint256[] calldata proofSiblings, - uint8[] calldata proofPathIndices - ) external; - - /// @dev Allows whistleblowers to publish leaks anonymously. - /// @param leak: News leak. - /// @param nullifierHash: Nullifier hash. - /// @param entityId: Id of the entity. - /// @param proof: Private zk-proof parameters. - function publishLeak(uint256 leak, uint256 nullifierHash, uint256 entityId, uint256[8] calldata proof) external; -} diff --git a/packages/contracts/hardhat.config.ts b/packages/contracts/hardhat.config.ts index 319582c03..9c272d8b2 100644 --- a/packages/contracts/hardhat.config.ts +++ b/packages/contracts/hardhat.config.ts @@ -11,8 +11,6 @@ import "solidity-coverage" import { config } from "./package.json" import "./tasks/accounts" import "./tasks/deploy-semaphore" -import "./tasks/deploy-semaphore-voting" -import "./tasks/deploy-semaphore-whistleblowing" dotenvConfig({ path: resolve(__dirname, "../../.env") }) diff --git a/packages/contracts/tasks/deploy-semaphore-voting.ts b/packages/contracts/tasks/deploy-semaphore-voting.ts deleted file mode 100644 index 249af9fe3..000000000 --- a/packages/contracts/tasks/deploy-semaphore-voting.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { poseidonContract } from "circomlibjs" -import { task, types } from "hardhat/config" - -task("deploy:semaphore-voting", "Deploy a SemaphoreVoting contract") - .addOptionalParam("logs", "Print the logs", true, types.boolean) - .setAction(async ({ logs }, { ethers }): Promise => { - const PairingFactory = await ethers.getContractFactory("Pairing") - const pairing = await PairingFactory.deploy() - - await pairing.deployed() - - if (logs) { - console.info(`Pairing library has been deployed to: ${pairing.address}`) - } - - const SemaphoreVerifierFactory = await ethers.getContractFactory("SemaphoreVerifier", { - libraries: { - Pairing: pairing.address - } - }) - - const semaphoreVerifier = await SemaphoreVerifierFactory.deploy() - - await semaphoreVerifier.deployed() - - if (logs) { - console.info(`SemaphoreVerifier contract has been deployed to: ${semaphoreVerifier.address}`) - } - - const poseidonABI = poseidonContract.generateABI(2) - const poseidonBytecode = poseidonContract.createCode(2) - - const [signer] = await ethers.getSigners() - - const PoseidonFactory = new ethers.ContractFactory(poseidonABI, poseidonBytecode, signer) - const poseidon = await PoseidonFactory.deploy() - - await poseidon.deployed() - - if (logs) { - console.info(`Poseidon library has been deployed to: ${poseidon.address}`) - } - - const IncrementalBinaryTreeFactory = await ethers.getContractFactory("IncrementalBinaryTree", { - libraries: { - PoseidonT3: poseidon.address - } - }) - const incrementalBinaryTree = await IncrementalBinaryTreeFactory.deploy() - - await incrementalBinaryTree.deployed() - - if (logs) { - console.info(`IncrementalBinaryTree library has been deployed to: ${incrementalBinaryTree.address}`) - } - - const SemaphoreVotingFactory = await ethers.getContractFactory("SemaphoreVoting", { - libraries: { - IncrementalBinaryTree: incrementalBinaryTree.address - } - }) - - const semaphoreVoting = await SemaphoreVotingFactory.deploy(semaphoreVerifier.address) - - await semaphoreVoting.deployed() - - if (logs) { - console.info(`SemaphoreVoting contract has been deployed to: ${semaphoreVoting.address}`) - } - - return { - semaphoreVoting, - pairingAddress: pairing.address, - semaphoreVerifierAddress: semaphoreVerifier.address, - poseidonAddress: poseidon.address, - incrementalBinaryTreeAddress: incrementalBinaryTree.address - } - }) diff --git a/packages/contracts/tasks/deploy-semaphore-whistleblowing.ts b/packages/contracts/tasks/deploy-semaphore-whistleblowing.ts deleted file mode 100644 index f16cc6dc1..000000000 --- a/packages/contracts/tasks/deploy-semaphore-whistleblowing.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { poseidonContract } from "circomlibjs" -import { task, types } from "hardhat/config" - -task("deploy:semaphore-whistleblowing", "Deploy a SemaphoreWhistleblowing contract") - .addOptionalParam("logs", "Print the logs", true, types.boolean) - .setAction(async ({ logs }, { ethers }): Promise => { - const PairingFactory = await ethers.getContractFactory("Pairing") - const pairing = await PairingFactory.deploy() - - await pairing.deployed() - - if (logs) { - console.info(`Pairing library has been deployed to: ${pairing.address}`) - } - - const SemaphoreVerifierFactory = await ethers.getContractFactory("SemaphoreVerifier", { - libraries: { - Pairing: pairing.address - } - }) - - const semaphoreVerifier = await SemaphoreVerifierFactory.deploy() - - await semaphoreVerifier.deployed() - - if (logs) { - console.info(`SemaphoreVerifier contract has been deployed to: ${semaphoreVerifier.address}`) - } - - const poseidonABI = poseidonContract.generateABI(2) - const poseidonBytecode = poseidonContract.createCode(2) - - const [signer] = await ethers.getSigners() - - const PoseidonFactory = new ethers.ContractFactory(poseidonABI, poseidonBytecode, signer) - const poseidon = await PoseidonFactory.deploy() - - await poseidon.deployed() - - if (logs) { - console.info(`Poseidon library has been deployed to: ${poseidon.address}`) - } - - const IncrementalBinaryTreeFactory = await ethers.getContractFactory("IncrementalBinaryTree", { - libraries: { - PoseidonT3: poseidon.address - } - }) - const incrementalBinaryTree = await IncrementalBinaryTreeFactory.deploy() - - await incrementalBinaryTree.deployed() - - if (logs) { - console.info(`IncrementalBinaryTree library has been deployed to: ${incrementalBinaryTree.address}`) - } - - const SemaphoreWhistleblowingFactory = await ethers.getContractFactory("SemaphoreWhistleblowing", { - libraries: { - IncrementalBinaryTree: incrementalBinaryTree.address - } - }) - - const semaphoreWhistleblowing = await SemaphoreWhistleblowingFactory.deploy(semaphoreVerifier.address) - - await semaphoreWhistleblowing.deployed() - - if (logs) { - console.info(`SemaphoreWhistleblowing contract has been deployed to: ${semaphoreWhistleblowing.address}`) - } - - return { - semaphoreWhistleblowing, - pairingAddress: pairing.address, - semaphoreVerifierAddress: semaphoreVerifier.address, - poseidonAddress: poseidon.address, - incrementalBinaryTreeAddress: incrementalBinaryTree.address - } - }) diff --git a/packages/contracts/test/SemaphoreVoting.ts b/packages/contracts/test/SemaphoreVoting.ts deleted file mode 100644 index 79423ea92..000000000 --- a/packages/contracts/test/SemaphoreVoting.ts +++ /dev/null @@ -1,224 +0,0 @@ -/* eslint-disable jest/valid-expect */ -import { Group } from "@semaphore-protocol/group" -import { Identity } from "@semaphore-protocol/identity" -import { SemaphoreProof, generateProof } from "@semaphore-protocol/proof" -import { expect } from "chai" -import { Signer } from "ethers" -import { ethers, run } from "hardhat" -import { Pairing, SemaphoreVoting } from "../build/typechain" - -describe("SemaphoreVoting", () => { - let semaphoreVotingContract: SemaphoreVoting - let pairingContract: Pairing - let accounts: Signer[] - let coordinator: string - - const treeDepth = Number(process.env.TREE_DEPTH) || 20 - const pollIds = [1, 2, 3] - const encryptionKey = BigInt(0) - const decryptionKey = BigInt(0) - - const wasmFilePath = `../../snark-artifacts/${treeDepth}/semaphore.wasm` - const zkeyFilePath = `../../snark-artifacts/${treeDepth}/semaphore.zkey` - - before(async () => { - const { semaphoreVoting, pairingAddress } = await run("deploy:semaphore-voting", { - logs: false - }) - - semaphoreVotingContract = semaphoreVoting - pairingContract = await ethers.getContractAt("Pairing", pairingAddress) - - accounts = await ethers.getSigners() - coordinator = await accounts[1].getAddress() - }) - - describe("# createPoll", () => { - it("Should not create a poll with a wrong depth", async () => { - const transaction = semaphoreVotingContract.createPoll(pollIds[0], coordinator, 10) - - await expect(transaction).to.be.revertedWithCustomError( - semaphoreVotingContract, - "Semaphore__MerkleTreeDepthIsNotSupported" - ) - }) - - it("Should create a poll", async () => { - const transaction = semaphoreVotingContract.createPoll(pollIds[0], coordinator, treeDepth) - - await expect(transaction).to.emit(semaphoreVotingContract, "PollCreated").withArgs(pollIds[0], coordinator) - }) - - it("Should not create a poll if it already exists", async () => { - const transaction = semaphoreVotingContract.createPoll(pollIds[0], coordinator, treeDepth) - - await expect(transaction).to.be.revertedWithCustomError( - semaphoreVotingContract, - "Semaphore__GroupAlreadyExists" - ) - }) - }) - - describe("# startPoll", () => { - it("Should not start the poll if the caller is not the coordinator", async () => { - const transaction = semaphoreVotingContract.startPoll(pollIds[0], encryptionKey) - - await expect(transaction).to.be.revertedWithCustomError( - semaphoreVotingContract, - "Semaphore__CallerIsNotThePollCoordinator" - ) - }) - - it("Should start the poll", async () => { - const transaction = semaphoreVotingContract.connect(accounts[1]).startPoll(pollIds[0], encryptionKey) - - await expect(transaction) - .to.emit(semaphoreVotingContract, "PollStarted") - .withArgs(pollIds[0], coordinator, encryptionKey) - }) - - it("Should not start a poll if it has already been started", async () => { - const transaction = semaphoreVotingContract.connect(accounts[1]).startPoll(pollIds[0], encryptionKey) - - await expect(transaction).to.be.revertedWithCustomError( - semaphoreVotingContract, - "Semaphore__PollHasAlreadyBeenStarted" - ) - }) - }) - - describe("# addVoter", () => { - before(async () => { - await semaphoreVotingContract.createPoll(pollIds[1], coordinator, treeDepth) - }) - - it("Should not add a voter if the caller is not the coordinator", async () => { - const { commitment } = new Identity() - - const transaction = semaphoreVotingContract.addVoter(pollIds[0], commitment) - - await expect(transaction).to.be.revertedWithCustomError( - semaphoreVotingContract, - "Semaphore__CallerIsNotThePollCoordinator" - ) - }) - - it("Should not add a voter if the poll has already been started", async () => { - const { commitment } = new Identity() - - const transaction = semaphoreVotingContract.connect(accounts[1]).addVoter(pollIds[0], commitment) - - await expect(transaction).to.be.revertedWithCustomError( - semaphoreVotingContract, - "Semaphore__PollHasAlreadyBeenStarted" - ) - }) - - it("Should add a voter to an existing poll", async () => { - const { commitment } = new Identity("test") - const group = new Group(pollIds[1], treeDepth) - - group.addMember(commitment) - - const transaction = semaphoreVotingContract.connect(accounts[1]).addVoter(pollIds[1], commitment) - - await expect(transaction) - .to.emit(semaphoreVotingContract, "MemberAdded") - .withArgs(pollIds[1], 0, commitment, group.root) - }) - - it("Should return the correct number of poll voters", async () => { - const size = await semaphoreVotingContract.getNumberOfMerkleTreeLeaves(pollIds[1]) - - expect(size).to.be.eq(1) - }) - }) - - describe("# castVote", () => { - const identity = new Identity("test") - const vote = 1 - - const group = new Group(pollIds[1], treeDepth) - - group.addMembers([identity.commitment, BigInt(1)]) - - let fullProof: SemaphoreProof - - before(async () => { - await semaphoreVotingContract.connect(accounts[1]).addVoter(pollIds[1], BigInt(1)) - await semaphoreVotingContract.connect(accounts[1]).startPoll(pollIds[1], encryptionKey) - await semaphoreVotingContract.createPoll(pollIds[2], coordinator, treeDepth) - - fullProof = await generateProof(identity, group, pollIds[1], vote, { - wasmFilePath, - zkeyFilePath - }) - }) - - it("Should not cast a vote if the poll is not ongoing", async () => { - const transaction = semaphoreVotingContract - .connect(accounts[1]) - .castVote(vote, fullProof.nullifierHash, pollIds[2], fullProof.proof) - - await expect(transaction).to.be.revertedWithCustomError( - semaphoreVotingContract, - "Semaphore__PollIsNotOngoing" - ) - }) - - it("Should not cast a vote if the proof is not valid", async () => { - const transaction = semaphoreVotingContract - .connect(accounts[1]) - .castVote(vote, 0, pollIds[1], fullProof.proof) - - await expect(transaction).to.be.revertedWithCustomError(pairingContract, "InvalidProof") - }) - - it("Should cast a vote", async () => { - const transaction = semaphoreVotingContract - .connect(accounts[1]) - .castVote(vote, fullProof.nullifierHash, pollIds[1], fullProof.proof) - - await expect(transaction).to.emit(semaphoreVotingContract, "VoteAdded").withArgs(pollIds[1], vote) - }) - - it("Should not cast a vote twice", async () => { - const transaction = semaphoreVotingContract - .connect(accounts[1]) - .castVote(vote, fullProof.nullifierHash, pollIds[1], fullProof.proof) - - await expect(transaction).to.be.revertedWithCustomError( - semaphoreVotingContract, - "Semaphore__YouAreUsingTheSameNillifierTwice" - ) - }) - }) - - describe("# endPoll", () => { - it("Should not end the poll if the caller is not the coordinator", async () => { - const transaction = semaphoreVotingContract.endPoll(pollIds[1], decryptionKey) - - await expect(transaction).to.be.revertedWithCustomError( - semaphoreVotingContract, - "Semaphore__CallerIsNotThePollCoordinator" - ) - }) - - it("Should end the poll", async () => { - const transaction = semaphoreVotingContract.connect(accounts[1]).endPoll(pollIds[1], encryptionKey) - - await expect(transaction) - .to.emit(semaphoreVotingContract, "PollEnded") - .withArgs(pollIds[1], coordinator, decryptionKey) - }) - - it("Should not end a poll if it has already been ended", async () => { - const transaction = semaphoreVotingContract.connect(accounts[1]).endPoll(pollIds[1], encryptionKey) - - await expect(transaction).to.be.revertedWithCustomError( - semaphoreVotingContract, - "Semaphore__PollIsNotOngoing" - ) - }) - }) -}) diff --git a/packages/contracts/test/SemaphoreWhistleblowing.ts b/packages/contracts/test/SemaphoreWhistleblowing.ts deleted file mode 100644 index adc2b4049..000000000 --- a/packages/contracts/test/SemaphoreWhistleblowing.ts +++ /dev/null @@ -1,179 +0,0 @@ -/* eslint-disable jest/valid-expect */ -import { Group } from "@semaphore-protocol/group" -import { Identity } from "@semaphore-protocol/identity" -import { SemaphoreProof, generateProof } from "@semaphore-protocol/proof" -import { expect } from "chai" -import { Signer, utils } from "ethers" -import { ethers, run } from "hardhat" -import { Pairing, SemaphoreWhistleblowing } from "../build/typechain" - -describe("SemaphoreWhistleblowing", () => { - let semaphoreWhistleblowingContract: SemaphoreWhistleblowing - let pairingContract: Pairing - let accounts: Signer[] - let editor: string - - const treeDepth = Number(process.env.TREE_DEPTH) || 20 - const entityIds = [1, 2] - - const wasmFilePath = `../../snark-artifacts/${treeDepth}/semaphore.wasm` - const zkeyFilePath = `../../snark-artifacts/${treeDepth}/semaphore.zkey` - - before(async () => { - const { semaphoreWhistleblowing, pairingAddress } = await run("deploy:semaphore-whistleblowing", { - logs: false - }) - - semaphoreWhistleblowingContract = semaphoreWhistleblowing - pairingContract = await ethers.getContractAt("Pairing", pairingAddress) - - accounts = await ethers.getSigners() - editor = await accounts[1].getAddress() - }) - - describe("# createEntity", () => { - it("Should not create an entity with a wrong depth", async () => { - const transaction = semaphoreWhistleblowingContract.createEntity(entityIds[0], editor, 10) - - await expect(transaction).to.be.revertedWithCustomError( - semaphoreWhistleblowingContract, - "Semaphore__MerkleTreeDepthIsNotSupported" - ) - }) - - it("Should create an entity", async () => { - const transaction = semaphoreWhistleblowingContract.createEntity(entityIds[0], editor, treeDepth) - - await expect(transaction) - .to.emit(semaphoreWhistleblowingContract, "EntityCreated") - .withArgs(entityIds[0], editor) - }) - - it("Should not create a entity if it already exists", async () => { - const transaction = semaphoreWhistleblowingContract.createEntity(entityIds[0], editor, treeDepth) - - await expect(transaction).to.be.revertedWithCustomError( - semaphoreWhistleblowingContract, - "Semaphore__GroupAlreadyExists" - ) - }) - }) - - describe("# addWhistleblower", () => { - it("Should not add a whistleblower if the caller is not the editor", async () => { - const { commitment } = new Identity() - - const transaction = semaphoreWhistleblowingContract.addWhistleblower(entityIds[0], commitment) - - await expect(transaction).to.be.revertedWithCustomError( - semaphoreWhistleblowingContract, - "Semaphore__CallerIsNotTheEditor" - ) - }) - - it("Should add a whistleblower to an existing entity", async () => { - const { commitment } = new Identity("test") - const group = new Group(entityIds[0], treeDepth) - - group.addMember(commitment) - - const transaction = semaphoreWhistleblowingContract - .connect(accounts[1]) - .addWhistleblower(entityIds[0], commitment) - - await expect(transaction) - .to.emit(semaphoreWhistleblowingContract, "MemberAdded") - .withArgs(entityIds[0], 0, commitment, group.root) - }) - - it("Should return the correct number of whistleblowers of an entity", async () => { - const size = await semaphoreWhistleblowingContract.getNumberOfMerkleTreeLeaves(entityIds[0]) - - expect(size).to.be.eq(1) - }) - }) - - describe("# removeWhistleblower", () => { - it("Should not remove a whistleblower if the caller is not the editor", async () => { - const { commitment } = new Identity() - const group = new Group(entityIds[0], treeDepth) - - group.addMember(commitment) - - const { siblings, pathIndices } = group.generateMerkleProof(0) - - const transaction = semaphoreWhistleblowingContract.removeWhistleblower( - entityIds[0], - commitment, - siblings, - pathIndices - ) - - await expect(transaction).to.be.revertedWithCustomError( - semaphoreWhistleblowingContract, - "Semaphore__CallerIsNotTheEditor" - ) - }) - - it("Should remove a whistleblower from an existing entity", async () => { - const { commitment } = new Identity("test") - const group = new Group(entityIds[0], treeDepth) - - group.addMember(commitment) - - const { siblings, pathIndices } = group.generateMerkleProof(0) - - group.removeMember(0) - - const transaction = semaphoreWhistleblowingContract - .connect(accounts[1]) - .removeWhistleblower(entityIds[0], commitment, siblings, pathIndices) - - await expect(transaction) - .to.emit(semaphoreWhistleblowingContract, "MemberRemoved") - .withArgs(entityIds[0], 0, commitment, group.root) - }) - }) - - describe("# publishLeak", () => { - const identity = new Identity("test") - const leak = utils.formatBytes32String("This is a leak") - - const group = new Group(entityIds[1], treeDepth) - - group.addMembers([identity.commitment, BigInt(1)]) - - let fullProof: SemaphoreProof - - before(async () => { - await semaphoreWhistleblowingContract.createEntity(entityIds[1], editor, treeDepth) - await semaphoreWhistleblowingContract - .connect(accounts[1]) - .addWhistleblower(entityIds[1], identity.commitment) - await semaphoreWhistleblowingContract.connect(accounts[1]).addWhistleblower(entityIds[1], BigInt(1)) - - fullProof = await generateProof(identity, group, entityIds[1], leak, { - wasmFilePath, - zkeyFilePath - }) - }) - - it("Should not publish a leak if the proof is not valid", async () => { - const transaction = semaphoreWhistleblowingContract - .connect(accounts[1]) - .publishLeak(leak, 0, entityIds[1], fullProof.proof) - - await expect(transaction).to.be.revertedWithCustomError(pairingContract, "InvalidProof") - }) - - it("Should publish a leak", async () => { - const transaction = semaphoreWhistleblowingContract - .connect(accounts[1]) - .publishLeak(leak, fullProof.nullifierHash, entityIds[1], fullProof.proof) - - await expect(transaction) - .to.emit(semaphoreWhistleblowingContract, "LeakPublished") - .withArgs(entityIds[1], leak) - }) - }) -})