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




Công nghệ sử dụng
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 |
|
2 | Voter | Connects wallet / OAuth → Verifier checks requirements off-chain |
3 | Verifier | Returns EIP-712 attestation to voter |
4 | Voter |
|
5 | Creator |
|
6 | Voter |
|
7 | On-chain | Poll closes when |
8 | Verifier |
|
9 | Verifier |
|
10 | Threshold Network | Returns |
11 | Verifier |
|
12 | Voter | Reads |
13 | Member |
|
Features
Communities
Create a community with name, description, logo, and credential type
Define membership requirements with
ANDORgroup logic mix token balance, NFT ownership, social follows, Discord roles, GitHub accounts, and moreCommunity 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-chainCredentials 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
parentIdandchildCount; sub-category rollup tallies computed on-chain viarolledUpTalliesSimple 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 tallyDouble-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 revealedcreateSurvey()registers questions on-chain withanswerCounts[]andlabelHashes[]castSurveyVote()accumulates encrypted answers into_surveyTallies[pollId][questionId][answerId]requestSurveyReveal()+publishSurveyResult()same Threshold Network pattern as pollsResults page shows per-question bar charts with counts and percentages
Tally & Results
After poll closes,
requestTallyReveal()callsFHE.allowPublicper option (noFHE.decryptnew pattern)Tally runner calls
decryptForTxoff-chain, thenpublishTallyResultwith Threshold Network signatureResults page reads
revealedTalliesdirectly from the contractHierarchical polls show nested tree results with
rolledUpTalliesfor parent nodesAutomated 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 viacreatePost()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 32mProgress 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 |
|---|---|---|
| Community creator | Register community on-chain |
| Community creator | Create flat ranked-choice poll (2-32 options) |
| Community creator | Create poll with on-chain option tree |
| Community creator | Create single-choice poll |
| Community creator | Create multi-question anonymous survey |
| Voter | Submit EIP-712 attestation to get credential |
| Voter | Submit FHE-encrypted per-option weights (ranked) |
| Voter | Submit FHE-encrypted single choice |
| Voter | Submit FHE-encrypted answers (flat 0/1 array) |
| Anyone (after poll ends) |
|
| Tally runner | Verify Threshold Network sig + write plaintext |
| Anyone (after survey ends) |
|
| Tally runner | Verify sig + write survey answer count |
| 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 votedpublishTallyResultverifies the Threshold Network's signature results cannot be forgedSurvey responses are FHE-encrypted individual answers are never revealed, only aggregate counts
FHE.allowPublic(notFHE.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)