Skip to content

docs: restructure B20 guides and rewrite execution architecture - #213

Merged
rayyan224 merged 22 commits into
mainfrom
docs/restructure-b20-guides
Sep 3, 2026
Merged

docs: restructure B20 guides and rewrite execution architecture#213
rayyan224 merged 22 commits into
mainfrom
docs/restructure-b20-guides

Conversation

@rayyan224

Copy link
Copy Markdown
Collaborator

Summary

  • Replace the old per-primitive docs (docs/B20, PolicyRegistry, ActivationRegistry) with an audience-layered structure: overview, architecture, guides, concepts, and reference.
  • Rewrite the architecture page so readers can follow native precompile dispatch, self-managed gas and EVM-like errors, and writes that go straight into shared EVM account storage.
  • Fill in the overview (why B20, compliance, roles, pause) and the constants, errors, and events reference tables.

Test plan

  • Read docs/overview.md end to end and confirm it still matches current B20 behavior
  • Read docs/architecture.md §§1–3 and confirm the precompile vs contract story, routing, and token-creation flow are accurate
  • Confirm mermaid diagrams render (especially the Rust-precompile vs EVM-state transfer chart)
  • Click through links from docs/README.md and the root README.md into the new structure; no stale docs/B20 / PolicyRegistry / ActivationRegistry paths
  • Spot-check docs/reference/{constants,errors,events}.md against the interfaces

Made with Cursor

rayyan224 and others added 13 commits August 28, 2026 11:03
…/reference

Replaces the old docs/B20, docs/PolicyRegistry, and docs/ActivationRegistry
pages with an audience-layered structure: a short overview, a canonical
architecture doc, per-audience guides (integrator/indexer/implementer),
evergreen concept pages, and a reference section. Root README now points
into the new docs/ entry point instead of the removed paths.

Co-Authored-By: Claude <noreply@anthropic.com>
Walk grant-then-call and attach-then-gate in the overview, including
revert paths, and move the role and policy-scope tables to the concept pages.

Co-authored-by: Cursor <cursoragent@cursor.com>
Give roles, pause, and policy a why-then-how flow. Drop the stack section
that duplicated What is B20.

Co-authored-by: Cursor <cursoragent@cursor.com>
…rchitecture

Fills in the constants, errors, and events reference tables with the
actual role/policy hashes, error selectors, and event catalogue, and
rewrites architecture.md around the precompile execution model and
protocol-evolution guarantees.

Co-Authored-By: Claude <noreply@anthropic.com>
The changelog/README.md ordinal table is already the source of truth for
hardfork<->version mapping, so a separate reference/versions.md duplicated
it. Repoint the three referring TODOs at the changelog index instead.

Co-Authored-By: Claude <noreply@anthropic.com>
Rewrite the contracts-vs-precompiles section into a continuous narrative so readers can follow native execution, self-managed state and gas, registry routing, and the shared EVM flow.

Co-authored-by: Cursor <cursoragent@cursor.com>
Spell out that recognized precompiles run registered native code, meter
gas and EVM-like errors themselves, and write straight into account
storage — the same slots a contract would use.

Co-authored-by: Cursor <cursoragent@cursor.com>
Remove the unfinished implementer page and its nav links, and add a
compliance-guide template for the remaining how-to pages.

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions

Copy link
Copy Markdown

Interface Coverage

✅ All interface functions have test coverage.

@github-actions

github-actions Bot commented Aug 28, 2026

Copy link
Copy Markdown

⚠️ Fork tests: 46 failed, 702 passed

These failures indicate divergences where base/base needs to catch up to the base-std spec. This check is advisory and does not block merging.

