Skip to content

feat(dashboard): renew ENS security council term, add Compound proposal guardian - #2097

Open
alextnetto wants to merge 2 commits into
devfrom
feat/security-council-renewal-comp-guardian
Open

feat(dashboard): renew ENS security council term, add Compound proposal guardian#2097
alextnetto wants to merge 2 commits into
devfrom
feat/security-council-renewal-comp-guardian

Conversation

@alextnetto

Copy link
Copy Markdown
Member

What

The ENS Security Council card on /ens was showing an expired term (ended 2026-07-24). ENS has since seated a new council, so this points the card at it — and adds Compound's Proposal Guardian to the same card, which had no entry at all.

Data (verified on-chain, mainnet)

ENS

Old (in config) New
SecurityCouncil contract 0xb8fa0ce3…3ee0 (config had 0x552DF471…2a95) 0x2acBf518b3759f6e1fA163294eda55bF1d0ae051
Safe multisig 0xaA5cD05f…2Cc7 (4/8) 0x7101B78638e34444F0a5AdE9e1149fbEeC029931 (5/8)
expiration() 1784919179 → 2026-07-24 18:52:59 UTC 1847389751 → 2028-07-16 19:49:11 UTC
Term start July 1, 2024 (approx.) 2026-07-22 05:44:59 UTC
  • RoleGranted(PROPOSER_ROLE, 0x2acB…e051) on the ENS timelock 0xFe89cc7a…44b7 at block 25586264 (ts 1784699099), tx 0xb2f732c433471ce5274c77d1fe04bd060389319a3b32dfa26ee16164ef46812f — used as the term start date.
  • 0x2acB…e051: owner() = 0x7101B786…9931, timelock() = 0xFe89cc7a…44b7, expiration() = 1847389751. Safe reports getThreshold() = 5, 8 owners.
  • Matches the reported "two-year term until July 16, 2028, 5-of-8".

Note: the previous council contract still holds PROPOSER_ROLE (no RoleRevoked emitted) — nobody has called renounceTimelockRoleByExpiration() yet — but its expiration() has passed, so it can no longer cancel.

Compound

CompoundGovernor.proposalGuardian() on 0x309a862b…c8C0 returns:

  • account 0xbbf3f1421D886E9b2c5D716B5192aC998af2012c (Compound Community Multisig, getThreshold() = 5, 9 owners)
  • expiration 1898467200 → 2030-02-28 00:00:00 UTC

Extension history from ProposalGuardianSet events:

Block New expiry
21688680 2025-02-17
22179688 2025-09-11
23418776 2026-09-12
24492577 (ts 1771524383, 2026-02-19) 2030-02-28 ← current

Term start uses the block time of the most recent extension (2026-02-19).

Changes

  • shared/dao-config/ens.ts — new council address, 5/8 Safe, new start/expiration.
  • shared/dao-config/comp.ts — new securityCouncil entry for the Proposal Guardian.
  • shared/dao-config/types.ts — optional label (card heading) and multisig.description (tooltip).
  • SecurityCouncilCard.tsx / ProgressBar.tsx — heading and multisig tooltip were hardcoded to ENS's wording and 4-of-8 numbers; both now read from config, so Compound renders "PROPOSAL GUARDIAN" with its own copy.

Also fixed in passing

comp.ts SECURITY_COUNCIL.impact said "4/8 multisig approval". The Community Multisig is 5-of-9 on-chain, and leaving it would have contradicted the new card. Updated to 5/9. The adjacent requirements line ("raise the threshold to 75%") is unchanged — 5/9 is 55%, so the recommendation still stands.

Verification

  • Typecheck (tsc --noEmit) and ESLint/Prettier clean on all touched files. The repo-wide pnpm dashboard typecheck fails on pre-existing errors from @anticapture/client codegen (needs network to reach the Gateful spec) — unrelated to this diff and unchanged by it.
  • Progress-bar math sanity-checked against today's date: ENS ~1.2% elapsed with the danger zone at 87.7%; Compound ~11% elapsed with the danger zone at 93.9%.
  • Not rendered in a browser — no local .env for the dashboard. The card is pure config with no data fetching.

…al guardian

ENS seated a new Security Council in July 2026 after the previous one's
veto power expired on 2026-07-24. Point the card at the new
SecurityCouncil contract (0x2acB...e051, PROPOSER_ROLE granted
2026-07-22, expiration() = 1847389751 / 2028-07-16) and its 5-of-8 Safe
(0x7101...9931).

Add Compound's Proposal Guardian to the same card:
CompoundGovernor.proposalGuardian() returns the Community Multisig
(0xbbf3...012c, 5-of-9) with expiry 1898467200 / 2030-02-28, last
extended on 2026-02-19.

The card heading and multisig tooltip were hardcoded to ENS's wording and
4-of-8 numbers, so both now come from the DAO config.
@vercel

vercel Bot commented Jul 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
anticapture-storybook Ready Ready Preview Jul 31, 2026 11:03pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
anticapture Ignored Ignored Jul 31, 2026 11:03pm

Request Review

@railway-app

railway-app Bot commented Jul 30, 2026

Copy link
Copy Markdown

🚅 Deployed to the anticapture-pr-2097 environment in anticapture-infra

Service Status Web Updated (UTC)
prometheus ✅ Success (View Logs) Jul 31, 2026 at 11:02 pm
otelcol ✅ Success (View Logs) Jul 31, 2026 at 11:02 pm
authful ✅ Success (View Logs) Web Jul 31, 2026 at 11:01 pm
alertmanager ✅ Success (View Logs) Web Jul 31, 2026 at 11:01 pm
grafana ✅ Success (View Logs) Web Jul 31, 2026 at 11:01 pm
gateful ✅ Success (View Logs) Web Jul 31, 2026 at 11:01 pm
loki ✅ Success (View Logs) Jul 31, 2026 at 11:01 pm
tempo ✅ Success (View Logs) Jul 31, 2026 at 11:01 pm
uniswap-indexer-offchain ✅ Success (View Logs) Jul 30, 2026 at 10:13 pm
ens-indexer-offchain ✅ Success (View Logs) Jul 30, 2026 at 10:10 pm
compound-indexer-offchain ✅ Success (View Logs) Jul 30, 2026 at 10:09 pm
shutter-indexer-offchain ✅ Success (View Logs) Jul 30, 2026 at 10:09 pm
gitcoin-indexer-offchain ✅ Success (View Logs) Jul 30, 2026 at 10:04 pm
mcp ✅ Success (View Logs) Web Jul 30, 2026 at 8:11 pm
docs ✅ Success (View Logs) Web Jul 30, 2026 at 8:11 pm
obol-api ✅ Success (View Logs) Jul 30, 2026 at 8:11 pm
tornado-api ✅ Success (View Logs) Jul 30, 2026 at 8:10 pm
aave-api ✅ Success (View Logs) Jul 30, 2026 at 8:10 pm
lil-nouns-indexer ✅ Success (View Logs) Jul 30, 2026 at 8:10 pm
compound-api ✅ Success (View Logs) Jul 30, 2026 at 8:10 pm
nouns-indexer ✅ Success (View Logs) Jul 30, 2026 at 8:10 pm
address-enrichment ✅ Success (View Logs) Web Jul 30, 2026 at 8:10 pm
aave-indexer ✅ Success (View Logs) Jul 30, 2026 at 8:10 pm
fluid-indexer ✅ Success (View Logs) Jul 30, 2026 at 8:10 pm
uniswap-api ✅ Success (View Logs) Jul 30, 2026 at 8:10 pm
gitcoin-api ✅ Success (View Logs) Jul 30, 2026 at 8:10 pm
scroll-indexer ✅ Success (View Logs) Jul 30, 2026 at 8:10 pm
lil-nouns-api ✅ Success (View Logs) Jul 30, 2026 at 8:10 pm
gitcoin-indexer ✅ Success (View Logs) Jul 30, 2026 at 8:10 pm
tornado-indexer ✅ Success (View Logs) Jul 30, 2026 at 8:10 pm
uniswap-indexer ✅ Success (View Logs) Jul 30, 2026 at 8:10 pm
obol-indexer ✅ Success (View Logs) Jul 30, 2026 at 8:10 pm
ens-api ✅ Success (View Logs) Jul 30, 2026 at 8:10 pm
fluid-api ✅ Success (View Logs) Jul 30, 2026 at 8:10 pm
nouns-api ✅ Success (View Logs) Jul 30, 2026 at 8:10 pm
compound-indexer ✅ Success (View Logs) Jul 30, 2026 at 8:10 pm
ens-indexer ✅ Success (View Logs) Jul 30, 2026 at 8:10 pm
shutter-api ✅ Success (View Logs) Jul 30, 2026 at 8:10 pm
shutter-indexer ✅ Success (View Logs) Jul 30, 2026 at 8:10 pm
ens-relayer ✅ Success (View Logs) Jul 30, 2026 at 8:10 pm
erpc ✅ Success (View Logs) Web Jul 30, 2026 at 8:09 pm
nodeful ✅ Success (View Logs) Jul 30, 2026 at 8:09 pm
user-api ✅ Success (View Logs) Web Jul 30, 2026 at 8:07 pm
scroll-api ✅ Success (View Logs) Jul 30, 2026 at 8:07 pm

Copy link
Copy Markdown
Collaborator

🎨 UI Review

Automated review · Figma: not found (searched PR body/comments, the two preconfigured ClickUp lists, and a workspace-wide search for "security council renewal Compound guardian") · No linked ClickUp task found either.
ℹ️ Reviewed without a Figma reference — grounded in diff review + UX-expert evaluation. The anticapture dashboard Vercel deployment for this PR shows as Ignored (only the unrelated anticapture-storybook build deployed), matching the author's own note that this wasn't rendered in a browser — so there's no live preview to check either. Findings below are [Code-only].


DAO Overview — Security Council / Proposal Guardian card

