hackquest logo

Fhenix Poll

Privacy-preserving ranked-choice voting powered by Fully Homomorphic Encryption (FHE) on Fhenix / Arbitrum Sepolia. Vote totals accumulate homomorphically under encryption.

Video

Hình ảnh dự án 1
Hình ảnh dự án 2
Hình ảnh dự án 3
Hình ảnh dự án 4

Công nghệ sử dụng

Node
Fhenix
Solidity
VITE

Sự miêu tả

FhenixPoll

Privacy-preserving ranked-choice voting powered by Fully Homomorphic Encryption (FHE) on Fhenix / Arbitrum Sepolia. Vote totals accumulate homomorphically under encryption the plaintext is only revealed after the poll closes via the Threshold Network.

Deployed contract (Arbitrum Sepolia): 0xE663beAE94fc6eF11f8C37c866D439272dEE7e6c

How it works?

Step

Actor

Action

1

Creator

registerCommunity() → community + membership rules stored on-chain

2

Voter

Connects wallet / OAuth → Verifier checks requirements off-chain

3

Verifier

Returns EIP-712 attestation to voter

4

Voter

issueCredential(attestation) → credential + voting weight stored on-chain

5

Creator

createPoll(), createSimplePoll(), createHierarchicalPoll(), or createSurvey() → FHE tally slots on-chain

6

Voter

castVote(FHE-encrypted weights) / castSimpleVote() / castSurveyVote() → tally updated homomorphically

7

On-chain

Poll closes when endBlock + 2 L1 blocks pass

8

Verifier

requestTallyReveal() or requestSurveyReveal()FHE.allowPublic per option/answer

9

Verifier

decryptForTx(ctHash) per option against the Threshold Network

10

Threshold Network

Returns plaintext + signature

11

Verifier

publishTallyResult(plaintext, sig) or publishSurveyResult() → sig verified on-chain

12

Voter

Reads revealedTallies / surveyRevealedTallies directly from contract → trustless result verification

13

Member

createPost(contentHash) → IPFS content hash stored on-chain (gated)

Features

Communities

  • Create a community with name, description, logo, and credential type

  • Define membership requirements with ANDOR group logic mix token balance, NFT ownership, social follows, Discord roles, GitHub accounts, and more

  • Community metadata pinned to IPFS via Pinata (required for persistence)

  • Only the community creator can create polls

Credentials

  • Verifier checks requirements off-chain, returns an EIP-712 signed attestation

  • Voter's wallet submits attestation to issueCredential() on-chain

  • Credentials have an on-chain expiry block

  • Credentials Hub shows per-community eligibility and lets users claim or renew

Voting

  • Flat polls ranked-choice ballot, voters rank up to 32 options

  • Hierarchical polls options have sub-options (up to 4 levels deep, 8 per parent); option tree stored on-chain with parentId and childCount; sub-category rollup tallies computed on-chain via rolledUpTallies

  • Simple polls single-choice (pick exactly one option); radio button UI, castSimpleVote() encrypts [0,...,votingPower,...,0]

  • Each ranking maps to an encrypted weight submitted to castVote() the contract adds it homomorphically to the running FHE tally

  • Double-vote prevention via on-chain mapping

Surveys

  • Anonymous multi-question surveys each question has 2–10 answer options

  • Responses are FHE-encrypted as euint32(0/1) per answer slot individual responses are never revealed

  • createSurvey() registers questions on-chain with answerCounts[] and labelHashes[]

  • castSurveyVote() accumulates encrypted answers into _surveyTallies[pollId][questionId][answerId]

  • requestSurveyReveal() + publishSurveyResult() same Threshold Network pattern as polls

  • Results page shows per-question bar charts with counts and percentages

Tally & Results

  • After poll closes, requestTallyReveal() calls FHE.allowPublic per option (no FHE.decrypt new pattern)

  • Tally runner calls decryptForTx off-chain, then publishTallyResult with Threshold Network signature

  • Results page reads revealedTallies directly from the contract

  • Hierarchical polls show nested tree results with rolledUpTallies for parent nodes

  • Automated tally runner checks every 60 seconds; manual trigger via POST /admin/tally/:pollId

Community Posts & Articles

  • Credentialed members can publish articles (title + markdown body + cover image)

  • Markdown editor with toolbar (bold, italic, headings, code, links, lists)

  • Article cards with preview text, thumbnail, author, and reading time

  • Full article view with rendered markdown

  • Content stored on IPFS; keccak256(CID) stored on-chain via createPost()

  • Gated communities require a valid credential to post

Social Sharing

  • Share buttons on poll/survey creation success (Twitter/X, Telegram, Copy Link)

  • Share icon on every poll card - one-click copy link

  • Mobile native share via Web Share API

Poll Time Indicators

  • Live countdown timer on poll cards 2d 14h 32m

  • Progress bar showing time elapsed vs total duration (green → amber → red)

  • Pulsing red dot for polls closing within 24 hours

  • "Closed Xm ago" with relative time instead of just "Closed"

  • "Results ready" badge when tally is complete

Voting power decay

Period 1: 100% → Period 2: 50% → Period 3: 25% → Period 4: 12.5% → Period 5: 6.25% → deactivated

CountedVotes (CV) = EligibleVotes (EV) × VotingPower% (VP)

Contract functions

Function

Caller

Description

registerCommunity

Community creator

Register community on-chain

createPoll

Community creator

Create flat ranked-choice poll (2-32 options)

createHierarchicalPoll

Community creator

Create poll with on-chain option tree

createSimplePoll

Community creator

Create single-choice poll

createSurvey

Community creator

Create multi-question anonymous survey

issueCredential

Voter

Submit EIP-712 attestation to get credential

castVote

Voter

Submit FHE-encrypted per-option weights (ranked)

castSimpleVote

Voter

Submit FHE-encrypted single choice

castSurveyVote

Voter

Submit FHE-encrypted answers (flat 0/1 array)

requestTallyReveal

Anyone (after poll ends)

FHE.allowPublic per option

publishTallyResult

Tally runner

Verify Threshold Network sig + write plaintext

requestSurveyReveal

Anyone (after survey ends)

FHE.allowPublic per question×answer

publishSurveyResult

Tally runner

Verify sig + write survey answer count

createPost

Credentialed member

Post content hash on-chain

Security notes

  • Vote totals accumulate homomorphically under FHE, plaintext never exposed until poll ends

  • msg.sender (voter address) is public privacy is about what you voted, not that you voted

  • publishTallyResult verifies the Threshold Network's signature results cannot be forged

  • Survey responses are FHE-encrypted individual answers are never revealed, only aggregate counts

  • FHE.allowPublic (not FHE.decrypt) is the correct pattern per Fhenix SDK v0.5+

  • Creator-only guardrail: only community creator can create polls/surveys (enforced on-chain + UI warning)

Trưởng nhóm
MMayur Asodara
Liên kết dự án
Triển khai Hệ sinh thái
Arbitrum SepoliaArbitrum Sepolia
Ngành
DAOOther