feat(dashboard): enable the Tornado Cash whitelabel with full governance - #2136
Conversation
Serve the Tornado Cash whitelabel from tornado.gov.blockful.io and let TORN join ENS and Shutter as a DAO you can draft, publish, vote on and execute proposals for. Tornado governance is custom: proposals are pre-deployed contracts that the governance delegatecalls on execution, so proposal creation gets a propose(target, description) path that takes the single action's contract address as the proposal contract and rejects multi-action or ETH-sending drafts before they reach the wallet. Execution gets an execute(proposalId) path; there is no queue step since the timelock is built into the governance contract. Voting is fixed for accounts without delegators: castDelegatedVote reverts on-chain with "Can not be empty" for an empty from list, so those voters now go through castVote(proposalId, support) instead. Validated end to end on an anvil mainnet fork with the governance fork test: propose via submitProposalRequest, for and against votes from impersonated locked-balance holders with exact tally matches, then execute via executeProposal after the 2-day execution delay. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
🎨 UI Review
Tornado Cash whitelabel enablementQuestion for author
Validated — no change needed
Out of scope for this review (code, not UI)
Findings: 1 total — 0 must-fix, 1 question for author. Generated by Claude Code |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ae5520130c
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
🚅 Deployed to the anticapture-pr-2136 environment in anticapture-infra
|
…posals Address Codex review: a transfer or arbitrary custom action would create a Tornado proposal whose delegatecalled execution does nothing the DAO reviewed, so publishing now requires the single action to be exactly an executeProposal() call on the pre-deployed proposal contract and rejects anything else before the wallet. Also replace the unsafe unknown cast in the test's contract-writer fake with a properly typed mock. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 564725aff5
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
…test fixtures Hide the Execute button for TORN proposals while they are queued: Tornado proposals stay timelocked for two days after passing and execute(proposalId) reverts until the API advances them to pending_execution, mirroring the existing SHU exclusion in both action-button predicates. Rebuild the voteOnProposal tests on a real viem wallet client over a fake JSON-RPC transport, asserting on the encoded calldata, so the fixtures satisfy the genuine Account and WalletClient contracts with no casts through unknown anywhere in the file. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0c66528d08
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
…solved Address Codex review: a failed delegators request left an empty list that read as a verified solo voter, so the vote fell back to castVote and silently dropped the delegated voting power shown for the account. The voting modal now disables submission and bails out of handleSubmit while the TORN delegator query is loading or errored, and passes the account as a typed json-rpc account instead of casting the address through unknown. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
@codex review |
|
Codex Review: Didn't find any major issues. 👍 Reviewed commit: ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
# Conflicts: # apps/dashboard/features/create-proposal/constants.ts
|
🔍 Vercel preview: https://anticapture-bvhupcc1d-ful.vercel.app |
# Conflicts: # apps/dashboard/features/create-proposal/constants.ts
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ddd22fb6ae
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 93d6e6885f
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| const isTornDelegatorListIncomplete = | ||
| isLoadingTornDelegators || | ||
| isFetchingMoreTornDelegators || | ||
| !!hasMoreTornDelegators; |
There was a problem hiding this comment.
Make delegator pagination deterministic
When a TORN voter has more than 1,000 delegators and multiple delegators have the same amount, this can mark the list complete while still missing addresses. The API applies offset pagination after ordering only by the aggregate amount (apps/api/src/repositories/delegations/delegators.ts:27-51), so tied rows can move between requests; getNextPageParam counts raw rows, while useDelegators and this modal deduplicate repeated addresses. The new pagination loop can therefore reach hasMoreTornDelegators === false after loading totalCount raw rows but fewer unique delegators, and castDelegatedVote silently omits the skipped voting power. Add a stable address tie-breaker to the API ordering or verify the unique-address count against totalCount before enabling submission.
Useful? React with 👍 / 👎.
What
tornado.gov.blockful.ionow resolves to the whitelabel shell (hostnames+whitelabelin dao-config), withgovPlatformpointing at AnticapturecanCreateProposalForDaowith a Tornado-specific propose path: Tornado proposals are pre-deployed contracts that governance delegatecalls on execution, sosubmitProposalRequestsendspropose(target, description)using the single action's contract address as the proposal contract, and rejects multi-action or ETH-sending drafts before they reach the walletsubmitGovernanceActiongains a TORNexecute(proposalId)path (no queue step: the timelock is built into the governance contract)castDelegatedVotereverts on-chain with "Can not be empty" for an emptyfromlist (the code comment claimed empty works). Those voters now go throughcastVote(proposalId, support).Validation
Full lifecycle PASS on an anvil mainnet fork via the governance fork test (#2133), running the dashboard's own transaction code with impersonated locked-balance holders:
The "Can not be empty" revert was reproduced on the fork before the fix and is covered by a new unit test; the Tornado propose path has its own unit tests (single-action guard, ETH guard, event ABI matching the indexer's). Typecheck, lint and the create-proposal + governance + dao-config suites (415 tests) pass.
Notes
🤖 Generated with Claude Code