Nice-to-have — naming inconsistency introduced by this PR
This PR establishes "Proposal Guardian" as Compound's official display name for this entity (securityCouncil.label on the Overview card, and the existing currentSetting copy). But the impact string in the same file's GovernanceImplementationEnum.SECURITY_COUNCIL block — the exact line this PR edits to bump 4/85/9 — still reads "The Security Council can protect the DAO from malicious proposals by canceling them after the 5/9 multisig approval." Same entity, two names on the same DAO page. Since the diff already touches this string, worth renaming it to "Proposal Guardian" here too (apps/dashboard/shared/dao-config/comp.ts, the impact line under SECURITY_COUNCIL). The neighboring requirements line and the VETO_STRATEGY.impact line in the same file also say "Security Council" for Compound — out of scope for this diff, but a follow-up copy pass would fully align it.

Question for author — fallback tooltip copy assumes Timelock-based cancellation
SecurityCouncilCard.tsx's new default tooltip text is generic but hardcodes the mechanism: "...to execute a cancel transaction for an approved proposal in the Timelock contract." That's accurate for ENS (cancels via its Timelock), and Compound correctly opts out with an explicit multisig.description override noting it cancels "on the Governor contract" instead. But any future DAO added with a securityCouncil entry and no explicit multisig.description will silently get this ENS-specific wording even if their guardian cancels elsewhere (as Compound's does). Since this PR is what generalizes the card to multiple DAOs, might be worth flagging that this fallback is safe today only because both current entries either match it (ENS) or override it (Compound) — a comment on the types.ts description? field noting "required if the cancellation path isn't a Timelock" would prevent a silent copy bug for the next DAO.

Mobile

No layout changes in this diff (only copy/data become dynamic instead of hardcoded), and no live preview was reachable to double-check — nothing new to verify here.

Design-system adherence

No issues — the diff reuses existing DS primitives (TooltipInfo, UnderlinedLink, DividerDefault) and doesn't hand-roll anything new.

Scope note

This is a UI-only review (copy accuracy, visual fidelity, DS adherence) — architecture, on-chain data verification, and other code-quality concerns are left to the code reviewer.


Generated by Claude Code

@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

🔍 Vercel preview: https://anticapture-29ojdwwbx-ful.vercel.app

…sistently

Review follow-up. The Overview card now labels it "Proposal Guardian",
so the Risk Analysis copy on the same page shouldn't call the same
multisig a "Security Council". The L2Beat line keeps that wording since
it names an external standard.

Also document that the fallback multisig tooltip assumes cancellation
happens on the Timelock, so the next DAO whose guardian cancels
elsewhere doesn't silently inherit wrong copy.
@alextnetto

Copy link
Copy Markdown
Member Author

Thanks — both points were valid, addressed in 899fbe6.

1. Naming inconsistency. Fixed, and extended slightly past the one line you flagged. Renamed to "Proposal Guardian" in comp.ts:

  • SECURITY_COUNCIL.impact — "The Security Council can protect…" → "The Proposal Guardian can protect…"
  • SECURITY_COUNCIL.requirements — "The Compound Security Council needs to raise the threshold…"
  • VETO_STRATEGY.impact — "Compound can veto malicious proposals with the Security Council."

One deliberate exception: SECURITY_COUNCIL.nextStep still reads "Follow L2Beat's standards to have a more secure Security Council." That one names an external standard — L2Beat publishes a Security Council standard, not a Proposal Guardian one — so renaming it would break the reference. The section heading also stays "Security Council" since it comes from GOVERNANCE_IMPLEMENTATION_CONSTANTS and is shared across every DAO.

2. Timelock assumption in the fallback tooltip. Good catch — documented on the description? field in types.ts rather than leaving it implicit:

/**
 * Tooltip next to the multisig link. Falls back to a generated
 * description that assumes cancellation happens on the Timelock, so set
 * this explicitly whenever the cancellation path is somewhere else
 * (Compound's guardian, for instance, cancels on the Governor).
 */
description?: string;

I considered making the mechanism a required field instead of a documented default, but that would force every existing and future DAO to restate the common case. A comment felt like the right weight for two entries.

On the preview: I tried the Vercel URL to do the visual check I couldn't do locally, but anticapture-r78jg00km-ful.vercel.app is behind Vercel deployment protection and the anticapture project build shows as Ignored, so there's still no reachable render of this card. SecurityCouncilCard has no Storybook story either. So the visual state remains unverified — the card is pure config with no data fetching, and typecheck/lint are clean, but someone with preview access should eyeball /ens and /compound before merge.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 899fbe609b

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

multisig: {
threshold: 4,
threshold: 5,
signers: 8,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Refresh the ENS Security Council risk copy

When users open the Security Council detail in ENS Risk Analysis, the unchanged governanceImplementation.fields[SECURITY_COUNCIL].currentSetting in this same file still says the council is a 4/8 multisig expiring in July 2026. This update now configures a 5/8 council expiring in July 2028, so the overview card and risk-analysis drawer present contradictory council details; update the current-setting copy as part of the renewal.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants