Skip to content

Update ERC-8180: promote contentTag to indexed topic on BAM core events#3

Open
0xrcinus wants to merge 1 commit into
erc-8180/sender-renamefrom
erc-8180/content-tag
Open

Update ERC-8180: promote contentTag to indexed topic on BAM core events#3
0xrcinus wants to merge 1 commit into
erc-8180/sender-renamefrom
erc-8180/content-tag

Conversation

@0xrcinus
Copy link
Copy Markdown
Owner

Summary

Promotes contentTag into the indexed topic set on both BAM core events (BlobBatchRegistered, CalldataBatchRegistered) and adds contentTag as a parameter on registerCalldataBatch. This is the headline breaking change in the in-flight ERC-8180 amendments.

Stacked on #2 (rename PR). Base = erc-8180/sender-rename. After PR #2 merges, this PR's base will be retargeted to master.

Why

ERC-8179 positions contentTag as the first-class indexer filter key on BlobSegmentDeclared. Without this promotion, the "every BAM batch for protocol X" query has no direct filter on the BAM event itself:

  1. Blob path: must join BlobBatchRegistered against same-transaction BlobSegmentDeclared events by versioned hash, then read the segment's contentTag to identify the protocol. On shared blobs with multiple declared segments under the same versioned hash, the pairing requires log-index bookkeeping to stay unambiguous, and the join is not expressible as a single eth_getLogs call.
  2. Calldata path: there is no BlobSegmentDeclared for registerCalldataBatch. CalldataBatchRegistered is filterable only by decoder or submitter, and payload inspection (decoding the batch to look at its in-band protocol identifier) is the only way to identify the protocol from the event log. The "anyone can read and filter" property does not hold uniformly across the two registration paths.

After this PR, a single eth_getLogs call on either BAM core event recovers every matching registration with its decoder and signature registry in one shot, no joins required. The calldata path gains protocol-identity filtering at parity with the blob path.

What changes

Interface (IERC_BAM_Core)

 event BlobBatchRegistered(
     bytes32 indexed versionedHash,
     address indexed submitter,
-    address indexed decoder,
+    bytes32 indexed contentTag,
+    address decoder,
     address signatureRegistry
 );

Same shape change on CalldataBatchRegistered. registerCalldataBatch gains a bytes32 contentTag parameter.

Behavior (new normative clauses 12-14)

  • contentTag binding — the emitted value MUST equal the caller-supplied argument verbatim (no re-derivation, hashing, normalization, or defaulting). The topic MUST be identical across BlobSegmentDeclared and BlobBatchRegistered produced by a single registerBlobBatch call.
  • contentTag validation — implementations MUST NOT reject any value. bytes32(0) is accepted at the contract layer; a require(contentTag != 0) check is non-conforming.
  • Indexed-topic layoutcontentTag occupies topic[3]; decoder and signatureRegistry are unindexed event data. Flagged as a breaking change relative to earlier drafts in which decoder occupied the third indexed slot.

Why demote decoder (and not submitter)

Solidity caps non-anonymous events at three indexed topics. With contentTag promoted, one existing indexed topic must move to event data:

  • submitter is retained because the (chainId, contentTag, submitter) attribution tuple recommended for BSS indexers (and now BAM indexers) needs to stay cheap to query.
  • decoder is demoted because filter-by-decoder becomes less useful as decoders converge on a small stable set, while filter-by-contentTag is the standard indexer query under ERC-8179's design.
  • The Rationale also explicitly rejects two minority positions: (a) keep decoder indexed and leave contentTag unindexed (forces data-level filtering for the first-class query), and (b) declare the events anonymous and use four indexed topics (sacrifices topic-0 dispatch, which loses more discoverability than the extra slot recovers).

Security Considerations (three new subsections)

  • contentTag tag spoofingcontentTag is a caller-chosen label, not an ownership primitive. Indexers MUST attribute by (chainId, contentTag, submitter) and apply submitter-level trust policy.
  • contentTag null-tag discouragementbytes32(0) is accepted but NOT RECOMMENDED at the application layer (mirrors ERC-8179 null-tag guidance).
  • contentTag griefing economics on the calldata path — calldata is cheaper per batch than the blob path, so log-spam attacks are sharper in degree though not in kind. Same attribution-tuple mitigation.

Test Cases

New rows cover:

  • Verbatim emission of contentTag on both blob and calldata paths
  • bytes32(0) accepted on both paths (NOT RECOMMENDED at app layer)
  • eth_getLogs filter on BlobBatchRegistered and CalldataBatchRegistered returns only matching contentTag registrations

Reference Implementation

Sepolia deployment table updated:

  • BlobAuthenticatedMessagingCore (0x9C4b2300…) — amended layout
  • SocialBlobsCore (legacy, 0x11a825a0…) — retained for pre-amendment log inspection

Minimal Core Implementation reflects the new event signatures and registerCalldataBatch parameter.

Breaking-change scope

Existing deployments emit the upstream layout (decoder indexed). New deployments would emit the amended layout (contentTag indexed). No on-chain coexistence path is proposed; consumers re-key their filters against the new topic position. Acceptable for a Draft-status ERC.

Test plan

  • Both BAM event signatures updated consistently (interface + minimal impl)
  • registerCalldataBatch signature updated consistently (interface + minimal impl + worked example 2 + test cases)
  • Behavior clauses 3, 6 updated to mention contentTag in emit; new clauses 12-14 added
  • Worked Examples 1, 2, 3 show contentTag in events
  • Test Cases table has rows for verbatim emission and getLogs filter behavior on both paths
  • Three new Security Considerations subsections present
  • No registerBlobBatches content (deferred to a follow-up PR)
  • No ECDSA divergence content (deferred)
  • No "Reference v1 ABI shape" content (orthogonal clarification; not part of this PR)
  • References use "ERC-8179" (numbered) throughout, matching upstream style

🤖 Generated with Claude Code

Aligns BAM with ERC-8179's first-class filter key:

- BlobBatchRegistered: bytes32 indexed contentTag occupies the third
  indexed topic; decoder demoted to unindexed event data
- CalldataBatchRegistered: same layout
- registerCalldataBatch gains a bytes32 contentTag parameter
- Behavior clauses 12-14: verbatim binding, no-rejection validation,
  indexed-topic layout (breaking change)
- New Rationale subsections: contentTag uniformity across blob and
  calldata paths, why contentTag is indexed and decoder is not
- New Security Considerations: tag spoofing, null-tag discouragement,
  calldata griefing economics
- Test Cases: new rows for contentTag verbatim emission and
  eth_getLogs filter behavior on both BAM events
- Worked Examples and Minimal Core Implementation updated
- Sepolia table reflects amended core deployment alongside legacy

Breaking change: existing deployments emit the upstream layout; new
deployments would emit the amended layout. Acceptable for Draft-status
ERC; no on-chain coexistence path is proposed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant