Skip to content

feat(dashboard): recursive calldata decoder (proposal actions + /tools/decoder) - #2146

Merged
brunod-e merged 49 commits into
devfrom
feat/calldata-decoder
Sep 15, 2026
Merged

brunod-e merged 49 commits into
devfrom
feat/calldata-decoder

Conversation

@brunod-e

Copy link
Copy Markdown
Collaborator

Implements the technical decoder from the Calldata Visualization PRD (ClickUp DEV-1159 / 86aje4uvc). The AI summary strip is out of scope and will ship separately.

What this adds

Decode engine (shared/services/decoder/, pure TS, 71 unit tests)

  • Structured decode tree (DecodedCall/DecodedParam) instead of the old formatted string.
  • ABI fallback chain: verified (bundled + Etherscan proxy) -> user-uploaded -> OpenChain -> word-shape-guessed arg0..argN with a permanent warning. Never a blank state; raw hex is preserved on every path.
  • OpenChain candidates are validated by decoding (fixes the old take-first-signature bug); ambiguous matches are flagged.
  • Recursive multicall unpacking: Safe execTransaction (delegatecall flagged), Multicall3 aggregate/aggregate3/tryAggregate, OZ Timelock schedule/scheduleBatch/execute/executeBatch, Governor relay. Depth capped at 5 with node/size budgets.
  • Humanizers (duration, timestamp, grouped numbers, ETH value) plus async ERC20 enrichment ("25,000 USDC") that never blocks the decode.
  • Deterministic summary sentences for known functions (transfer/approve/transferFrom/delegate/NFT transfers/updateDelay/batches).

Proposal Actions tab

  • Decoded cards replace the flat decode block: chip cluster (decoded ✓, ABI · VERIFIED|UPLOADED|OPENCHAIN), summary row, identity chips for every address (replaces the regex CalldataWithEns), aligned type chips, humanized-first values with raw annotations, nested subcall cards, decoded | raw toggle and copy on every card.
  • First action auto-expands; the rest collapse to one-line rows ([+] [chip] sentence · signature), remembered per session, deep-linkable via ?tab=actions#action-2. Calldata-shaped bytes params get a lazy [+ decode].

Standalone tool

  • New global page /tools/decoder (sidebar entry, desktop + mobile): paste calldata, optional target + chain, paste/upload ABI. Decode state lives in the URL for permalinks (the custom ABI intentionally does not).

Refactors

  • Promoted to shared: fetchAbi->fetchVerifiedAbi, parseAbiStrict, parseAbiJson, paramShape (from argTree), SUGGESTED_TRANSFER_TOKENS, bundled-ABI lookup. useDecodeCalldata deleted.

Verification

  • pnpm dashboard typecheck, lint (0 errors) and test (638 passed) green.
  • Verified in the browser against dev-gateful: ENS proposal with a real Safe execTransaction unpacked to swapOwner via OpenChain, identity chips resolving ENS names, collapsed-row sentences, decoded|raw toggle, and the standalone page decoding a USDC transfer from a permalink.

Known v1 limitations (per plan)

  • ERC1967 proxies: Etherscan returns the proxy ABI, so implementation calls fall through to OpenChain.
  • Token enrichment needs the RPC proxy; where it fails the UI shows raw units.

🤖 Generated with Claude Code

brunod-e and others added 11 commits August 30, 2026 16:01
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…manizers

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…king and summaries

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…lldata

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… cards

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…controls

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 30, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated
anticapture-storybook Ready Ready Preview Sep 15, 2026 5:13pm UTC
1 Skipped Deployment
Project Deployment Actions Updated
anticapture Ignored Ignored Sep 15, 2026 5:13pm UTC

Request Review

@railway-app

railway-app Bot commented Aug 30, 2026

Copy link
Copy Markdown

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

