Inspiration
Collective action has a first-mover problem. The first person to report a manager, sign a union card, or commit to a boycott takes all the risk and gets none of the safety of numbers. The usual fix is a coordinator who collects everyone's early commitments, but whoever holds those commitments can read them, leak them, or be compelled to hand them over. That exposure kills the movement before it reaches critical mass.
We wanted a way for people to commit contingent on others where the commitments stay sealed until enough of them exist. A normal server can't do this, because whoever runs it can peek. That's the gap zero-knowledge fills, so we built it on Midnight.
What it does
Sealed Collective Action lets people privately pledge to act, and each pledge only unlocks when a hidden threshold of matching pledges is reached.
- An organizer creates a campaign with a target and a hidden threshold. Neither is published, only commitments to them go on chain.
- Participants pledge in plain language. An AI assistant phrases the pledge, and only an opaque commitment reaches the chain. The plaintext and the pledger's secret never leave their device.
- Before the threshold, the public ledger shows nothing actionable: no count you can act on, no identities, no target, no sense of how close the campaign is.
- When the threshold is genuinely met, a zero-knowledge proof reveals the target and settles the coordinated action on a second chain, a real transaction on Ethereum Sepolia that anyone can open on Etherscan.
The AI never decides when to act. The proof does. The contract is the enforced guardrail: below the threshold, the reveal fails as a proof and nothing crosses chains.
How we built it
Three layers.
The private core is a Compact contract on Midnight. It stores opaque pledge commitments, uses nullifiers to enforce one distinct pledge per participant, and keeps the target and threshold as salted commitments. A reveal circuit proves the number of distinct pledges has reached the hidden threshold and that the disclosed target matches its commitment, then unlocks. We run the real compiled circuits through the Compact runtime, so the reveal genuinely fails as a proof when the threshold isn't met.
The cross-chain leg is a Solidity settler contract. When the Midnight proof is valid, an AI coordinator relays the verified result to the settler, which records the coordinated action and emits an event. It runs on an in-process EVM for a zero-setup offline demo, and on real Ethereum Sepolia when you supply an RPC and a funded key. Same code, different provider.
The AI layer uses AWS Bedrock Nova to turn a person's messy words into a clean contingent pledge, with a deterministic offline fallback so the whole thing runs without a key. A validation step rejects non-intents so the model never fabricates a pledge from nothing.
On top sits a role-based web UI: an organizer page, an isolated participant page that shows the cause but hides the count, and a coordinator page that shows the Midnight ledger and the EVM settlement side by side.
Challenges we ran into
The hardest part was expressing the threshold logic in Compact without leaking the running count. It took some iteration to land on a design where the count is only ever consulted inside the reveal proof, and the target and threshold live as salted commitments so an observer can't map the on-chain data back to a specific campaign or judge how close it is.
The toolchain also had sharp edges. The compiled contract expected one runtime version while the latest published runtime was newer, so we pinned the runtime to match. The runtime's shipped JavaScript signature for building a circuit context differed from its own type definitions, which cost time to figure out. And two copies of the same underlying library caused instanceof checks to fail across module boundaries until we stopped constructing state objects ourselves and only passed through what the contract returned.
On the cross-chain side, wiring the EVM leg to real Sepolia meant getting gas price above the block base fee and reading the account nonce live instead of tracking it, since even reverted transactions bump it.
Accomplishments that we're proud of
It actually works end to end, and the cross-chain settlement is real, not simulated. There are live Sepolia transactions on record where a Midnight proof triggered an on-chain settlement, verifiable on Etherscan.
The privacy guarantee holds up to inspection: below the threshold, an on-chain observer sees only opaque hashes. We documented the boundary honestly instead of overclaiming.
And it runs from a clean clone with no compiler, no cloud key, and no wallet needed for the offline path, so a judge can try it in a minute.
What we learned
How much of a privacy design lives in what you don't put on the ledger. The interesting decisions were about what stays a commitment, what stays a witness, and what only gets consulted inside a proof. Compact's explicit disclosure rules force you to be deliberate about that, the compiler won't let you write a witness value to the ledger without saying so.
We also learned that "cross-chain" reads very differently to a person watching a demo when the second chain is a real transaction they can click through to, versus a status field flipping to true.
What's next for Herona
- Deploy the Midnight side to the public testnet, not just run the circuits locally.
- Replace the trusted relayer with an on-chain verifier so the second chain checks the Midnight proof directly instead of trusting a coordinator.
- Package the "commit contingent on N others, reveal nothing until N" logic as a reusable primitive an organizer could drop into their own flow.
- Per-participant campaign links so each pledger only ever sees their own view.
Built With
- amazon-web-services
- compact
- ether
- midnight
- node.js
- nova
- solidity
- typescript



Log in or sign up for Devpost to join the conversation.