Skip to content

Reduce StreamCore deployment size#90

Merged
punk6529 merged 3 commits into
mainfrom
codex/streamcore-size-reduction
Jun 11, 2026
Merged

Reduce StreamCore deployment size#90
punk6529 merged 3 commits into
mainfrom
codex/streamcore-size-reduction

Conversation

@punk6529

@punk6529 punk6529 commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Summary

  • moves pure on-chain metadata rendering, escaping, animation wrapper generation, and raw-attribute structural validation into a linked StreamMetadataRenderer library
  • removes optional ERC-721 Enumerable support from StreamCore while preserving a live totalSupply() view and ERC-4906 support
  • adds a production deployability size gate to make check, Linux/Windows check scripts, and CI: forge build --sizes --via-ir --skip test --force
  • updates status, tooling, metadata, roadmap, Slither baseline, and autonomous run docs with the new size/security evidence

Closes #89.

Size Evidence

Before this work, StreamCore was 35,696 runtime bytes, 11,120 bytes over the EIP-170 runtime limit.

The production gate now passes:

forge build --sizes --via-ir --skip test --force
StreamCore runtime size: 23,139 bytes
StreamCore runtime headroom: 1,437 bytes
StreamMetadataRenderer runtime size: 6,843 bytes

The generic all-artifact forge build --sizes remains diagnostic because test-only invariant handlers can exceed initcode limits. The release gate is the explicit skip-test, IR-optimized production profile above.

Validation

  • make check passed
  • powershell -ExecutionPolicy Bypass -File scripts\check.ps1 passed
  • $env:Path="$HOME\.foundry\bin;$env:Path"; forge fmt --check smart-contracts\StreamCore.sol smart-contracts\StreamMetadataRenderer.sol test\StreamMetadataEvents.t.sol passed
  • forge fmt --check smart-contracts\StreamMetadataRenderer.sol test\StreamMetadataEscaping.t.sol passed after CodeRabbit fixes
  • forge test --match-contract 'StreamMetadata(Escaping|Golden|Events)Test' -vvv passed with 26 tests after CodeRabbit fixes
  • git diff --check passed
  • forge build --sizes --via-ir --skip test --force passed
  • Slither baseline comparison returned the expected non-zero baseline exit with 717 total findings and high/medium unchanged at 4/19; target detectors remain zero for arbitrary-send-eth, reentrancy-eth, weak-prng, uninitialized-state, and encode-packed-collision

Notes

  • This intentionally drops the optional ERC-721 Enumerable interface from StreamCore; docs now call out that tokenByIndex and tokenOfOwnerByIndex are not part of the current release surface.
  • Deployment scripts/manifests/rehearsals still need to use the same production profile, and that remains tracked as follow-up deployment work.

@claude claude 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.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Refactors StreamCore to delegate metadata/escaping to a new StreamMetadataRenderer library, removes ERC721Enumerable while tracking live supply, adds a production-only forge size gate across CI/Makefile/scripts, and updates tests, docs, and operational records to reflect interface and size changes.

Changes

StreamCore refactoring and metadata renderer extraction

Layer / File(s) Summary
StreamMetadataRenderer library: metadata URIs and escaping utilities
smart-contracts/StreamMetadataRenderer.sol
New pure library providing on-chain token metadata as base64 data-URIs via onchainTokenURI and onchainMetadataJson, animation HTML via onchainAnimationURI, generative JS via generativeScript, context-specific escaping (escapeHtmlAttribute, escapeJavaScriptSingleQuotedString, escapeScriptElementEndTags, escapeJsonString), and raw-attributes structural validation via isSafeRawAttributes.
StreamCore contract: remove ERC721Enumerable, delegate to renderer
smart-contracts/StreamCore.sol
StreamCore switches from ERC721EnumerableERC721, adds _liveTokenSupply (mint increment, burn decrement), implements totalSupply(), updates supportsInterface to omit Enumerable while advertising ERC-4906, and delegates tokenURI/generative-script and raw-attributes checks to StreamMetadataRenderer.
Production size gating: CI, Makefile, and build scripts
.github/workflows/ci.yml, Makefile, scripts/check.sh, scripts/check.ps1
CI job timeout increased; new "Production size" CI step runs forge build --sizes --via-ir --skip test --force (output to ci-logs/forge-size.log). Makefile adds size target and updates check prerequisites to include size. Local check scripts updated to invoke the production-size build flags.
Tests: interface assertions and renderer escaping tests
test/StreamMetadataEvents.t.sol, test/StreamMetadataEscaping.t.sol
Add ERC721_ENUMERABLE_INTERFACE_ID and assert supportsInterface(...) for it returns false. Add testRendererEscapesSchemaAndStateFields() that calls StreamMetadataRenderer.onchainMetadataJson(...), verifies decoded JSON parses, and asserts escaped schema/state fields.
Architecture and process docs: ADR, tooling, metadata, status, blockers
README.md, docs/adr/0006-metadata-freeze.md, docs/known-blockers.md, docs/metadata.md, docs/status.md, docs/tooling.md
Update ADR and various docs to record ERC-4906 coverage without ERC-721 Enumerable, mark escaping/attribute-fragment coverage in scope, and document the production size gate command and EIP-170 headroom evidence.
Operational tracking and Slither baseline
ops/AUTONOMOUS_RUN.md, ops/ROADMAP.md, ops/SLITHER_BASELINE.md
AUTONOMOUS_RUN updated with active PR/branch and decision log entries for size-reduction work. ROADMAP updated verification metadata, machine-verifiable baseline, and Slither counts. SLITHER_BASELINE timestamp and impact counts refreshed and delta narrative updated to reflect removal of Enumerable and renderer extraction.
Test README: ERC-4906/size-gate notes
test/README.md
Clarify ERC-4906 test coverage expectations and document that production bytecode size is validated via the IR release-profile forge build --sizes --via-ir --skip test --force command in CI rather than by a unit test.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

  • #89: [P1-DEPLOY-001] Reduce StreamCore below EIP-170 deployment size — This PR directly implements the documented size-gate command, extracts rendering out of StreamCore, and removes optional Enumerable inheritance to address the deployment-size objective.

Possibly related PRs

Poem

🐰 In bytes we trust, but slim we must be,
I carved a renderer, set metadata free,
Stripped enumerable fat, counted live supply,
CI checks our size gate — watch the deployable sky.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and directly summarizes the primary goal of this PR: reducing StreamCore's deployment size below EIP-170.
Linked Issues check ✅ Passed The PR fully addresses all coding objectives from issue #89: extracts metadata rendering into StreamMetadataRenderer library, removes ERC-721 Enumerable, adds production-size gate to CI/make check with forge build --sizes --via-ir --skip test --force, updates docs, and achieves StreamCore runtime of 23,139 bytes (below EIP-170).
Out of Scope Changes check ✅ Passed All changes are directly scoped to the PR objectives: metadata rendering extraction, ERC-721 Enumerable removal with totalSupply() preservation, size-gate implementation, and documentation updates. No extraneous changes detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/streamcore-size-reduction

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ops/ROADMAP.md`:
- Line 66: Update the Static analysis table row in ops/ROADMAP.md so the Low
findings count matches ops/SLITHER_BASELINE.md (change the "92 Low" value to "93
Low" in the Static analysis evidence cell), ensuring the row labeled "Static
analysis" and its accompanying evidence text (`slither . --config-file
slither.config.json --foundry-compile-all`, `ops/SLITHER_BASELINE.md`, and
`docs/vendored-libraries.md`) remain unchanged otherwise so totals (717, 4 High,
19 Medium) still reconcile exactly with the baseline.

In `@smart-contracts/StreamMetadataRenderer.sol`:
- Around line 75-94: The JSON assembly embeds schemaVersion and metadataState
without escaping, risking malformed JSON if they contain quotes or backslashes;
update the JSON construction in StreamMetadataRenderer.sol to call
escapeJsonString on both schemaVersion and metadataState (e.g., use
escapeJsonString(schemaVersion) and escapeJsonString(metadataState) in the
abi.encodePacked sequence) so those fields are safely escaped before being
concatenated into the returned string.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8f5939d7-10b9-4550-b5ba-2262c78adeb6

📥 Commits

Reviewing files that changed from the base of the PR and between f22a14c and 306b178.

📒 Files selected for processing (17)
  • .github/workflows/ci.yml
  • Makefile
  • README.md
  • docs/adr/0006-metadata-freeze.md
  • docs/known-blockers.md
  • docs/metadata.md
  • docs/status.md
  • docs/tooling.md
  • ops/AUTONOMOUS_RUN.md
  • ops/ROADMAP.md
  • ops/SLITHER_BASELINE.md
  • scripts/check.ps1
  • scripts/check.sh
  • smart-contracts/StreamCore.sol
  • smart-contracts/StreamMetadataRenderer.sol
  • test/README.md
  • test/StreamMetadataEvents.t.sol

Comment thread ops/ROADMAP.md Outdated
Comment thread smart-contracts/StreamMetadataRenderer.sol
@punk6529 punk6529 merged commit 36d993a into main Jun 11, 2026
2 checks passed
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.

[P1-DEPLOY-001] Reduce StreamCore below EIP-170 deployment size

1 participant