Skip to content

Commit

Permalink
fix(contracts): fix contract extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
vplasencia committed Aug 9, 2024
1 parent 0dda621 commit 0fcfee6
Show file tree
Hide file tree
Showing 8 changed files with 221 additions and 123 deletions.
4 changes: 4 additions & 0 deletions packages/contracts/contracts/SemaphoreVoting.sol
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ contract SemaphoreVoting is ISemaphoreVoting {

/// @dev See {ISemaphoreVoting-endPoll}.
function endPoll(uint256 pollId, uint256 decryptionKey) public override onlyCoordinator(pollId) {
if (polls[pollId].state != PollState.Ongoing) {
revert SemaphoreVoting__PollIsNotOngoing();
}

polls[pollId].state = PollState.Ended;

emit PollEnded(pollId, msg.sender, decryptionKey);
Expand Down
8 changes: 4 additions & 4 deletions packages/contracts/contracts/SemaphoreWhistleblowing.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ contract SemaphoreWhistleblowing is ISemaphoreWhistleblowing {
}

/// @dev See {ISemaphoreWhistleblowing-createEntity}.
function createEntity(address editor) external {
uint256 groupId = semaphore.createGroup(editor);
function createEntity(address editor) external override {
uint256 groupId = semaphore.createGroup();
entities[groupId] = editor;
emit EntityCreated(groupId, editor);
}
Expand All @@ -46,7 +46,7 @@ contract SemaphoreWhistleblowing is ISemaphoreWhistleblowing {
uint256 entityId,
uint256 identityCommitment,
uint256[] calldata proofSiblings
) external onlyEditor(entityId) {
) external override onlyEditor(entityId) {
semaphore.removeMember(entityId, identityCommitment, proofSiblings);
}

Expand All @@ -58,7 +58,7 @@ contract SemaphoreWhistleblowing is ISemaphoreWhistleblowing {
uint256 merkleTreeDepth,
uint256 merkleTreeRoot,
uint256[8] calldata proof
) external {
) external override {
ISemaphore.SemaphoreProof memory semaphoreProof = ISemaphore.SemaphoreProof({
merkleTreeDepth: merkleTreeDepth,
merkleTreeRoot: merkleTreeRoot,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,10 @@ interface ISemaphoreWhistleblowing {
/// @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
uint256[] calldata proofSiblings
) external;

/// @dev Allows whistleblowers to publish leaks anonymously.
Expand Down
1 change: 1 addition & 0 deletions packages/contracts/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import "dotenv/config"
import { HardhatUserConfig } from "hardhat/config"
import "./tasks/deploy-semaphore-voting"
import "./tasks/deploy-semaphore-whistle-blowing"
import "./tasks/accounts"

const config: HardhatUserConfig = {
solidity: "0.8.23",
Expand Down
10 changes: 6 additions & 4 deletions packages/contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
"deploy:semaphore-whistleblowing": "hardhat deploy:semaphore-whistleblowing",
"verify": "hardhat verify",
"test": "hardhat test",
"test:report-gas": "REPORT_GAS=true hardhat test",
"test:coverage": "hardhat coverage",
"lint": "solhint 'contracts/**/*.sol'"
},
"devDependencies": {
Expand All @@ -19,9 +21,9 @@
"@nomicfoundation/hardhat-network-helpers": "^1.0.0",
"@nomicfoundation/hardhat-toolbox": "^4.0.0",
"@nomicfoundation/hardhat-verify": "^2.0.0",
"@semaphore-protocol/core": "4.0.0-beta.16",
"@semaphore-protocol/hardhat": "4.0.0-beta.16",
"@semaphore-protocol/utils": "4.0.0-beta.16",
"@semaphore-protocol/core": "4.0.1",
"@semaphore-protocol/hardhat": "4.0.1",
"@semaphore-protocol/utils": "4.0.1",
"@typechain/ethers-v6": "^0.5.0",
"@typechain/hardhat": "^9.0.0",
"@types/chai": "^4.2.0",
Expand All @@ -43,7 +45,7 @@
"hardhat-gas-reporter": "^1.0.8",
"prettier": "^3.2.5",
"prettier-plugin-solidity": "^1.3.1",
"solhint": "^4.1.1",
"solhint": "^5.0.3",
"solidity-coverage": "^0.8.1",
"ts-node": "^10.9.2",
"typechain": "^8.3.0",
Expand Down
154 changes: 123 additions & 31 deletions packages/contracts/test/SemaphoreVoting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,22 @@ import { ethers, run } from "hardhat"
import { Signer } from "ethers"
import { loadFixture } from "@nomicfoundation/hardhat-toolbox/network-helpers"
import { Group, Identity, generateProof } from "@semaphore-protocol/core"
import { BigNumber } from "@ethersproject/bignumber"
// @ts-ignore
import { SemaphoreVoting } from "../typechain-types"

describe("SemaphoreVoting", () => {
async function deploySemaphoreVotingFixture() {
const semaphoreVoting = await run("deploy:semaphore-voting", {
const { semaphore } = await run("deploy:semaphore", {
logs: false
})

const semaphoreVoting = await run("deploy:semaphore-voting", {
logs: false,
semaphore: await semaphore.getAddress()
})

const semaphoreContract = semaphore

const SemaphoreVotingContract: SemaphoreVoting = semaphoreVoting

const accounts = await run("accounts", { logs: false })
Expand All @@ -21,21 +27,30 @@ describe("SemaphoreVoting", () => {
const coordinator = accounts[0]
const voter = accounts[1]
const identity = new Identity()
const groupId = BigNumber.from(0)
const group = new Group(groupId)
const group = new Group()
group.addMember(identity.commitment)
const vote = ethers.keccak256(ethers.toUtf8Bytes("vote"))
const proof = await generateProof(identity, group, 0, vote)

return { SemaphoreVotingContract, coordinator, voter, identity, group, vote, proof, accountAddresses }
const proof = await generateProof(identity, group, vote, 0)

return {
SemaphoreVotingContract,
coordinator,
voter,
identity,
group,
vote,
proof,
accountAddresses,
semaphoreContract
}
}

describe("# createPoll", () => {
it("Should create a poll", async () => {
const { SemaphoreVotingContract, coordinator } = await loadFixture(deploySemaphoreVotingFixture)

const pollId = 0
const transaction = await SemaphoreVotingContract.createPoll(pollId, coordinator.address)
const transaction = await SemaphoreVotingContract.createPoll(coordinator.address)

await expect(transaction)
.to.emit(SemaphoreVotingContract, "PollCreated")
Expand All @@ -45,28 +60,46 @@ describe("SemaphoreVoting", () => {

describe("# addVoter", () => {
it("Should add a voter to a poll", async () => {
const { SemaphoreVotingContract, coordinator, identity } = await loadFixture(deploySemaphoreVotingFixture)
const { SemaphoreVotingContract, coordinator, identity, group, semaphoreContract } =
await loadFixture(deploySemaphoreVotingFixture)

const pollId = 0
await SemaphoreVotingContract.createPoll(pollId, coordinator.address)
await SemaphoreVotingContract.createPoll(coordinator.address)

const transaction = await SemaphoreVotingContract.addVoter(pollId, identity.commitment)

await expect(transaction).to.emit(SemaphoreVotingContract, "MemberAdded")
await expect(transaction)
.to.emit(semaphoreContract, "MemberAdded")
.withArgs(pollId, 0, identity.commitment, group.root)
})

it("Should not add a voter to a poll that has already been started", async () => {
const { SemaphoreVotingContract, coordinator, identity } = await loadFixture(deploySemaphoreVotingFixture)

const pollId = 0
await SemaphoreVotingContract.createPoll(pollId, coordinator.address)
await SemaphoreVotingContract.createPoll(coordinator.address)
await SemaphoreVotingContract.startPoll(pollId, 0)

const transaction = SemaphoreVotingContract.addVoter(pollId, identity.commitment)

await expect(transaction).to.be.revertedWithCustomError(
SemaphoreVotingContract,
"Semaphore__PollHasAlreadyBeenStarted"
"SemaphoreVoting__PollHasAlreadyBeenStarted"
)
})

it("Should not add a voter to a poll if the coordinator is not correct", async () => {
const { SemaphoreVotingContract, coordinator, identity, voter } =
await loadFixture(deploySemaphoreVotingFixture)

const pollId = 0
await SemaphoreVotingContract.createPoll(coordinator.address)

const transaction = SemaphoreVotingContract.connect(voter).addVoter(pollId, identity.commitment)

await expect(transaction).to.be.revertedWithCustomError(
SemaphoreVotingContract,
"SemaphoreVoting__CallerIsNotThePollCoordinator"
)
})
})
Expand All @@ -76,7 +109,7 @@ describe("SemaphoreVoting", () => {
const { SemaphoreVotingContract, coordinator } = await loadFixture(deploySemaphoreVotingFixture)

const pollId = 0
await SemaphoreVotingContract.createPoll(pollId, coordinator.address)
await SemaphoreVotingContract.createPoll(coordinator.address)

const transaction = await SemaphoreVotingContract.startPoll(pollId, 0)

Expand All @@ -87,62 +120,106 @@ describe("SemaphoreVoting", () => {
const { SemaphoreVotingContract, coordinator } = await loadFixture(deploySemaphoreVotingFixture)

const pollId = 0
await SemaphoreVotingContract.createPoll(pollId, coordinator.address)
await SemaphoreVotingContract.createPoll(coordinator.address)
await SemaphoreVotingContract.startPoll(pollId, 0)

const transaction = SemaphoreVotingContract.startPoll(pollId, 0)

await expect(transaction).to.be.revertedWithCustomError(
SemaphoreVotingContract,
"Semaphore__PollHasAlreadyBeenStarted"
"SemaphoreVoting__PollHasAlreadyBeenStarted"
)
})

it("Should not start a poll if the caller is not poll coordinator", async () => {
const { SemaphoreVotingContract, voter } = await loadFixture(deploySemaphoreVotingFixture)

const pollId = 0
await SemaphoreVotingContract.createPoll(voter.address)
const transaction = SemaphoreVotingContract.startPoll(pollId, 0)

await expect(transaction).to.be.revertedWithCustomError(
SemaphoreVotingContract,
"SemaphoreVoting__CallerIsNotThePollCoordinator"
)
})
})

describe("# castVote", () => {
it("Should allow a voter to cast a vote", async () => {
const { SemaphoreVotingContract, coordinator, identity, vote, proof } =
const { SemaphoreVotingContract, coordinator, identity, vote, proof, group } =
await loadFixture(deploySemaphoreVotingFixture)

const pollId = 0
await SemaphoreVotingContract.createPoll(pollId, coordinator.address)
await SemaphoreVotingContract.createPoll(coordinator.address)
await SemaphoreVotingContract.addVoter(pollId, identity.commitment)
await SemaphoreVotingContract.startPoll(pollId, 0)

const transaction = await SemaphoreVotingContract.castVote(vote, proof.nullifier, pollId, proof.proof)
const transaction = await SemaphoreVotingContract.castVote(
vote,
pollId,
proof.merkleTreeDepth,
proof.nullifier,
group.root,
proof.points
)

await expect(transaction).to.emit(SemaphoreVotingContract, "VoteAdded")
})

it("Should not allow a voter to cast a vote twice", async () => {
const { SemaphoreVotingContract, coordinator, identity, vote, proof } =
const { SemaphoreVotingContract, coordinator, identity, vote, proof, group, semaphoreContract } =
await loadFixture(deploySemaphoreVotingFixture)

const pollId = 0
await SemaphoreVotingContract.createPoll(pollId, coordinator.address)
await SemaphoreVotingContract.createPoll(coordinator.address)
await SemaphoreVotingContract.addVoter(pollId, identity.commitment)
await SemaphoreVotingContract.startPoll(pollId, 0)
await SemaphoreVotingContract.castVote(vote, proof.nullifier, pollId, proof.proof)
await SemaphoreVotingContract.castVote(
vote,
pollId,
proof.merkleTreeDepth,
proof.nullifier,
group.root,
proof.points
)

const transaction = SemaphoreVotingContract.castVote(vote, proof.nullifier, pollId, proof.proof)
const transaction = SemaphoreVotingContract.castVote(
vote,
pollId,
group.depth,
proof.nullifier,
group.root,
proof.points
)

await expect(transaction).to.be.revertedWithCustomError(
SemaphoreVotingContract,
semaphoreContract,
"Semaphore__YouAreUsingTheSameNullifierTwice"
)
})

it("Should not allow a voter to cast a vote in a poll that is not ongoing", async () => {
const { SemaphoreVotingContract, coordinator, identity, vote, proof } =
const { SemaphoreVotingContract, coordinator, identity, vote, proof, group } =
await loadFixture(deploySemaphoreVotingFixture)

const pollId = 0
await SemaphoreVotingContract.createPoll(pollId, coordinator.address)
await SemaphoreVotingContract.createPoll(coordinator.address)
await SemaphoreVotingContract.addVoter(pollId, identity.commitment)

const transaction = SemaphoreVotingContract.castVote(vote, proof.nullifier, pollId, proof.proof)
const transaction = SemaphoreVotingContract.castVote(
vote,
pollId,
group.depth,
proof.nullifier,
group.root,
proof.points
)

await expect(transaction).to.be.revertedWithCustomError(SemaphoreVoting, "Semaphore__PollIsNotOngoing")
await expect(transaction).to.be.revertedWithCustomError(
SemaphoreVotingContract,
"SemaphoreVoting__PollIsNotOngoing"
)
})
})

Expand All @@ -151,7 +228,7 @@ describe("SemaphoreVoting", () => {
const { SemaphoreVotingContract, coordinator } = await loadFixture(deploySemaphoreVotingFixture)

const pollId = 0
await SemaphoreVotingContract.createPoll(pollId, coordinator.address)
await SemaphoreVotingContract.createPoll(coordinator.address)
await SemaphoreVotingContract.startPoll(pollId, 0)

const transaction = await SemaphoreVotingContract.endPoll(pollId, 0)
Expand All @@ -163,13 +240,28 @@ describe("SemaphoreVoting", () => {
const { SemaphoreVotingContract, coordinator } = await loadFixture(deploySemaphoreVotingFixture)

const pollId = 0
await SemaphoreVotingContract.createPoll(pollId, coordinator.address)
await SemaphoreVotingContract.createPoll(coordinator.address)

const transaction = SemaphoreVotingContract.endPoll(pollId, 0)

await expect(transaction).to.be.revertedWithCustomError(
SemaphoreVotingContract,
"Semaphore__PollIsNotOngoing"
"SemaphoreVoting__PollIsNotOngoing"
)
})

it("Should not end a poll if the coordinator is not correct", async () => {
const { SemaphoreVotingContract, coordinator, voter } = await loadFixture(deploySemaphoreVotingFixture)

const pollId = 0
await SemaphoreVotingContract.createPoll(coordinator.address)
await SemaphoreVotingContract.startPoll(pollId, 0)

const transaction = SemaphoreVotingContract.connect(voter).endPoll(pollId, 0)

await expect(transaction).to.be.revertedWithCustomError(
SemaphoreVotingContract,
"SemaphoreVoting__CallerIsNotThePollCoordinator"
)
})
})
Expand Down
Loading

0 comments on commit 0fcfee6

Please sign in to comment.