Service Status Web Updated
tempo ✅ Success (View Logs) Sep 15, 2026 at 5:18 pm UTC
otelcol ✅ Success (View Logs) Sep 15, 2026 at 5:18 pm UTC
gateful ✅ Success (View Logs) Web Sep 15, 2026 at 5:16 pm UTC
prometheus ✅ Success (View Logs) Sep 15, 2026 at 5:16 pm UTC
loki ✅ Success (View Logs) Sep 15, 2026 at 5:16 pm UTC
grafana ✅ Success (View Logs) Web Sep 15, 2026 at 5:16 pm UTC
authful ✅ Success (View Logs) Web Sep 15, 2026 at 5:16 pm UTC
alertmanager ✅ Success (View Logs) Web Sep 15, 2026 at 5:15 pm UTC
compound-indexer-offchain ✅ Success (View Logs) Sep 1, 2026 at 12:36 am UTC
gitcoin-indexer-offchain ✅ Success (View Logs) Sep 1, 2026 at 12:26 am UTC
uniswap-indexer-offchain ✅ Success (View Logs) Sep 1, 2026 at 12:19 am UTC
ens-indexer-offchain ✅ Success (View Logs) Sep 1, 2026 at 12:18 am UTC
shutter-indexer-offchain ✅ Success (View Logs) Sep 1, 2026 at 12:17 am UTC
docs ✅ Success (View Logs) Web Aug 30, 2026 at 7:58 pm UTC
mcp ✅ Success (View Logs) Web Aug 30, 2026 at 7:58 pm UTC
gitcoin-api ✅ Success (View Logs) Aug 30, 2026 at 7:58 pm UTC
gitcoin-indexer ✅ Success (View Logs) Aug 30, 2026 at 7:58 pm UTC
aave-api ✅ Success (View Logs) Aug 30, 2026 at 7:58 pm UTC
obol-api ✅ Success (View Logs) Aug 30, 2026 at 7:58 pm UTC
lil-nouns-indexer ✅ Success (View Logs) Aug 30, 2026 at 7:58 pm UTC
address-enrichment ✅ Success (View Logs) Web Aug 30, 2026 at 7:58 pm UTC
nouns-api ✅ Success (View Logs) Aug 30, 2026 at 7:58 pm UTC
compound-api ✅ Success (View Logs) Aug 30, 2026 at 7:58 pm UTC
fluid-indexer ✅ Success (View Logs) Aug 30, 2026 at 7:58 pm UTC
compound-indexer ✅ Success (View Logs) Aug 30, 2026 at 7:58 pm UTC
nouns-indexer ✅ Success (View Logs) Aug 30, 2026 at 7:58 pm UTC
obol-indexer ✅ Success (View Logs) Aug 30, 2026 at 7:58 pm UTC
fluid-api ✅ Success (View Logs) Aug 30, 2026 at 7:58 pm UTC
scroll-indexer ✅ Success (View Logs) Aug 30, 2026 at 7:58 pm UTC
ens-api ✅ Success (View Logs) Aug 30, 2026 at 7:58 pm UTC
lil-nouns-api ✅ Success (View Logs) Aug 30, 2026 at 7:58 pm UTC
shutter-api ✅ Success (View Logs) Aug 30, 2026 at 7:58 pm UTC
uniswap-api ✅ Success (View Logs) Aug 30, 2026 at 7:58 pm UTC
uniswap-indexer ✅ Success (View Logs) Aug 30, 2026 at 7:58 pm UTC
ens-indexer ✅ Success (View Logs) Aug 30, 2026 at 7:58 pm UTC
tornado-api ✅ Success (View Logs) Aug 30, 2026 at 7:58 pm UTC
shutter-indexer ✅ Success (View Logs) Aug 30, 2026 at 7:58 pm UTC
aave-indexer ✅ Success (View Logs) Aug 30, 2026 at 7:58 pm UTC
tornado-indexer ✅ Success (View Logs) Aug 30, 2026 at 7:58 pm UTC
ens-relayer ✅ Success (View Logs) Aug 30, 2026 at 7:57 pm UTC
erpc ✅ Success (View Logs) Aug 30, 2026 at 7:57 pm UTC
nodeful ✅ Success (View Logs) Aug 30, 2026 at 7:57 pm UTC
user-api ✅ Success (View Logs) Web Aug 30, 2026 at 7:56 pm UTC
scroll-api ✅ Success (View Logs) Aug 30, 2026 at 7:56 pm UTC

@railway-app
railway-app Bot temporarily deployed to anticapture-infra / anticapture-pr-2146 August 30, 2026 19:54 Destroyed

@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

const res = await fetch(`/api/etherscan?${params.toString()}`);
if (!res.ok) return null;
const json = (await res.json()) as EtherscanResponse;

P2 Badge Catch verified-ABI transport failures

