ArcSeal
Timelock-encrypted voting · live on Arc mainnet

Every vote stays sealed until the clock opens it.

ArcSeal locks each vote to a future drand round. Nobody can read it while voting is open — not the other members, not the contract. When the round arrives, anyone can open every vote at once.

0.0014USDC to seal a vote, gas included
3 sdrand quicknet round period
10 min – 7 dvoting window, set per proposal
0owners, relayers or upgrade keys

An open tally votes for you.

Onchain votes are public the moment they land. The last voters see the score and follow it. ArcSeal keeps the score closed until everyone has voted.

Ordinary onchain vote

TALLY PUBLIC WHILE OPEN
t1Voter 1 → For
1 – 0
t2Voter 2 → For
2 – 0
t3Voter 3 → Against
2 – 1
t4Voter 4 → For
3 – 1
t5Voter 5 → Against
3 – 2

Voters 4 and 5 already know the score. Late voters follow the lead, and deals get made mid-vote.

With ArcSeal

TALLY SEALED UNTIL ROUND N
t1Voter 1 →
? – ?
t2Voter 2 →
? – ?
t3Voter 3 →
? – ?
t4Voter 4 →
? – ?
t5Voter 5 →
? – ?
Nround opens all
3 – 2

Every voter decides blind. The score exists only once, at the close round, for everyone at the same time.

Interactive · one proposal, start to finish

Watch a vote seal and open.

Members
AMember Aproposer
BMember Bmember
CMember Cmember · recipient
Anyoneclicks “Reveal votes”
What Arc storesSealedDAO · 0x789f…2c44
PROPOSAL #1 · TransferUSDCPay 1 USDC to member C
vote · A
vote · B
vote · C
Public tally
drand clock
N − 1,200
Treasury · USDC
2.00

Illustrative walkthrough: the real proofs on mainnet are below.

Anatomy of one sealed vote.

Pick a choice and watch what your browser produces. Two things go onchain, one stays with you. The contract never opens the ciphertext; at reveal it only checks that the opened vote hashes back to the commitment.

In your browser
Your choice
Random salt · 32 bytes
proposal #1 · voter 0x47bD…34E0
CommitmentONCHAIN · 32 BYTES
keccak256(proposalId, voter, choice, salt). Hides the choice now, proves it later — the only thing the contract ever checks.
CiphertextONCHAIN · OPENS AT ROUND N
Nobody can open it before round N, and nobody needs you to open it after.
ReceiptSTAYS IN YOUR BROWSER
Optional. It proves your own vote — which is also why ArcSeal is not coercion-resistant.

Values here are illustrative. The real ones come from @arcseal/sdk in the app.

What the contract promises, and keeps.

SealedDAO is immutable: no owner, no upgrade, no pause. Treasury token, quorum and reveal payment are fixed at deployment.

The hash rules

The contract never parses a ciphertext and runs no onchain BLS check. It only compares hashes at reveal.

No relayer

Any visitor or SDK script can reveal. Nothing in the protocol depends on this site.

Bad items never block

Mismatched, unknown or duplicate items are skipped (RevealSkipped); the rest of the batch still lands.

Pull-only payouts

Payouts are credited, then claimed by their own recipient. A blocklisted address stalls no one.

Quorum ≠ outcome

Quorum counts sealed votes; passing counts revealed ones only. Ties fail. An unrevealed vote is never lost.

No drain without a pass

The reveal payment is credited only for a proposal that met quorum, so a lone member cannot empty the treasury.

Built for Arc

Why Arc.

Arc has no VRF and no timelock service, so ArcSeal brings its own primitive — and leans on what Arc does have.

Gas paid in USDC
Sealing a vote costs about 0.0014 USDC; the reveal payment is paid in the same unit the revealer spends.
Deterministic finality
A sealed vote is final on inclusion, so it counts right after the close with no confirmation depth.
Native USDC treasury
Treasury and gas are the same asset, read through the 6-decimal ERC-20 view at 0x3600…0000.
USDC blocklist
Pull-based claim() means a blocked recipient can never stall a proposal for anyone else.
Privacy, stated plainly

Secret during voting. Public, per address, forever after. This is not anonymity.

propose▲ close round N — reveal, finalize, execute

Proven on mainnet.

PROPOSAL 1 · TransferUSDCPay 1 USDC3 of 3 revealed through the site's button, passed 2–1, executed and claimed · reveal · finalize · execute · claim
✓✓✓✓✓
PROPOSAL 2 · SetMemberAdd a member2 of 2 revealed through the site's button, passed, the DAO now has 4 members · reveal · finalize · execute
✓✓✓✓✓
PROPOSAL 3 · below quorumFails by design1 revealed, 1 garbage item skipped, no payment, finalized as Failed · reveal · finalize
✓✓✓✓

All three proofs ran end to end on 2026-09-18/19, every transaction with status success, 0 votes lost. Finalize and execute came 24 h after the close, when the reveal window ended. The proof DAO's members are wallets the author controls.

What's built

Sealed.solAbstract primitive: hash commitments keyed to a drand round, reveal by hash, no ownerin the suite below
SealedDAO.solMember-list DAO: sealed voting, USDC treasury, pull-based payouts173 tests
@arcseal/tlockVendored tlock-js, quicknet only, Node and browser72 tests
@arcseal/sdkseal, unseal, reveal-all, viem actions for every contract call129 tests
apps/webStatic site: proposals, voting, reveal, treasury77 tests

Read more