Failing tests
  • test_policyId_success_reflectsUpdatePolicy(uint8,uint64): UnsupportedPolicyType(0xedb5da348cfb67af08746d3afd1be81034b50d5c8576f31aff688f39dfd540ed); counterexample: calldata=0xa21d943e000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000135644152c2 args=[3, 1328826897090 [1.328e12]]
  • test_policyId_success_zeroByDefault(uint8): UnsupportedPolicyType(0xedb5da348cfb67af08746d3afd1be81034b50d5c8576f31aff688f39dfd540ed); counterexample: calldata=0x11a5c8f40000000000000000000000000000000000000000000000000000000000000069 args=[105]
  • test_seizeWithMemo_revertOrder_receiver_beats_balance(address,address): UnsupportedPolicyType(0xedb5da348cfb67af08746d3afd1be81034b50d5c8576f31aff688f39dfd540ed); counterexample: calldata=0xc375ac630000000000000000000000000000000000000000000000000000000000003481000000000000000000000000000000000000000000000000000000004c63e561 args=[0x0000000000000000000000000000000000003481, 0x000000000000000000000000000000004C63e561]
  • test_seizeWithMemo_revert_insufficientBalance(address,address,uint256): UnsupportedPolicyType(0xedb5da348cfb67af08746d3afd1be81034b50d5c8576f31aff688f39dfd540ed); counterexample: calldata=0x033c50050000000000000000000000006ab857f89b6698ad58b9f7b951202c2af16b40ae000000000000000000000000a1bb154d2e4f5259c0866dc6567eff97ccbe53060000000000000000000000000000000000000000000000000000000000000001 args=[0x6Ab857f89B6698AD58b9f7B951202C2AF16b40Ae, 0xa1BB154D2E4F5259C0866dc6567eFF97CcbE5306, 1]
  • test_seizeWithMemo_revert_invalidReceiver(address,uint256): UnsupportedPolicyType(0xedb5da348cfb67af08746d3afd1be81034b50d5c8576f31aff688f39dfd540ed); counterexample: calldata=0x92e9b3880000000000000000000000002607efc56e2eacc32ca7c37d592caed5994686de000000000000000000000000000000000000000000000000000030289148545c args=[0x2607eFc56e2eacC32ca7c37d592caED5994686DE, 52950794261596 [5.295e13]]
  • test_seizeWithMemo_revert_receiverPolicyForbids(address,address,uint256): UnsupportedPolicyType(0xedb5da348cfb67af08746d3afd1be81034b50d5c8576f31aff688f39dfd540ed); counterexample: calldata=0x05a3631f000000000000000000000000ff19efefe389206d5e6012137b81ee51bae42482000000000000000000000000dc7661c6b5c7fadfd6541215ffa3ecf9d3e6c7290000000000000000000000000000000000000000000000000000000000170115 args=[0xfF19EFEFe389206D5E6012137B81ee51baE42482, 0xDc7661C6B5C7FadFd6541215fFa3ecf9d3e6C729, 1507605 [1.507e6]]
  • test_seizeWithMemo_revert_selfSeize(address,uint256): UnsupportedPolicyType(0xedb5da348cfb67af08746d3afd1be81034b50d5c8576f31aff688f39dfd540ed); counterexample: calldata=0xffbeec220000000000000000000000000000000000000000000000000000000000000d5d0000000000000000000000000000000000000000000000000000000000000635 args=[0x0000000000000000000000000000000000000d5D, 1589]
  • test_seizeWithMemo_revert_whenSeizePaused(address,address,uint256): UnsupportedPolicyType(0xedb5da348cfb67af08746d3afd1be81034b50d5c8576f31aff688f39dfd540ed); counterexample: calldata=0x83c47ba40000000000000000000000000000000000000000000000000000000000003fda0000000000000000000000000000000000000000000000000000000000001217cdcc772fe4cbdb1029f822861176d09e646db96723d4c1e82ddfdeb8163ef54c args=[0x0000000000000000000000000000000000003fda, 0x0000000000000000000000000000000000001217, 93085393359812225330546714545801767655967775857010822972004765400649682580812 [9.308e76]]
  • test_seizeWithMemo_revert_zeroFrom(address,uint256): UnsupportedPolicyType(0xedb5da348cfb67af08746d3afd1be81034b50d5c8576f31aff688f39dfd540ed); counterexample: calldata=0xdf1bcb7a0000000000000000000000002faf4e309b1443f7c8e487a0ba9003d07eec494f00000000000000000000000000000000000000000000000000000004f1a95cf2 args=[0x2FaF4E309B1443f7c8e487a0BA9003d07Eec494f, 21234277618 [2.123e10]]
  • test_seizeWithMemo_success_configuredReceiverPolicyAllows(address,address,uint256): UnsupportedPolicyType(0xedb5da348cfb67af08746d3afd1be81034b50d5c8576f31aff688f39dfd540ed); counterexample: calldata=0xd1038b0d000000000000000000000000cb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034a0000000000000000000000000000000000000000000000000000000000000040 args=[0xCB00000000000000000000000000000000000000, 0x000000000000000000000000000000000000034a, 64]
  • test_seizeWithMemo_success_emitsEvents(address,address,uint256,bytes32): UnsupportedPolicyType(0xedb5da348cfb67af08746d3afd1be81034b50d5c8576f31aff688f39dfd540ed); counterexample: calldata=0x984936cb000000000000000000000000bdee0392e70362d3a598e061e4a93ace22077fb80000000000000000000000001ddae32d2c9221531429541521cc777252d9b504000000000000003a73b0a04d6f5b84c5a20cc5828009e40a7f5cc83f6650a81827f2f2c3dfe403e11be0a7523b409be28ea9b551d3ec0bc93acf4029f045eff4 args=[0xbDeE0392E70362d3A598e061E4A93ace22077FB8, 0x1DdAE32D2C9221531429541521cC777252d9b504, 366908609874848674637007424216440985862417206534681769584664 [3.669e59], 0x27f2f2c3dfe403e11be0a7523b409be28ea9b551d3ec0bc93acf4029f045eff4]
  • test_seizeWithMemo_success_ignoresReceiverPolicy(address,address,uint256): UnsupportedPolicyType(0xedb5da348cfb67af08746d3afd1be81034b50d5c8576f31aff688f39dfd540ed); counterexample: calldata=0x6358be6c000000000000000000000000ff2efc68a43e49566ca5695e83458a393ae89ea9000000000000000000000000c091d75255c52b5087f76401bc16ce560810d69200000000000000000000133a001df879ad33b4a355ed86d743bc261339446922 args=[0xfF2EFc68A43e49566cA5695e83458A393ae89EA9, 0xc091d75255c52B5087F76401Bc16Ce560810d692, 7193511727309566223174767661854539613187618191468834 [7.193e51]]
  • test_seizeWithMemo_success_movesBalance(address,address,uint256): UnsupportedPolicyType(0xedb5da348cfb67af08746d3afd1be81034b50d5c8576f31aff688f39dfd540ed); counterexample: calldata=0xc4ab022a000000000000000000000000af306fe3ea51a37a850ce690c530f6736bbadcc2000000000000000000000000dda6b7fa23e7e7386767ec2993b8a1265e30b1cdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd args=[0xAf306Fe3ea51a37a850Ce690C530f6736bBaDcc2, 0xDDA6b7fA23e7e7386767eC2993b8A1265e30b1CD, 115792089237316195423570985008687907853269984665640564039457584007913129639933 [1.157e77]]
  • test_seizeWithMemo_success_noAllowanceRequired(address,address,uint256): UnsupportedPolicyType(0xedb5da348cfb67af08746d3afd1be81034b50d5c8576f31aff688f39dfd540ed); counterexample: calldata=0xdc26e1f5000000000000000000000000a6f00135c5968fa5739e4201e12cc5f34132a71a000000000000000000000000288505685752f4b61d629863fdc3bf28f4416720000000000000000000000000001bcc00129fd131e0dc2685201f737f55507ab1 args=[0xA6F00135c5968fa5739e4201E12CC5F34132A71A, 0x288505685752F4b61d629863fdC3BF28f4416720, 619891051446328015150813158090565871196994225 [6.198e44]]
  • test_seizeWithMemo_success_unsetReceiverPolicyAllowsAnyDestination(address,address,uint256): UnsupportedPolicyType(0xedb5da348cfb67af08746d3afd1be81034b50d5c8576f31aff688f39dfd540ed); counterexample: calldata=0x47ad42e20000000000000000000000001e4c39536afe1c2010f2376ba3ff24917b043426000000000000000000000000ba09a2ee366e58ece72f8c8ba67f9db925963de8000cd343816d04cee17cab959198b6d1573fdfdca86f6e47564e6c4ce90d6dfc args=[0x1E4c39536AFE1c2010F2376bA3ff24917B043426, 0xBA09a2ee366E58ECe72f8C8bA67F9db925963dE8, 22660253203073470801954005332893893678486967697444150706900107764616228348 [2.266e73]]
  • test_updatePolicy_revert_policyNotFound(uint8,uint64): Error != expected error: UnsupportedPolicyType(0xedb5da348cfb67af08746d3afd1be81034b50d5c8576f31aff688f39dfd540ed) != PolicyNotFound(144115188075855878 [1.441e17]); counterexample: calldata=0x74fd7f390000000000000000000000000000000000000000000000000000000000000021000000000000000000000000000000000000000000000000000000000000067a args=[33, 1658]
  • test_updatePolicy_success_builtinAllow(uint8): UnsupportedPolicyType(0xedb5da348cfb67af08746d3afd1be81034b50d5c8576f31aff688f39dfd540ed); counterexample: calldata=0xde997e8b0000000000000000000000000000000000000000000000000000000000000003 args=[3]
  • test_updatePolicy_success_builtinReject(uint8): UnsupportedPolicyType(0xedb5da348cfb67af08746d3afd1be81034b50d5c8576f31aff688f39dfd540ed); counterexample: calldata=0x56f5b90800000000000000000000000000000000000000000000000000000000000000b1 args=[177]
    [FAIL: SEIZE_HOLDER_POLICY() must not resolve (renamed to SEIZE_EXEMPT_POLICY)] test_seizeHolderPolicy_revert_selectorRemoved() (gas: 8601)
    [FAIL: UnsupportedPolicyType(0xedb5da348cfb67af08746d3afd1be81034b50d5c8576f31aff688f39dfd540ed)] test_b20Layout_success_populatedSnapshotMatchesAllSlots() (gas: 618346)
    [FAIL: UnsupportedPolicyType(0xedb5da348cfb67af08746d3afd1be81034b50d5c8576f31aff688f39dfd540ed)] test_seizePolicyIdsSlot_success_decodesExemptLane() (gas: 12527)
    [FAIL: custom error 0xfeb346ec] test_SEIZE_EXEMPT_POLICY_success_matchesExpected() (gas: 5185)
    [FAIL: custom error 0xfeb346ec] test_seizeExemptPolicy_success_renamedFromSeizeHolder() (gas: 5187)