If the browser request to /api/etherscan rejects—for example during a transient network or proxy failure—this uncaught exception rejects the complete decode query before the resolver can fall back to an uploaded ABI, OpenChain, or word guessing. Both decoder consumers ignore the query error and therefore render a blank result once loading ends; catch fetch and response-parsing failures here and return null, consistent with the resolver's graceful fallback contract.

ℹ️ 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".

Comment thread apps/dashboard/shared/services/decoder/decode.ts Outdated
Comment thread apps/dashboard/shared/services/decoder/multicall/detectors.ts Outdated

Copy link
Copy Markdown
Collaborator

🎨 UI Review

Automated review · Figma: Calldata Visualization — frame 08 "IN PRODUCTION" · Spec (DEV-1159) · Preview: not built — Vercel skipped the apps/dashboard deployment for this PR (only the Storybook project built), so this is Figma + diff only.
Colors below are resolved via get_variable_defs against the frame's actual mode, not the var(--token, fallback) string.


Decoded Action Card — summary: row

  • Both the summary: label and the sentence render dimmed — text-dimmed on the label, text-secondary on the sentence. Figma has the whole row at text/primary (#fafafa), same weight as the target:/function: rows right below it (which the code gets right via RowLabel). Change both to text-primary.
    apps/dashboard/features/decoder/components/SummaryRow.tsx:12-13 [Figma-confirmed]

Decoded Action Card — value: row

  • The row is gated on call.value > 0n, so it disappears for every action that doesn't move ETH — i.e. most governance actions. Figma's own "in production" reference (the register action) always renders value: 0 ETH; nothing in the PRD says to hide it at zero. Drop the > 0n check so the row always renders (still fine for it to read "0 ETH").
    apps/dashboard/features/decoder/components/DecodedActionCard.tsx:156-164 [Figma-confirmed]

AddressChip

  • No border at rest. The chip is border border-transparent, only picking up border-border-contrast on hover. Every AddressChip in Figma (target row, param owner chip, collapsed-row USDC/Timelock chips) has a visible border-borders/contrast (#3f3f46) pill at rest — right now the chip reads as plain inline text until you hover it. Also, the interaction spec (frame 09) says address-chip hover moves the border to borders/highlight (#ec762e, the brand orange), not to contrast — so the hover target itself is one step short too.
    apps/dashboard/features/decoder/components/AddressChip.tsx:79-80 — change to border-border-contrast at rest, hover:border-highlight (or the project's equivalent highlight-border class) [Figma-confirmed]

  • Unresolved-address fallback text is text-secondary. Figma's owner param chip (no ENS name resolved) still renders the raw checksum in text/primary (#fafafa) — only the truncated-address annotation next to a resolved name drops to secondary. Swap the ternary so the no-name case is text-primary too.
    apps/dashboard/features/decoder/components/AddressChip.tsx:58 [Figma-confirmed]

  • EOA tag is boxed (border-border-contrast border px-1). Figma renders it as plain text-secondary inline text, no border — smaller thing than the two above, but worth a look while you're in the file.
    apps/dashboard/features/decoder/components/AddressChip.tsx:116-119 [Figma-confirmed]


Standalone tool — /tools/decoder

  • No "copy permalink" affordance. Frame 06 puts [COPY PERMALINK] in the title row next to the tool title; the page is genuinely permalink-able via nuqs state, there's just no one-click way to grab the link — the reader has to copy the address bar manually.
    apps/dashboard/features/decoder/components/DecoderTool.tsx (title row, ~line 100) [Figma-confirmed]

  • No [PASTE] / [CLEAR] controls on the input card. Frame 06's buttons row has DECODE / [PASTE] / [CLEAR] plus a "supports: raw calldata · …" hint; the live-decode-on-type approach makes an explicit DECODE button unnecessary, but [CLEAR] (one click to empty a pasted 2KB blob) and [PASTE] (clipboard read without the browser's default paste flow interrupting the URL-synced textarea) are missing entirely, and there's no hint telling the reader what input formats the field accepts.
    apps/dashboard/features/decoder/components/DecoderInputPanel.tsx (buttons row absent) [Figma-confirmed]

  • Question for author: the ClickUp spec's "Decisions" section says the standalone tool "accepts raw calldata / signed tx hex / explorer URL," but isValidCalldataInput only accepts bare 0x-prefixed hex (apps/dashboard/features/decoder/utils/calldataInput.ts:6-7) — pasting a tx hash or an Etherscan URL just trips the "Must be 0x-prefixed hex…" error, and the field's helper text doesn't mention the narrower scope either. Deliberately deferred, or should the copy (and maybe the validator) be updated to match what v1 actually supports?


Motion

  • --ease-decoder: cubic-bezier(0.2, 0, 0, 1) is added to globals.css for "the one easing every calldata-card transition uses" (frame 09's explicit spec), but nothing in the decoder feature references it — every transition (AddressChip, CollapsedActionRow, CopyRawButton, the collapse [–] control) uses transition-colors duration-[120ms] with no ease-* class, so they fall back to the default timing function instead of the specified curve.
    apps/dashboard/app/globals.css:57 [Figma-confirmed]

Validated against Figma — no change needed

  • First action auto-expands, rest collapse, state remembered per session (sessionStorage), deep-linkable via #action-N — matches the PRD's progressive-disclosure spec exactly (useActionExpansion.ts).
  • 300ms skeleton threshold before showing a loading card, cached decodes render with no flash — matches the Component States table (useDelayedFlag.ts, default delayMs=300).
  • [copy raw calldata] swaps to copied ✓ in text-success for 1.2s, no toast — matches frame 09's interaction row exactly (CopyRawButton.tsx).
  • decoded | raw segmented control reuses the shared SegmentedControl DS component; visual match to Figma's "View toggle" (bordered wrapper, active segment on surfaces/contrast).
  • Nested subcall cards and nested param children both use a 1px left rail + indent — matches "mirrors ArgInput.tsx" from the PRD.
  • No hand-rolled primitives found in the new decoder components — BadgeStatus, SegmentedControl, Skeleton, Button, Textarea/Input/Select, BlankSlate, Tooltip, InlineAlert, CodeBlock, DefaultLink are all reused from the design system, and every new component is built with 0px radius, consistent with "Orbit UI, 0px radius everywhere."
  • Sidebar (HeaderSidebar.tsx) and mobile nav (HeaderMobile.tsx) "Decoder" entries reuse the exact existing nav-link pattern (icon + label) used by every other global tool entry — no separate mobile-specific issue.

Generated by Claude Code

@github-actions

github-actions Bot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

🔍 Vercel preview: https://anticapture-6jocd9trr-ful.vercel.app

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@railway-app
railway-app Bot temporarily deployed to anticapture-infra / anticapture-pr-2146 August 30, 2026 23:08 Destroyed
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@railway-app
railway-app Bot temporarily deployed to anticapture-infra / anticapture-pr-2146 August 30, 2026 23:09 Destroyed
@brunod-e

Copy link
Copy Markdown
Collaborator Author

Addressed the UI review in 3d82ef0 — thanks, this was thorough:

  • summary: row: label and sentence both moved to text-primary, matching the target:/function: rows.
  • value: row: no longer gated on > 0n; it always renders (zero shows as 0 ETH). It only stays hidden when the call has no value at all (nested bytes decodes in the standalone tool).
  • AddressChip: visible border-border-contrast pill at rest, hover:border-highlight (brand) per frame 09; unresolved-address fallback now text-primary; EOA tag is plain text-secondary inline text, box removed.
  • Motion: every decoder transition (AddressChip, CollapsedActionRow row + [+], CopyRawButton, the [–] collapse control) now uses ease-[var(--ease-decoder)], so the token is actually consumed.
  • Standalone: [copy permalink] added to the title row (resolves window.location.href at click, same copied ✓ feedback); [paste] / [clear] added above the calldata field ([paste] reads the clipboard, [clear] empties the URL-synced value); helper copy now states the supported format.

On the input-scope question: deliberate v1 narrowing — the field accepts raw calldata (0x hex) only. Signed tx hex and explorer URLs both need extra machinery (tx-envelope RLP parsing, or fetching the tx by hash through the RPC proxy) and are worth their own slice; the helper text now says "Supports raw calldata (0x-prefixed hex)" so the copy no longer overpromises. I'll note it on DEV-1159 as a follow-up.

brunod-e and others added 4 commits September 14, 2026 15:30
- A delegatecall child carries an execution mode through the decode, and
  nothing claims effects at the code it runs: no token hint, a sentence
  reading "Delegatecalls 0xabcd…1234 (transfer)", a warning on the card and
  a badge on the collapsed row. The parent repeats the operation, never the
  effect. Safe multiSend is unpacked too, so its packed operation byte and
  its per-record value get the same treatment.
- The parameter count and signature line come from the ABI's input count,
  so a 300-input function no longer reads as 100 params. A batch whose
  children the budget dropped now ends its name list with an ellipsis
  rather than an exact remainder it cannot know.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- A wrapper's summary is structural and stays true however the parent
  invoked it. The canonical Safe batch delegatecalls MultiSend, so the old
  ordering hid every child behind one address; the qualifier now rides on
  the sentence: "Executes 2 calls (delegatecall): transfer, approve."
  Leaf templates still refuse to claim effects for a delegatecall.
- The parameter budget is tree-wide as well as per call, so 200 calls can
  no longer contribute a hundred rows each. Wrapper caveats read off the
  extracted calls instead of unpacking a MultiSend blob a second time.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- A collapsed action decodes at depth 0, so a page of batched actions no
  longer issues an ABI proxy request per nested call before anyone has
  expanded a row. Wrapper summaries fall back to the arity when the
  children are raw, and an option passed as undefined keeps its default
  instead of switching the guard off.
- Tuples get the same preview cap as arrays, the resolver caches evict
  least-recently-used, raw hex scrolls instead of growing the card, pastes
  stop at the decode limit, and tooltips are truncated.
- A token symbol read from an arbitrary contract is sanitized before it
  reaches a sentence, and a chain id from the URL is validated before it
  reaches the ABI proxy. Network JSON is narrowed with guards rather than
  asserted, the last address casts are gone, and the hook dependency
  warnings are fixed at the source.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…nd records

- A collapsed action decodes one level, so its sentence names the direct
  children and keeps their delegatecall qualifier, at one ABI lookup per
  child and none deeper.
- MultiSend stops at any operation byte it cannot execute, and says what it
  could not read: an invalid byte, an over-declared length, or a trailing
  stub. Nothing after such a record is presented as a call.
- The decoder tool says when a paste was truncated to the decode limit and
  when the link was omitted. The budget constants now state that they count
  retained values, not the notes about them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@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: 80fa7b3537

ℹ️ 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".

Comment thread apps/dashboard/shared/services/decoder/decode.ts
Comment thread apps/dashboard/shared/services/decoder/multicall/detectors.ts
…verting batches

- Children decode in parallel and claim their rows when their own ABI
  lookup resolves, so a shared budget handed the tree to whichever network
  call returned first and the same calldata rendered differently between
  decodes. The tree budget is now partitioned before the workers start,
  the same way the node budget already was, with ties to source order.
- A Timelock batch whose targets, values and payloads disagree in length
  cannot execute, so it decodes to no calls and says it would revert
  rather than inventing an empty call for each missing payload.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@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: 0a9a695204

ℹ️ 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".

Comment thread apps/dashboard/shared/services/decoder/decode.ts Outdated
Comment thread apps/dashboard/shared/services/decoder/decode.ts
…hild its parameter share back

Two follow-ups from a regression pass over yesterday's decoder commits:

- The params section was gated on the retained rows, so a call whose every
  input the budget dropped rendered no params and no note, claiming it takes
  no arguments, and its signature read `transfer (, +3 more)`. The note now
  shows whenever it exists and the argument list joins its parts.
- The reclaim pass re-decoded a child with the parameter budget its first
  attempt had already spent, so the replacement had more calls and fewer
  arguments than the tree it discarded. The retry now starts from the
  child's own share again, as it already did for nodes, and hands its
  leftovers back the same way.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

@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: 3cf55588ae

ℹ️ 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".

Comment thread apps/dashboard/shared/services/decoder/summarize.ts
Comment thread apps/dashboard/shared/services/decoder/multicall/detectors.ts
Comment thread apps/dashboard/features/decoder/components/AbiInput.tsx
brunod-e and others added 2 commits September 15, 2026 09:43
Standalone tool: SectionTitle header with the braces icon, new page
description, ABI source behind Automatic / Contract address / Custom ABI
tabs with the calldata pinned above them, chain picker in the card header,
Paste and Clear as design-system ghost buttons, Paste hidden where the
clipboard cannot be read and its failure surfaced, copy link moved into the
result card, and the Decoded | Raw toggle dropped on the tool only.

Decoded card: uppercase mono labels that stack above the value on phones,
Base/Regular content everywhere hex and signatures used to be mono, type
chips as outline status badges (TypeChip deleted), the six Safe execution
parameters folded behind one line, operation shown as `1 · delegatecall`
with an Elevated permission badge, nested calls as chevron rows with token
and DAO icons, and copy as the design-system copy control.

Identity chips resolve curated tokens and DAO governor / timelock / token
contracts offline, so USDC gets a token logo and ENS contracts the DAO logo
instead of an ENS identicon.

Engine: Governor propose (OpenZeppelin and Bravo) is unpacked into one
action per target with a "Submits a proposal with N actions" summary, the
card hides the parallel arrays the action list already spells out, and the
maximum uint256 amount reads as "unlimited".

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A batch that unpacked nothing, or not everything, keeps its parallel arrays
in view, since the would-revert and budget warnings point at them. An
address that arrived in a permalink survives a trip through the Automatic
tab, and the Custom ABI tab takes the contract address so a pasted ABI can
be scoped to it again. Embedded cards carry the ABI-source badge, the
contract link and Copy raw in a meta row. A Safe transaction cut short by
the parameter budget keeps its operation row; a failed token logo is
remembered per URL, not per slot; NFT DAO tokens are named by the DAO's
display name; the collapsed action row announces its state; and Bravo
signatures are hashed exactly as the governor stores them.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

@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: e2248250f8

ℹ️ 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".

Comment thread apps/dashboard/shared/services/decoder/multicall/detectors.ts Outdated
Comment thread apps/dashboard/shared/services/decoder/decode.ts Outdated
Batch summaries group their calls by kind and count them ("3 unlimited
approvals, 1 role grant") instead of listing function names. AccessControl
role hashes resolve to their names, so grantRole and revokeRole read as
"Grants the PROPOSER_ROLE role to 0x…", and the three role functions decode
without an ABI. Token amounts annotate the raw units and the decimals they
were read with, so 1e21 units of USDC cannot pass for 1,000.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

@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: f00f6bff4a

ℹ️ 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".

Comment thread apps/dashboard/features/decoder/components/DecoderTool.tsx
Comment thread apps/dashboard/shared/components/decoder/AddressChip.tsx
Comment thread apps/dashboard/shared/services/decoder/decode.ts
brunod-e and others added 2 commits September 15, 2026 10:18
approve and transferFrom decoded from the canonical table or a signature
database no longer claim a fungible amount until the target's decimals are
known: the sentence names units that may be an ERC-20 amount or a token id.
A Safe operation outside call and delegatecall yields no child and a
would-revert warning. Governor Bravo signatures are hashed verbatim, as the
governor does, instead of parsed and canonicalised. An invalid ABI file
clears the previously applied ABI instead of leaving it live behind an
error. Word-guessed parameters spend the shared tree budget like decoded
ones, the folded remainder included.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…BI sources

An address that arrives in the URL while the decoder is mounted opens the
Contract address tab, so Back/Forward between permalinks decodes with the
ABI the link names. The EOA tag only shows on mainnet, the one chain the
enrichment service reads code on. A verified-ABI or OpenChain lookup that
runs to its timeout latches that source closed for a minute, so a batch of
children on distinct unverified contracts falls through to the next tier
at once instead of waiting out one timeout wave per four children.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

@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: b97c033426

ℹ️ 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".

Comment thread apps/dashboard/shared/services/decoder/summarize.ts Outdated
…in its sentence

The outage latch tripped on elapsed time alone, so a slow but successful
Etherscan answer closed the verified tier for a minute, for every chain,
and skipped even memoized ABIs. It now latches only on a slow AND empty
network answer, lifts only on a prompt non-empty one, serves settled
memoized entries before consulting the latch, and never waits on a
request that was already in flight when it closed. A wrapper that borrows
its single child's sentence now says the ETH that child carries, once.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

@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: 032d62cab9

ℹ️ 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".

Comment thread apps/dashboard/features/decoder/utils/calldataInput.ts
Comment thread apps/dashboard/shared/services/decoder/summarize.ts
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.

3 participants