@github-actions

github-actions Bot commented Aug 28, 2026

Copy link
Copy Markdown

📊 Forge Coverage (src/lib/)

🟡 ≥95% across all metrics — some metrics below 99%.

File Lines Stmts Branches Funcs
🟡 B20FactoryLib.sol 97.70% 98.00% 100.00% 95.00%
🔴 test/lib/ForceFeeder.sol 0.00% 0.00% 100.00% 0.00%
🔴 test/lib/PrecompileProbe.sol 0.00% 0.00% 0.00% 0.00%
🟢 MockActivationRegistry.sol 100.00% 100.00% 100.00% 100.00%
🟢 MockActivationRegistryStorage.sol 100.00% 100.00% 100.00% 100.00%
🟢 MockB20.sol 100.00% 100.00% 100.00% 100.00%
🟢 MockB20Asset.sol 100.00% 100.00% 100.00% 100.00%
🟡 MockB20Factory.sol 98.96% 99.10% 100.00% 100.00%
🟢 MockB20Stablecoin.sol 100.00% 100.00% 100.00% 100.00%
🟢 MockB20Storage.sol 100.00% 100.00% 100.00% 100.00%
🟡 MockPolicyRegistry.sol 100.00% 99.54% 97.67% 100.00%
🟢 MockPolicyRegistryStorage.sol 100.00% 100.00% 100.00% 100.00%
Total 97.07% 97.52% 98.16% 97.00%

Full report: download artifact. To browse locally: make coverage (runs forge coverage + genhtml + opens the HTML report).

rayyan224 and others added 9 commits August 31, 2026 11:27
Replace the roles stub with a full roles-and-pause concept, write Asset
and Stablecoin as token types, and move execution and versioning into
architecture so callers have one place for each mental model.

Co-authored-by: Cursor <cursoragent@cursor.com>
Replace the stub with a progressive-discovery guide covering registry types, admin lifecycle, scopes, and composite examples.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Give issuers a step-by-step path from SEIZE_ROLE and inverted holder policy through seizeWithMemo, confirmed by the Seized event.

Co-authored-by: Cursor <cursoragent@cursor.com>
Walk operators through scheduling a UI multiplier for corporate actions,
plus cancel, optional transfer pause, and emergency instant override.

Co-authored-by: Cursor <cursoragent@cursor.com>
Replace their nav links with the seize and schedule-multiplier how-tos.

Co-authored-by: Cursor <cursoragent@cursor.com>
Give issuers and indexers a shared on-chain path to disclose operator-driven
holder changes, from announce wrapping through the four corporate-action scenarios.

Co-authored-by: Cursor <cursoragent@cursor.com>
Lead with the issuer job (displayed balances change at an agreed time) instead of the UI-multiplier API name.

Co-authored-by: Cursor <cursoragent@cursor.com>
Give integrators and indexers a concept page for why the scale exists, how WAD encoding works, and how a scheduled flip is read without rewriting raw ERC-20 balances.

Co-authored-by: Cursor <cursoragent@cursor.com>
@rayyan224
rayyan224 marked this pull request as ready for review September 3, 2026 21:52
@rayyan224
rayyan224 merged commit be6d045 into main Sep 3, 2026
10 checks passed
@rayyan224
rayyan224 deleted the docs/restructure-b20-guides branch September 3, 2026 22:11
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