diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/index.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/index.mdx
new file mode 100644
index 000000000..d9183f14d
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/index.mdx
@@ -0,0 +1,220 @@
+---
+title: "B20 specification"
+description: "Normative Beryl specification for Base's B20 native token standard, precompile registries, policy scopes, factory, and variants."
+---
+
+
+This is the normative Beryl specification for B20.
+
+
+B20 is Base's native ERC-20-compatible token standard implemented as Rust precompiles. It adds chain-native roles, policy scopes, memos, pausing, supply caps, ERC-2612 `permit`, deterministic factory creation, and variant-specific surfaces for Asset and Stablecoin tokens.
+
+## ERC-20 Compatibility
+
+B20 is a superset of ERC-20. Standard ERC-20 calls and events keep selector and behavior parity for `transfer`, `transferFrom`, `approve`, `allowance`, `balanceOf`, `totalSupply`, `name`, `symbol`, `decimals`, `Transfer`, and `Approval`.
+
+B20-specific methods extend the standard without changing the ERC-20 surface.
+
+## Roles Model
+
+B20 includes role-based access control with fixed built-in roles.
+
+| Role | Gates |
+|---|---|
+| `DEFAULT_ADMIN_ROLE` | `grantRole`, `revokeRole`, `setRoleAdmin`, `updatePolicy`, `updateSupplyCap` |
+| `MINT_ROLE` | `mint`, `mintWithMemo` |
+| `BURN_ROLE` | `burn`, `burnWithMemo` |
+| `BURN_BLOCKED_ROLE` | Deprecated back-compat `burnBlocked` path |
+| `SEIZE_ROLE` | `seizeWithMemo` |
+| `PAUSE_ROLE` | `pause` |
+| `UNPAUSE_ROLE` | `unpause` |
+| `METADATA_ROLE` | `updateName`, `updateSymbol`, `updateContractURI` |
+| `OPERATOR_ROLE` | Asset-only multiplier and announcement operations |
+
+User-defined roles are supported by the role graph but have no built-in enforcement by B20 token functions.
+
+### Admin Renunciation
+
+The final `DEFAULT_ADMIN_ROLE` holder cannot be removed with normal `renounceRole` or `revokeRole`; both revert with `LastAdminCannotRenounce`. `renounceLastAdmin()` is the only normal path to permanently transition to admin-less operation.
+
+A token can launch admin-less by setting `initialAdmin == address(0)` at creation. After admin renunciation, `DEFAULT_ADMIN_ROLE`-gated functions are permanently uncallable and admin resurrection is blocked.
+
+## Policy Registry
+
+The PolicyRegistry is a singleton precompile that stores policies addressed by `uint64 policyId`. B20 tokens store policy IDs in fixed scopes and call `isAuthorized(policyId, account)` during gated operations.
+
+State-changing PolicyRegistry calls are ActivationRegistry-gated. Read functions are always callable.
+
+### Policy Types
+
+| PolicyType | Behavior |
+|---|---|
+| `BLOCKLIST` | Account is authorized unless listed. |
+| `ALLOWLIST` | Account is authorized only if listed. |
+| `UNION` | Composite: account is authorized if any child simple policy authorizes it. |
+| `INTERSECT` | Composite: account is authorized only if every child simple policy authorizes it. |
+
+Composite policies reference existing simple `ALLOWLIST` or `BLOCKLIST` child policies. They cannot reference composites or built-ins as children.
+
+### Policy IDs
+
+Policy IDs are laid out as:
+
+```text
+[top 8 bits: PolicyType][low 56 bits: counter]
+```
+
+Counters `0` and `1` are reserved for built-ins:
+
+| Built-in | Value | Behavior |
+|---|---:|---|
+| `ALWAYS_ALLOW` | `0` | Authorizes every account. |
+| `ALWAYS_BLOCK` | `(uint64(ALLOWLIST) << 56) \| 1` | Denies every account. |
+
+Custom policy creation starts at counter `2`.
+
+### Admin Model
+
+Each policy has one admin. Admin transfer is two-step: `stageUpdateAdmin(policyId, newAdmin)` followed by `finalizeUpdateAdmin(policyId)` from the pending admin. `renounceAdmin(policyId)` permanently freezes membership or child-policy updates for that policy.
+
+### Read Interface
+
+| Method | Description |
+|---|---|
+| `isAuthorized(policyId, account)` | Returns authorization and never reverts for uncreated IDs. |
+| `policyExists(policyId)` | Returns whether a policy exists. |
+| `policyAdmin(policyId)` | Returns the current admin or zero. |
+| `pendingPolicyAdmin(policyId)` | Returns the staged admin or zero. |
+| `compositePolicyChildIds(policyId)` | Returns child policy IDs for composite policies. |
+
+`isAuthorized` collapses uncreated IDs to empty-set semantics. Callers that write policy IDs into token scopes must validate `policyExists` unless writing a built-in.
+
+## Policy Integration
+
+B20 tokens store one `uint64 policyId` per supported policy scope.
+
+| Scope | Checked account | Operation |
+|---|---|---|
+| `TRANSFER_SENDER_POLICY` | `from` | `transfer`, `transferFrom`, and memo variants |
+| `TRANSFER_RECEIVER_POLICY` | `to` | `transfer`, `transferFrom`, and memo variants |
+| `TRANSFER_EXECUTOR_POLICY` | `msg.sender` | `transferFrom` when `msg.sender != from` |
+| `MINT_RECEIVER_POLICY` | `to` | `mint`, `mintWithMemo` |
+| `SEIZE_HOLDER_POLICY` | `from` | `seizeWithMemo`; holder is seizable only when not authorized |
+
+All scopes default to `ALWAYS_ALLOW` at creation. `approve` and `permit` are not policy-gated.
+
+## Mint
+
+`mint` and `mintWithMemo` are gated by `MINT_ROLE`, checked against `MINT_RECEIVER_POLICY`, and bounded by `supplyCap`.
+
+## Burn
+
+`burn` and `burnWithMemo` burn from the caller and are gated by `BURN_ROLE`.
+
+The legacy `burnBlocked` path is deprecated and retained for backwards compatibility. New seizure flows use `seizeWithMemo`.
+
+## Seize
+
+`seizeWithMemo(from, to, amount, memo)` transfers balance from `from` to `to` and emits `Transfer`, `Memo`, and `Seized`. It is gated by `SEIZE_ROLE`, skips allowance and transfer policies, and requires `from` to be denied by `SEIZE_HOLDER_POLICY`.
+
+## Supply Cap
+
+The supply cap is optional. The sentinel `type(uint128).max` indicates no practical cap and is also the maximum permitted `totalSupply`. `updateSupplyCap` is admin-gated and reverts with `InvalidSupplyCap` if the proposed cap is below current supply or above the maximum.
+
+## Memos
+
+Memo-enabled operations emit `Memo(address indexed caller, bytes32 indexed memo)` immediately after the primary operation event. Indexers join memo logs to the parent log with `(transactionHash, logIndex - 1)`.
+
+Memo entrypoints include `transferWithMemo`, `transferFromWithMemo`, `mintWithMemo`, `burnWithMemo`, and `seizeWithMemo`.
+
+## Pause
+
+B20 supports granular pausing by `PausableFeature`: `TRANSFER`, `MINT`, `BURN`, and `SEIZE`. The enum is append-only. `pause` is gated by `PAUSE_ROLE`; `unpause` is gated by `UNPAUSE_ROLE`.
+
+## ERC-2612 Permit / EIP-712
+
+B20 implements ERC-2612 signed approvals with an EIP-712 domain shaped as `(name, version, chainId, verifyingContract)`, with `version` fixed at `"1"`. `updateName` rotates the domain separator and emits `EIP712DomainChanged`. ERC-1271 contract signatures are not accepted.
+
+## Contract URI (ERC-7572)
+
+`contractURI()` returns offchain token metadata per ERC-7572. `updateContractURI(newURI)` is gated by `METADATA_ROLE`.
+
+## Metadata Updates
+
+`updateName` and `updateSymbol` are gated by `METADATA_ROLE`. `updateName` also rotates the EIP-712 domain separator.
+
+## Factory
+
+All B20 tokens are created through the singleton factory precompile:
+
+```solidity
+createB20(B20Variant variant, bytes32 salt, bytes params, bytes[] initCalls)
+```
+
+| Parameter | Description |
+|---|---|
+| `variant` | `ASSET` or `STABLECOIN` |
+| `salt` | Caller-chosen entropy for deterministic address derivation |
+| `params` | Versioned, variant-specific create params |
+| `initCalls` | ABI-encoded bootstrap calls dispatched to the new token |
+
+The factory reverts with `FeatureNotActivated` if the requested variant is not activated.
+
+### Address Derivation
+
+B20 token addresses are deterministic and encode the variant:
+
+```text
+[10-byte B20 prefix][1-byte variant][9-byte keccak256(deployer, salt)]
+```
+
+`getB20Address`, `isB20`, and `isB20Initialized` are available on the factory.
+
+### initCalls Semantics
+
+During initCalls, factory-originated calls bypass token role gates and transfer-side policy gates: `TRANSFER_SENDER_POLICY`, `TRANSFER_RECEIVER_POLICY`, and `TRANSFER_EXECUTOR_POLICY`.
+
+The bypass does not apply to `MINT_RECEIVER_POLICY`, pause state, supply cap, or balance accounting invariants. The bootstrap window closes when `createB20` returns.
+
+## Variants
+
+| Variant | Byte | Decimals | Additional surface |
+|---|---:|---|---|
+| `ASSET` | `0x00` | 6-18, configured at creation | Multiplier, announcements, batch mint, extra metadata |
+| `STABLECOIN` | `0x01` | Fixed 6 | `currency()` |
+
+### Asset
+
+Asset tokens add `OPERATOR_ROLE`, scaled UI balance support, scheduled and instant multiplier updates, announcements, batch minting, and extra metadata.
+
+#### Multiplier
+
+The multiplier is WAD-precision and scales UI balance reads while raw balances remain unchanged.
+
+#### Announcements
+
+`announce` emits `Announcement`, dispatches internal calls, and emits `EndAnnouncement`. Announcement IDs are unique forever. Non-panic inner reverts are wrapped in `InternalCallFailed`.
+
+#### Batch Mint
+
+`batchMint` mints to parallel recipient and amount arrays atomically and is gated by `MINT_ROLE`.
+
+#### Extra Metadata
+
+`extraMetadata(key)` reads issuer-defined metadata. `updateExtraMetadata(key, value)` writes it and deletes the entry when `value` is empty.
+
+### Stablecoin
+
+Stablecoin tokens add `currency()`, set once at creation. The value must contain uppercase `A`-`Z` characters only. B20 validates the code format, not the issuer claim, reserves, legal status, or external registration.
+
+## Precompile addresses
+
+| Precompile | Address |
+|---|---|
+| B20Factory | `0xB20f000000000000000000000000000000000000` |
+| ActivationRegistry | `0x8453000000000000000000000000000000000001` |
+| PolicyRegistry | `0x8453000000000000000000000000000000000002` |
+
+## Developer documentation
+
+- [Generated reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses.mdx
new file mode 100644
index 000000000..800df9bf8
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses.mdx
@@ -0,0 +1,85 @@
+---
+title: "Constants & addresses"
+description: "Copy B20 precompile addresses, roles, policy scopes, variant bytes, policy IDs, and supply-cap constants."
+---
+
+Use `StdPrecompiles.sol` and `B20Constants.sol` from `base-std` as the canonical Solidity source. This page lists the same values for quick reference.
+
+## Precompile addresses
+
+These addresses are identical on every network where B20 is active.
+
+| Surface | Address |
+|---|---|
+| B20 Factory | `0xB20f000000000000000000000000000000000000` |
+| ActivationRegistry | `0x8453000000000000000000000000000000000001` |
+| PolicyRegistry | `0x8453000000000000000000000000000000000002` |
+
+## Roles
+
+| Role | Solidity constant |
+|---|---|
+| Default admin | `bytes32(0)` |
+| Mint | `keccak256("MINT_ROLE")` |
+| Burn | `keccak256("BURN_ROLE")` |
+| Deprecated blocked burn | `keccak256("BURN_BLOCKED_ROLE")` |
+| Seize | `keccak256("SEIZE_ROLE")` |
+| Pause | `keccak256("PAUSE_ROLE")` |
+| Unpause | `keccak256("UNPAUSE_ROLE")` |
+| Metadata | `keccak256("METADATA_ROLE")` |
+| Asset operator | `keccak256("OPERATOR_ROLE")` |
+
+## Policy scopes
+
+| Scope | Solidity constant |
+|---|---|
+| Transfer sender | `keccak256("TRANSFER_SENDER_POLICY")` |
+| Transfer receiver | `keccak256("TRANSFER_RECEIVER_POLICY")` |
+| Transfer executor | `keccak256("TRANSFER_EXECUTOR_POLICY")` |
+| Mint receiver | `keccak256("MINT_RECEIVER_POLICY")` |
+| Seize holder | `keccak256("SEIZE_HOLDER_POLICY")` |
+
+## Policy IDs
+
+| Name | Value |
+|---|---|
+| `ALWAYS_ALLOW` | `0` |
+| `ALWAYS_BLOCK` | `(uint64(uint8(IPolicyRegistry.PolicyType.ALLOWLIST)) << 56) \| 1` |
+
+Custom policy IDs use this layout:
+
+```text
+[8-bit PolicyType][56-bit counter]
+```
+
+Policy type bytes:
+
+| PolicyType | Byte |
+|---|---:|
+| `BLOCKLIST` | `0x00` |
+| `ALLOWLIST` | `0x01` |
+| `UNION` | `0x02` |
+| `INTERSECT` | `0x03` |
+
+## Variant bytes
+
+| Variant | Byte | Address shape |
+|---|---:|---|
+| `ASSET` | `0x00` | `0xB200...` |
+| `STABLECOIN` | `0x01` | `0xB201...` |
+
+## Supply and decimals
+
+| Constant | Value |
+|---|---:|
+| Minimum Asset decimals | `6` |
+| Maximum Asset decimals | `18` |
+| Maximum supply cap / no-cap sentinel | `type(uint128).max` |
+| All features paused bitmask | `15` (`TRANSFER | MINT | BURN | SEIZE`) |
+
+## Imports
+
+```solidity
+import {StdPrecompiles} from "base-std/StdPrecompiles.sol";
+import {B20Constants} from "base-std/lib/B20Constants.sol";
+```
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/errors-and-events-index.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/errors-and-events-index.mdx
new file mode 100644
index 000000000..a7952af39
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/errors-and-events-index.mdx
@@ -0,0 +1,98 @@
+---
+title: "Errors & events index"
+description: "Reverse lookup B20 errors and events by selector or topic."
+---
+
+
+## Index
+
+| Type | Name | Selector / topic0 | Interface | Meaning |
+|---|---|---|---|---|
+| error | `AccessControlBadConfirmation` | `0x6697b232` | `IB20` | The `callerConfirmation` argument to `renounceRole` was not `msg.sender`. |
+| error | `AccessControlUnauthorizedAccount` | `0xe2517d3f` | `IB20` | `account` does not hold `neededRole`. |
+| error | `AccountNotBlocked` | `0x64a5cb46` | `IB20` | The deprecated `burnBlocked` was called against a `from` that is currently authorized under |
+| error | `AccountNotSeizable` | `0x91dbbc8d` | `IB20` | `seizeWithMemo` was called against a `from` that is currently authorized under |
+| event | `AllowlistUpdated` | `0x18c46532f90187ba11e436e21da087b684801d7f0787f2043f26f079c91e9ef0` | `IPolicyRegistry` | One or more accounts had their ALLOWLIST membership set to `allowed` in a single batch. |
+| error | `AlreadyActivated` | `0x866b0041` | `IActivationRegistry` | Feature is already activated. |
+| event | `Announcement` | `0xccebf8218a62875909564adef86a6f4df81503cb617221e793357d62f8e813f7` | `IB20Asset` | Emitted by `announce` to open an announcement bracket. |
+| error | `AnnouncementIdAlreadyUsed` | `0xd10b3c9e` | `IB20Asset` | `announce` was called with an `id` that has already been consumed. |
+| error | `AnnouncementInProgress` | `0x5c5f0829` | `IB20Asset` | An inner call dispatched by `announce` tried to re-invoke `announce`. |
+| event | `Approval` | `0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925` | `IB20` | ERC-20 approval event. Emitted by `approve` and `permit`. |
+| event | `B20Created` | `0x86ee7a93da43b07286ea4c925a31ba17c41eb00c5ea396883bf32abfe5e73cfc` | `IB20Factory` | Emitted once per `createB20` invocation, after the token's identity is sealed |
+| error | `BatchSizeTooLarge` | `0x083e2f67` | `IPolicyRegistry` | A membership batch exceeded the registry limit. |
+| event | `BlocklistUpdated` | `0x2ff63c102b1b9fd7f5d39f83039c5d6aaf50a414a4f2def2704e41be2628f1e3` | `IPolicyRegistry` | One or more accounts had their BLOCKLIST membership set to `blocked` in a single batch. |
+| event | `BurnedBlocked` | `0x0b552e96653fd6842da37c477005d3b5c08a8c7d3631b1f43787b2dc9a1006a3` | `IB20` | Emitted by the deprecated `burnBlocked` in addition to `Transfer(from, address(0), amount)`. |
+| error | `ChildPoliciesOutsideOfRange` | `0xcbdee0f6` | `IPolicyRegistry` | A composite policy was created or updated with a child-policy count outside the |
+| event | `CompositePolicyUpdated` | `0x4ff6adaab31b0df87aa7b8b7320c52b8b3b5eede3bf28a6baaaa8b8b7e1d6363` | `IPolicyRegistry` | A composite policy's child set was set or replaced in full with `childPolicyIds`. Emitted |
+| error | `ContractPaused` | `0xf9df5ac9` | `IB20` | The `PausableFeature` covering this operation is currently paused. |
+| event | `ContractURIUpdated` | `0xa5d4097edda6d87cb9329af83fb3712ef77eeb13738ffe43cc35a4ce305ad962` | `IB20` | Emitted by `updateContractURI`. Per ERC-7572, parameterless: integrators re-fetch `contractURI()`. |
+| error | `DelegateCallNotAllowed` | `0x0d89438e` | `IActivationRegistry` | The precompile was invoked via `DELEGATECALL` or `CALLCODE`. |
+| error | `EffectiveAtInPast` | `0x14119cf6` | `IB20Asset` | `setUIMultiplier` was called with an `effectiveAt` that is not in the future |
+| error | `EffectiveAtTooFar` | `0x1ce214fa` | `IB20Asset` | `setUIMultiplier` was called with an `effectiveAt` above `type(uint64).max`, the |
+| event | `EIP712DomainChanged` | `0x0a6387c9ea3628b88a633bb4f3b151770f70085117a15f9bf3787cda53f13d31` | `IB20` | ERC-5267 domain-change signal. Emitted exactly once per successful `updateName` call, |
+| error | `EmptyBatch` | `0xc2e5347d` | `IB20Asset` | A batched function was called with empty arrays. |
+| error | `EmptyFeatureSet` | `0x4861ff45` | `IB20` | An empty array was passed to a function that requires at least one element. |
+| event | `EndAnnouncement` | `0x96d64dafe2c790596430196b982ad1da3221cb3b0f4e6e2df77f2e4f71a90037` | `IB20Asset` | Emitted by `announce` to close the bracket opened by the paired `Announcement` with the same `id`. |
+| error | `ExpiredSignature` | `0xbd2a913c` | `IB20` | An EIP-2612 `permit` was submitted with a `deadline` strictly less than `block.timestamp`. |
+| event | `ExtraMetadataUpdated` | `0xd7bb345be29e78d635203d40fe0567e7ef19d5cd5cc5fcd25f768b8063e82aa1` | `IB20Asset` | Emitted by `updateExtraMetadata`. An empty `value` indicates removal. |
+| event | `FeatureActivated` | `0x8c7a0ecdbb8d96e867e43ec1aef80027976ee493c18bef399fa799ed19752451` | `IActivationRegistry` | Emitted when `feature` is activated. |
+| event | `FeatureDeactivated` | `0x15bf65a782c3258c63268ba9d7aed710cf9f9315d3687d9a4632ccdad7926c84` | `IActivationRegistry` | Emitted when `feature` is deactivated. |
+| error | `FeatureNotActivated` | `0xb9b2a425` | `IActivationRegistry` | Feature is not activated. |
+| error | `IncompatiblePolicyType` | `0xf1011ef5` | `IPolicyRegistry` | The operation is incompatible with the policy's type. |
+| error | `InitCallFailed` | `0x4eae0860` | `IB20Factory` | One of the `initCalls` reverted. The factory bubbles the underlying revert reason |
+| error | `InsufficientAllowance` | `0x192b9e4e` | `IB20` | `spender`'s allowance is less than `needed` for the requested `transferFrom`. |
+| error | `InsufficientBalance` | `0xdb42144d` | `IB20` | `sender`'s balance is less than `needed` for the requested transfer or burn. |
+| error | `InternalCallFailed` | `0xb288a127` | `IB20Asset` | An inner call dispatched by `announce` reverted with an ordinary revert; its reason is |
+| error | `InternalCallMalformed` | `0x4e2f143e` | `IB20Asset` | An inner call dispatched by `announce` was shorter than four bytes. |
+| error | `InvalidAmount` | `0x2c5211c6` | `IB20` | An amount argument was zero where a non-zero value is required. Not used for ERC-20 amount arguments. |
+| error | `InvalidApprover` | `0x8bc146c4` | `IB20` | The approval's `owner` address is invalid (typically `address(0)`). |
+| error | `InvalidChildPolicy` | `0x46508ef6` | `IPolicyRegistry` | Composite policies are not simple policies. Child policies must be existing |
+| error | `InvalidCurrency` | `0x997c1de8` | `IB20Factory` | The stablecoin `currency` was non-empty but contained a non-`A`-`Z` byte. |
+| error | `InvalidDecimals` | `0xca950391` | `IB20Factory` | The asset `decimals` was outside the allowed inclusive range |
+| error | `InvalidMetadataKey` | `0x86ea3abb` | `IB20Asset` | `updateExtraMetadata` was called with an empty `key`. |
+| error | `InvalidMultiplier` | `0x6f12f3dc` | `IB20Asset` | A multiplier setter (`setUIMultiplier` or `updateMultiplier`) was called with a |
+| error | `InvalidReceiver` | `0x9cfea583` | `IB20` | The transfer's destination address is invalid (typically `address(0)`). |
+| error | `InvalidSender` | `0x4c14f64c` | `IB20` | The transfer's source address is invalid (typically `address(0)`). |
+| error | `InvalidSigner` | `0x7ba5ffb5` | `IB20` | ECDSA recovery on an EIP-2612 `permit` returned `signer`, which does not match the claimed `owner`. |
+| error | `InvalidSpender` | `0x4e15efda` | `IB20` | The approval's `spender` address is invalid (typically `address(0)`). |
+| error | `InvalidSupplyCap` | `0x0a3780ce` | `IB20` | The proposed supply cap is outside the permitted range: below the current |
+| error | `InvalidVariant` | `0xf10e8e43` | `IB20Factory` | `variant` is not a recognized `B20Variant`. |
+| error | `LastAdminCannotRenounce` | `0x361513e7` | `IB20` | `renounceRole(DEFAULT_ADMIN_ROLE, ...)` was called by the sole remaining admin. |
+| event | `LastAdminRenounced` | `0xe8d3a9872e7ca325571ff1e4c51ddd69090a0345240cc605ccde365ec867cc67` | `IB20` | Emitted by `renounceLastAdmin` in addition to the standard |
+| error | `LengthMismatch` | `0xab8b67c6` | `IB20Asset` | A batched function was called with parallel arrays of differing lengths. |
+| event | `Memo` | `0x6989f5818dcfd11f8cd53b27c94cec33dae1589735f03e639cba54553a1825e8` | `IB20` | Emitted by `transferWithMemo`, `transferFromWithMemo`, `mintWithMemo`, and `burnWithMemo` |
+| error | `MissingRequiredField` | `0x4a43ae87` | `IB20Factory` | A required string argument was the empty string. |
+| event | `MultiplierUpdateCancelled` | `0xf8929975f3e67bbd1e5ec70d4cceaa7cce7ea0e811720f29c96cf1724de09397` | `IB20Asset` | A scheduled multiplier update was cancelled. Emitted by `cancelScheduledMultiplier`, |
+| event | `NameUpdated` | `0x74321da206c1b9fa34367f7ece59ca49371dcd13820b9a5c3767ae1ecceed51a` | `IB20` | Emitted by `updateName`. Carries the new name string. |
+| error | `NonPayable` | `0x6fb1b0e9` | `IB20` | ETH was attached to a call targeting a nonpayable token selector. |
+| error | `NonPayable` | `0x6fb1b0e9` | `IB20Factory` | ETH was attached to a call targeting a nonpayable factory selector. |
+| error | `NonPayable` | `0x6fb1b0e9` | `IPolicyRegistry` | ETH was attached to a call targeting a nonpayable policy registry selector. |
+| error | `NoPendingAdmin` | `0xb4539afa` | `IPolicyRegistry` | `finalizeUpdateAdmin` was called with no pending admin staged. |
+| error | `NoScheduledMultiplier` | `0x002e806f` | `IB20Asset` | `cancelScheduledMultiplier` was called when there is no live pending update |
+| error | `NotSoleAdmin` | `0x2a98e73b` | `IB20` | `renounceLastAdmin()` was called when other accounts also hold `DEFAULT_ADMIN_ROLE`. |
+| event | `Paused` | `0x43e072977b8112813d7c2aa0b63d3c121c1fe3e714e6d2eacb5735fe4027e976` | `IB20` | Emitted by `pause`. `features` is the argument to the call (not the resulting paused state). |
+| event | `PolicyAdminStaged` | `0xdbf3b34a4c956c56ca05cd4b8f9293a4347ad61994445a4b89817d4a19561136` | `IPolicyRegistry` | A new admin was staged. `pendingAdmin == address(0)` clears a prior nomination. |
+| event | `PolicyAdminUpdated` | `0x98925cfb1bc09c5b43dd0dd56d3d95aa04fb3300927580cc588c3f5dd58c15e1` | `IPolicyRegistry` | The active admin changed. `newAdmin == address(0)` indicates renunciation; |
+| event | `PolicyCreated` | `0xdc870ce85be577234b8548f42b93f84bbff6d0c1f38ee725c809c49932a13885` | `IPolicyRegistry` | A new policy was created. |
+| error | `PolicyForbids` | `0xa43fec12` | `IB20` | A policy slot denied the operation. |
+| error | `PolicyNotFound` | `0xcccad523` | `IB20` | The provided policy ID does not exist in the policy registry. |
+| error | `PolicyNotFound` | `0x720caa4f` | `IPolicyRegistry` | The referenced policy ID does not exist. |
+| event | `PolicyUpdated` | `0x8b4790f7ff717fc8f60f07ae099e47ef318dc04b37ae98056b50a22b79056626` | `IB20` | Emitted by `updatePolicy` when a token's policy slot is changed. Initial slot assignment at |
+| event | `RoleAdminChanged` | `0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff` | `IB20` | Emitted by `setRoleAdmin` when the admin role for `role` changes. |
+| event | `RoleGranted` | `0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d` | `IB20` | Emitted when `account` is granted `role`. `sender` is the originating caller. |
+| event | `RoleRevoked` | `0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b` | `IB20` | Emitted when `role` is revoked from `account`. `sender` is the originating caller |
+| error | `ScheduleOverlap` | `0x91a52665` | `IB20Asset` | `setUIMultiplier` was called while a live pending update already exists |
+| event | `Seized` | `0xa9aec5d8b86e2fa2fd6ac3af62f2622e3dfdab1967d4cbbb56a5df7d74cb887c` | `IB20` | Emitted by `seizeWithMemo` in addition to `Transfer(from, to, amount)` (and the |
+| error | `StaticCallNotAllowed` | `0xbeaba5b7` | `IActivationRegistry` | A state-mutating entry point was invoked from a `STATICCALL` frame. |
+| error | `SupplyCapExceeded` | `0x4b344b11` | `IB20` | The mint would push `totalSupply` past the configured cap. |
+| event | `SupplyCapUpdated` | `0x6d14f44808ce024f263432bc38d019a9951fbe674e9898b54844dbc8dc09c23a` | `IB20` | Emitted by `updateSupplyCap`. |
+| event | `SymbolUpdated` | `0x64e8b5c6dcea43dd79766bb3b8af7c45968d12b68c960cf2da23856f34d598d4` | `IB20` | Emitted by `updateSymbol`. Carries the new symbol string. |
+| error | `TokenAlreadyExists` | `0x15ef3a57` | `IB20Factory` | A token already exists at the deterministic address derived from |
+| event | `Transfer` | `0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef` | `IB20` | ERC-20 transfer event. Emitted on every successful transfer (including memo'd variants), |
+| error | `Unauthorized` | `0x8e4a23d6` | `IActivationRegistry` | Caller is not the activation admin. |
+| error | `Unauthorized` | `0x82b42900` | `IB20` | Caller failed a positional authorization check that is not expressible as "missing role X". |
+| error | `Unauthorized` | `0x82b42900` | `IPolicyRegistry` | Caller is not the admin required by the attempted operation. |
+| event | `Unpaused` | `0xdc6281474ea3dea2a856e225c7ba3edf427de9164495817c4d49a595e683fed4` | `IB20` | Emitted by `unpause`. `features` is the argument to the call (not the resulting paused state). |
+| error | `UnsupportedPolicyType` | `0xcdd98a4a` | `IB20` | `policyScope` is not a slot this token (or its variant) supports. |
+| error | `UnsupportedVersion` | `0x6f3c1955` | `IB20Factory` | The leading `version` byte in `params` does not match any known encoding for the requested variant. |
+| error | `ZeroAddress` | `0xd92e233d` | `IPolicyRegistry` | A required address argument was the zero address. |
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry.mdx
new file mode 100644
index 000000000..3b9d07084
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry.mdx
@@ -0,0 +1,37 @@
+---
+title: "IActivationRegistry reference"
+description: "Generated B20 reference for IActivationRegistry functions, events, and errors."
+---
+
+
+## Functions
+
+| Function | Selector | Summary |
+|---|---|---|
+| [`isActivated`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry/isActivated) | `0xba87af80` | Whether `feature` is currently activated. Never reverts. |
+| [`checkActivated`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry/checkActivated) | `0xde5bfd9b` | Reverts with `FeatureNotActivated(feature)` if `feature` is not currently activated. |
+| [`admin`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry/admin) | `0xf851a440` | The address authorized to call `activate` and `deactivate`. |
+| [`activate`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry/activate) | `0x59db6e85` | Activates `feature`. Emits `FeatureActivated`. |
+| [`deactivate`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry/deactivate) | `0x22eee84c` | Deactivates `feature`. Emits `FeatureDeactivated`. |
+
+## Events
+
+| Event | Topic0 | Summary |
+|---|---|---|
+| `FeatureActivated` | `0x8c7a0ecdbb8d96e867e43ec1aef80027976ee493c18bef399fa799ed19752451` | Emitted when `feature` is activated. |
+| `FeatureDeactivated` | `0x15bf65a782c3258c63268ba9d7aed710cf9f9315d3687d9a4632ccdad7926c84` | Emitted when `feature` is deactivated. |
+
+## Errors
+
+| Error | Selector | Summary |
+|---|---|---|
+| `Unauthorized` | `0x8e4a23d6` | Caller is not the activation admin. |
+| `AlreadyActivated` | `0x866b0041` | Feature is already activated. |
+| `FeatureNotActivated` | `0xb9b2a425` | Feature is not activated. |
+| `DelegateCallNotAllowed` | `0x0d89438e` | The precompile was invoked via `DELEGATECALL` or `CALLCODE`. |
+| `StaticCallNotAllowed` | `0xbeaba5b7` | A state-mutating entry point was invoked from a `STATICCALL` frame. |
+
+
+
+
+
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry/activate.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry/activate.mdx
new file mode 100644
index 000000000..cdf739353
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry/activate.mdx
@@ -0,0 +1,46 @@
+---
+title: "IActivationRegistry.activate"
+description: "Generated B20 reference for activate(bytes32)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/architecture-and-precompiles)
+
+## Signature
+
+```solidity
+function activate(bytes32 feature) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x59db6e85` |
+| Canonical signature | `activate(bytes32)` |
+
+## Description
+
+Activates `feature`. Emits `FeatureActivated`.
+Dev: Reverts with `DelegateCallNotAllowed` when invoked via `DELEGATECALL` or `CALLCODE`.
+Dev: Reverts with `StaticCallNotAllowed` when invoked under `STATICCALL`.
+Dev: Reverts with `Unauthorized` when the caller is not the activation admin.
+Dev: Reverts with `AlreadyActivated` when `feature` is already activated.
+Param: feature Feature to activate.
+
+## Access control
+
+Callable by the ActivationRegistry admin.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IActivationRegistry(target).activate(arg0);
+```
+
+## Related
+
+- [IActivationRegistry reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry/admin.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry/admin.mdx
new file mode 100644
index 000000000..30bd3957c
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry/admin.mdx
@@ -0,0 +1,42 @@
+---
+title: "IActivationRegistry.admin"
+description: "Generated B20 reference for admin()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/architecture-and-precompiles)
+
+## Signature
+
+```solidity
+function admin() external view returns (address);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xf851a440` |
+| Canonical signature | `admin()` |
+
+## Description
+
+The address authorized to call `activate` and `deactivate`.
+Return: Current activation admin.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IActivationRegistry(target).admin();
+```
+
+## Related
+
+- [IActivationRegistry reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry/checkActivated.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry/checkActivated.mdx
new file mode 100644
index 000000000..22f2d1e62
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry/checkActivated.mdx
@@ -0,0 +1,44 @@
+---
+title: "IActivationRegistry.checkActivated"
+description: "Generated B20 reference for checkActivated(bytes32)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/architecture-and-precompiles)
+
+## Signature
+
+```solidity
+function checkActivated(bytes32 feature) external view;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xde5bfd9b` |
+| Canonical signature | `checkActivated(bytes32)` |
+
+## Description
+
+Reverts with `FeatureNotActivated(feature)` if `feature` is not currently activated.
+A pure assertion entry point so callers don't have to redefine the error.
+Dev: Reverts with `FeatureNotActivated` when `feature` is not activated.
+Param: feature Feature to assert is active.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IActivationRegistry(target).checkActivated(arg0);
+```
+
+## Related
+
+- [IActivationRegistry reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry/deactivate.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry/deactivate.mdx
new file mode 100644
index 000000000..acfe20f09
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry/deactivate.mdx
@@ -0,0 +1,46 @@
+---
+title: "IActivationRegistry.deactivate"
+description: "Generated B20 reference for deactivate(bytes32)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/architecture-and-precompiles)
+
+## Signature
+
+```solidity
+function deactivate(bytes32 feature) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x22eee84c` |
+| Canonical signature | `deactivate(bytes32)` |
+
+## Description
+
+Deactivates `feature`. Emits `FeatureDeactivated`.
+Dev: Reverts with `DelegateCallNotAllowed` when invoked via `DELEGATECALL` or `CALLCODE`.
+Dev: Reverts with `StaticCallNotAllowed` when invoked under `STATICCALL`.
+Dev: Reverts with `Unauthorized` when the caller is not the activation admin.
+Dev: Reverts with `AlreadyDeactivated` when `feature` is already deactivated.
+Param: feature Feature to deactivate.
+
+## Access control
+
+Callable by the ActivationRegistry admin.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IActivationRegistry(target).deactivate(arg0);
+```
+
+## Related
+
+- [IActivationRegistry reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry/isActivated.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry/isActivated.mdx
new file mode 100644
index 000000000..744d1bdf9
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry/isActivated.mdx
@@ -0,0 +1,43 @@
+---
+title: "IActivationRegistry.isActivated"
+description: "Generated B20 reference for isActivated(bytes32)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/architecture-and-precompiles)
+
+## Signature
+
+```solidity
+function isActivated(bytes32 feature) external view returns (bool);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xba87af80` |
+| Canonical signature | `isActivated(bytes32)` |
+
+## Description
+
+Whether `feature` is currently activated. Never reverts.
+Param: feature Feature to query.
+Return: Whether `feature` is activated.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IActivationRegistry(target).isActivated(arg0);
+```
+
+## Related
+
+- [IActivationRegistry reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IActivationRegistry)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20.mdx
new file mode 100644
index 000000000..6f68208a5
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20.mdx
@@ -0,0 +1,118 @@
+---
+title: "IB20 reference"
+description: "Generated B20 reference for IB20 functions, events, and errors."
+---
+
+
+## Functions
+
+| Function | Selector | Summary |
+|---|---|---|
+| [`DEFAULT_ADMIN_ROLE`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/DEFAULT_ADMIN_ROLE) | `0xa217fddf` | The default top-level admin role (`bytes32(0)`). Required to call `grantRole`, `revokeRole`, |
+| [`MINT_ROLE`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/MINT_ROLE) | `0xe9a9c850` | Required to call `mint` and `mintWithMemo`. |
+| [`BURN_ROLE`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/BURN_ROLE) | `0xb930908f` | Required to call `burn` and `burnWithMemo`. |
+| [`BURN_BLOCKED_ROLE`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/BURN_BLOCKED_ROLE) | `0x32ad9be8` | Required to call the deprecated `burnBlocked` (no longer part of this interface; retained for |
+| [`SEIZE_ROLE`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/SEIZE_ROLE) | `0x3c7e9ba5` | Required to call `seizeWithMemo`. |
+| [`PAUSE_ROLE`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/PAUSE_ROLE) | `0x389ed267` | Required to call `pause`. |
+| [`UNPAUSE_ROLE`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/UNPAUSE_ROLE) | `0x309756fb` | Required to call `unpause`. |
+| [`METADATA_ROLE`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/METADATA_ROLE) | `0x38841782` | Required to call `updateName`, `updateSymbol`, and `updateContractURI`. |
+| [`TRANSFER_SENDER_POLICY`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/TRANSFER_SENDER_POLICY) | `0xd116fc21` | Policy slot consulted against `from` on every transfer (including `transferFrom`). |
+| [`TRANSFER_RECEIVER_POLICY`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/TRANSFER_RECEIVER_POLICY) | `0x210f521b` | Policy slot consulted against `to` on every transfer. |
+| [`TRANSFER_EXECUTOR_POLICY`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/TRANSFER_EXECUTOR_POLICY) | `0x724e9c53` | Policy slot consulted against `msg.sender` on `transferFrom` when distinct from `from`. |
+| [`MINT_RECEIVER_POLICY`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/MINT_RECEIVER_POLICY) | `0x6e5b013d` | Policy slot consulted against `to` on every mint. |
+| [`SEIZE_HOLDER_POLICY`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/SEIZE_HOLDER_POLICY) | `0xb279d311` | Policy slot consulted against `from` by `seizeWithMemo`. |
+| [`name`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/name) | `0x06fdde03` | Token name. Set at creation, mutable via `updateName`. |
+| [`symbol`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/symbol) | `0x95d89b41` | Token symbol. Set at creation, mutable via `updateSymbol`. |
+| [`decimals`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/decimals) | `0x313ce567` | Number of decimal places. Immutable per token variant. |
+| [`totalSupply`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/totalSupply) | `0x18160ddd` | Total token supply currently in circulation. |
+| [`balanceOf`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/balanceOf) | `0x70a08231` | Balance of `account`. |
+| [`allowance`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/allowance) | `0xdd62ed3e` | Allowance granted by `owner` to `spender`. |
+| [`transfer`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/transfer) | `0xa9059cbb` | Transfers `amount` from `msg.sender` to `to`. Emits `Transfer`. |
+| [`transferFrom`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/transferFrom) | `0x23b872dd` | Transfers `amount` from `from` to `to` using `msg.sender`'s allowance. Emits `Transfer`. |
+| [`approve`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/approve) | `0x095ea7b3` | Sets `spender`'s allowance to `amount`. Not gated by any policy or by pause. Emits `Approval`. |
+| [`updateName`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/updateName) | `0x84da92a7` | Updates the token's `name`. Emits `NameUpdated` followed by `EIP712DomainChanged`. |
+| [`updateSymbol`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/updateSymbol) | `0x537f5312` | Updates the token's `symbol`. Emits `SymbolUpdated`. |
+| [`transferWithMemo`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/transferWithMemo) | `0x95777d59` | Same as `transfer`, plus emits `Memo` immediately after the standard `Transfer` event. |
+| [`transferFromWithMemo`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/transferFromWithMemo) | `0x929c2539` | Same as `transferFrom`, plus emits `Memo` immediately after the standard `Transfer` event. |
+| [`mint`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/mint) | `0x40c10f19` | Mints `amount` to `to`. Emits `Transfer(address(0), to, amount)`. |
+| [`mintWithMemo`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/mintWithMemo) | `0xe44f0b12` | Same as `mint`, plus emits `Memo` immediately after the standard `Transfer` event. |
+| [`burn`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/burn) | `0x42966c68` | Burns `amount` from the caller's own balance. Not subject to any policy. |
+| [`burnWithMemo`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/burnWithMemo) | `0x38f23b0b` | Same as `burn`, plus emits `Memo` immediately after the standard `Transfer` event. |
+| [`seizeWithMemo`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/seizeWithMemo) | `0xf916d81b` | Seizes `amount` of `from`'s balance and reassigns it to `to` in a single admin operation. |
+| [`hasRole`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/hasRole) | `0x91d14854` | Whether `account` is a member of `role`. User-defined roles are supported and have no |
+| [`getRoleAdmin`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/getRoleAdmin) | `0x248a9ca3` | The role required to grant or revoke `role`. Defaults to `DEFAULT_ADMIN_ROLE` if not |
+| [`grantRole`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/grantRole) | `0x2f2ff15d` | Grants `role` to `account`. Emits `RoleGranted`. |
+| [`revokeRole`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/revokeRole) | `0xd547741f` | Revokes `role` from `account`. Emits `RoleRevoked`. |
+| [`renounceRole`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/renounceRole) | `0x36568abe` | Caller renounces `role` for themselves. Emits `RoleRevoked`. |
+| [`renounceLastAdmin`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/renounceLastAdmin) | `0x6f79e3d7` | Permanently transitions the token to a zero-admin state. Revokes `DEFAULT_ADMIN_ROLE` |
+| [`setRoleAdmin`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/setRoleAdmin) | `0x1e4e0091` | Sets the admin role for `role`. Emits `RoleAdminChanged`. |
+| [`pausedFeatures`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/pausedFeatures) | `0xde9997e3` | The `PausableFeature`s currently paused on this token. Order is implementation-defined; |
+| [`isPaused`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/isPaused) | `0x165c44bc` | Whether `feature` is currently paused. O(1). |
+| [`pause`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/pause) | `0x9f98bd2d` | Pauses each of `features`. Additive: features already paused remain paused; duplicates |
+| [`unpause`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/unpause) | `0xb61b2ebc` | Unpauses each of `features`. Features not listed are unaffected; duplicates are idempotent. |
+| [`policyId`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/policyId) | `0xdb3de624` | The current policy ID configured for `policyScope`. Returns `0` (always-allow built-in) |
+| [`updatePolicy`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/updatePolicy) | `0xadf9c4ea` | Updates the policy ID assigned to `policyScope`. Takes effect immediately for the next |
+| [`supplyCap`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/supplyCap) | `0x8f770ad0` | The maximum total supply enforced on `mint`. Capped at `type(uint128).max`, which |
+| [`updateSupplyCap`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/updateSupplyCap) | `0xe5a97f07` | Sets a new supply cap. May be raised or lowered freely, but never below current |
+| [`DOMAIN_SEPARATOR`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/DOMAIN_SEPARATOR) | `0x3644e515` | The current EIP-712 domain separator for this token. Recomputed on each call so it |
+| [`nonces`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/nonces) | `0x7ecebe00` | The current EIP-2612 permit nonce for `owner`. Incremented by 1 on each successful `permit`. |
+| [`permit`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/permit) | `0xd505accf` | EIP-2612 permit. Recovers `owner` via ECDSA from `(v, r, s)`. EOA signatures only; |
+| [`eip712Domain`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/eip712Domain) | `0x84b0196e` | ERC-5267 EIP-712 domain introspection. |
+| [`contractURI`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/contractURI) | `0xe8a3d485` | Off-chain URI pointing at contract-level metadata for this token, per ERC-7572. |
+| [`updateContractURI`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/updateContractURI) | `0x7e5b1e24` | Updates `contractURI`. Emits the parameterless `ContractURIUpdated` event per ERC-7572; |
+
+## Events
+
+| Event | Topic0 | Summary |
+|---|---|---|
+| `Transfer` | `0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef` | ERC-20 transfer event. Emitted on every successful transfer (including memo'd variants), |
+| `Approval` | `0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925` | ERC-20 approval event. Emitted by `approve` and `permit`. |
+| `Memo` | `0x6989f5818dcfd11f8cd53b27c94cec33dae1589735f03e639cba54553a1825e8` | Emitted by `transferWithMemo`, `transferFromWithMemo`, `mintWithMemo`, and `burnWithMemo` |
+| `BurnedBlocked` | `0x0b552e96653fd6842da37c477005d3b5c08a8c7d3631b1f43787b2dc9a1006a3` | Emitted by the deprecated `burnBlocked` in addition to `Transfer(from, address(0), amount)`. |
+| `Seized` | `0xa9aec5d8b86e2fa2fd6ac3af62f2622e3dfdab1967d4cbbb56a5df7d74cb887c` | Emitted by `seizeWithMemo` in addition to `Transfer(from, to, amount)` (and the |
+| `RoleGranted` | `0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d` | Emitted when `account` is granted `role`. `sender` is the originating caller. |
+| `RoleRevoked` | `0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b` | Emitted when `role` is revoked from `account`. `sender` is the originating caller |
+| `RoleAdminChanged` | `0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff` | Emitted by `setRoleAdmin` when the admin role for `role` changes. |
+| `LastAdminRenounced` | `0xe8d3a9872e7ca325571ff1e4c51ddd69090a0345240cc605ccde365ec867cc67` | Emitted by `renounceLastAdmin` in addition to the standard |
+| `Paused` | `0x43e072977b8112813d7c2aa0b63d3c121c1fe3e714e6d2eacb5735fe4027e976` | Emitted by `pause`. `features` is the argument to the call (not the resulting paused state). |
+| `Unpaused` | `0xdc6281474ea3dea2a856e225c7ba3edf427de9164495817c4d49a595e683fed4` | Emitted by `unpause`. `features` is the argument to the call (not the resulting paused state). |
+| `PolicyUpdated` | `0x8b4790f7ff717fc8f60f07ae099e47ef318dc04b37ae98056b50a22b79056626` | Emitted by `updatePolicy` when a token's policy slot is changed. Initial slot assignment at |
+| `SupplyCapUpdated` | `0x6d14f44808ce024f263432bc38d019a9951fbe674e9898b54844dbc8dc09c23a` | Emitted by `updateSupplyCap`. |
+| `ContractURIUpdated` | `0xa5d4097edda6d87cb9329af83fb3712ef77eeb13738ffe43cc35a4ce305ad962` | Emitted by `updateContractURI`. Per ERC-7572, parameterless: integrators re-fetch `contractURI()`. |
+| `NameUpdated` | `0x74321da206c1b9fa34367f7ece59ca49371dcd13820b9a5c3767ae1ecceed51a` | Emitted by `updateName`. Carries the new name string. |
+| `SymbolUpdated` | `0x64e8b5c6dcea43dd79766bb3b8af7c45968d12b68c960cf2da23856f34d598d4` | Emitted by `updateSymbol`. Carries the new symbol string. |
+| `EIP712DomainChanged` | `0x0a6387c9ea3628b88a633bb4f3b151770f70085117a15f9bf3787cda53f13d31` | ERC-5267 domain-change signal. Emitted exactly once per successful `updateName` call, |
+
+## Errors
+
+| Error | Selector | Summary |
+|---|---|---|
+| `NonPayable` | `0x6fb1b0e9` | ETH was attached to a call targeting a nonpayable token selector. |
+| `AccessControlUnauthorizedAccount` | `0xe2517d3f` | `account` does not hold `neededRole`. |
+| `Unauthorized` | `0x82b42900` | Caller failed a positional authorization check that is not expressible as "missing role X". |
+| `ContractPaused` | `0xf9df5ac9` | The `PausableFeature` covering this operation is currently paused. |
+| `InsufficientAllowance` | `0x192b9e4e` | `spender`'s allowance is less than `needed` for the requested `transferFrom`. |
+| `InsufficientBalance` | `0xdb42144d` | `sender`'s balance is less than `needed` for the requested transfer or burn. |
+| `InvalidSender` | `0x4c14f64c` | The transfer's source address is invalid (typically `address(0)`). |
+| `InvalidReceiver` | `0x9cfea583` | The transfer's destination address is invalid (typically `address(0)`). |
+| `InvalidApprover` | `0x8bc146c4` | The approval's `owner` address is invalid (typically `address(0)`). |
+| `InvalidSpender` | `0x4e15efda` | The approval's `spender` address is invalid (typically `address(0)`). |
+| `InvalidAmount` | `0x2c5211c6` | An amount argument was zero where a non-zero value is required. Not used for ERC-20 amount arguments. |
+| `EmptyFeatureSet` | `0x4861ff45` | An empty array was passed to a function that requires at least one element. |
+| `InvalidSupplyCap` | `0x0a3780ce` | The proposed supply cap is outside the permitted range: below the current |
+| `SupplyCapExceeded` | `0x4b344b11` | The mint would push `totalSupply` past the configured cap. |
+| `PolicyForbids` | `0xa43fec12` | A policy slot denied the operation. |
+| `PolicyNotFound` | `0xcccad523` | The provided policy ID does not exist in the policy registry. |
+| `UnsupportedPolicyType` | `0xcdd98a4a` | `policyScope` is not a slot this token (or its variant) supports. |
+| `AccountNotSeizable` | `0x91dbbc8d` | `seizeWithMemo` was called against a `from` that is currently authorized under |
+| `AccountNotBlocked` | `0x64a5cb46` | The deprecated `burnBlocked` was called against a `from` that is currently authorized under |
+| `ExpiredSignature` | `0xbd2a913c` | An EIP-2612 `permit` was submitted with a `deadline` strictly less than `block.timestamp`. |
+| `InvalidSigner` | `0x7ba5ffb5` | ECDSA recovery on an EIP-2612 `permit` returned `signer`, which does not match the claimed `owner`. |
+| `LastAdminCannotRenounce` | `0x361513e7` | `renounceRole(DEFAULT_ADMIN_ROLE, ...)` was called by the sole remaining admin. |
+| `NotSoleAdmin` | `0x2a98e73b` | `renounceLastAdmin()` was called when other accounts also hold `DEFAULT_ADMIN_ROLE`. |
+| `AccessControlBadConfirmation` | `0x6697b232` | The `callerConfirmation` argument to `renounceRole` was not `msg.sender`. |
+
+
+
+
+
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/BURN_BLOCKED_ROLE.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/BURN_BLOCKED_ROLE.mdx
new file mode 100644
index 000000000..e770aa144
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/BURN_BLOCKED_ROLE.mdx
@@ -0,0 +1,43 @@
+---
+title: "IB20.BURN_BLOCKED_ROLE"
+description: "Generated B20 reference for BURN_BLOCKED_ROLE()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function BURN_BLOCKED_ROLE() external view returns (bytes32);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x32ad9be8` |
+| Canonical signature | `BURN_BLOCKED_ROLE()` |
+
+## Description
+
+Required to call the deprecated `burnBlocked` (no longer part of this interface; retained for
+the back-compat impl).
+Return: Role constant.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).BURN_BLOCKED_ROLE();
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/BURN_ROLE.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/BURN_ROLE.mdx
new file mode 100644
index 000000000..d1c844a38
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/BURN_ROLE.mdx
@@ -0,0 +1,42 @@
+---
+title: "IB20.BURN_ROLE"
+description: "Generated B20 reference for BURN_ROLE()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function BURN_ROLE() external view returns (bytes32);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xb930908f` |
+| Canonical signature | `BURN_ROLE()` |
+
+## Description
+
+Required to call `burn` and `burnWithMemo`.
+Return: Role constant.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).BURN_ROLE();
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/DEFAULT_ADMIN_ROLE.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/DEFAULT_ADMIN_ROLE.mdx
new file mode 100644
index 000000000..ee6ea7ca2
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/DEFAULT_ADMIN_ROLE.mdx
@@ -0,0 +1,43 @@
+---
+title: "IB20.DEFAULT_ADMIN_ROLE"
+description: "Generated B20 reference for DEFAULT_ADMIN_ROLE()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function DEFAULT_ADMIN_ROLE() external view returns (bytes32);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xa217fddf` |
+| Canonical signature | `DEFAULT_ADMIN_ROLE()` |
+
+## Description
+
+The default top-level admin role (`bytes32(0)`). Required to call `grantRole`, `revokeRole`,
+`setRoleAdmin`, `updatePolicy`, and `updateSupplyCap`.
+Return: Role constant.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).DEFAULT_ADMIN_ROLE();
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/DOMAIN_SEPARATOR.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/DOMAIN_SEPARATOR.mdx
new file mode 100644
index 000000000..79c2aac33
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/DOMAIN_SEPARATOR.mdx
@@ -0,0 +1,43 @@
+---
+title: "IB20.DOMAIN_SEPARATOR"
+description: "Generated B20 reference for DOMAIN_SEPARATOR()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function DOMAIN_SEPARATOR() external view returns (bytes32);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x3644e515` |
+| Canonical signature | `DOMAIN_SEPARATOR()` |
+
+## Description
+
+The current EIP-712 domain separator for this token. Recomputed on each call so it
+remains correct after `updateName` or a chain fork that changes `block.chainid`.
+Return: Current domain separator.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).DOMAIN_SEPARATOR();
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/METADATA_ROLE.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/METADATA_ROLE.mdx
new file mode 100644
index 000000000..08343ae61
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/METADATA_ROLE.mdx
@@ -0,0 +1,42 @@
+---
+title: "IB20.METADATA_ROLE"
+description: "Generated B20 reference for METADATA_ROLE()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function METADATA_ROLE() external view returns (bytes32);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x38841782` |
+| Canonical signature | `METADATA_ROLE()` |
+
+## Description
+
+Required to call `updateName`, `updateSymbol`, and `updateContractURI`.
+Return: Role constant.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).METADATA_ROLE();
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/MINT_RECEIVER_POLICY.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/MINT_RECEIVER_POLICY.mdx
new file mode 100644
index 000000000..a15e2e8ec
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/MINT_RECEIVER_POLICY.mdx
@@ -0,0 +1,45 @@
+---
+title: "IB20.MINT_RECEIVER_POLICY"
+description: "Generated B20 reference for MINT_RECEIVER_POLICY()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function MINT_RECEIVER_POLICY() external view returns (bytes32);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x6e5b013d` |
+| Canonical signature | `MINT_RECEIVER_POLICY()` |
+
+## Description
+
+Policy slot consulted against `to` on every mint.
+Dev: Unlike the transfer-side policies, this slot is ALWAYS enforced — including for
+factory-originated mints during the creation (bootstrap) window — so new supply is never
+issued to a policy-denied recipient even at creation. See `IB20Factory.createB20`.
+Return: Policy scope constant.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).MINT_RECEIVER_POLICY();
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/MINT_ROLE.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/MINT_ROLE.mdx
new file mode 100644
index 000000000..6943c0271
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/MINT_ROLE.mdx
@@ -0,0 +1,42 @@
+---
+title: "IB20.MINT_ROLE"
+description: "Generated B20 reference for MINT_ROLE()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function MINT_ROLE() external view returns (bytes32);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xe9a9c850` |
+| Canonical signature | `MINT_ROLE()` |
+
+## Description
+
+Required to call `mint` and `mintWithMemo`.
+Return: Role constant.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).MINT_ROLE();
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/PAUSE_ROLE.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/PAUSE_ROLE.mdx
new file mode 100644
index 000000000..20f5990d2
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/PAUSE_ROLE.mdx
@@ -0,0 +1,42 @@
+---
+title: "IB20.PAUSE_ROLE"
+description: "Generated B20 reference for PAUSE_ROLE()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function PAUSE_ROLE() external view returns (bytes32);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x389ed267` |
+| Canonical signature | `PAUSE_ROLE()` |
+
+## Description
+
+Required to call `pause`.
+Return: Role constant.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).PAUSE_ROLE();
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/SEIZE_HOLDER_POLICY.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/SEIZE_HOLDER_POLICY.mdx
new file mode 100644
index 000000000..907ee86fa
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/SEIZE_HOLDER_POLICY.mdx
@@ -0,0 +1,44 @@
+---
+title: "IB20.SEIZE_HOLDER_POLICY"
+description: "Generated B20 reference for SEIZE_HOLDER_POLICY()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function SEIZE_HOLDER_POLICY() external view returns (bytes32);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xb279d311` |
+| Canonical signature | `SEIZE_HOLDER_POLICY()` |
+
+## Description
+
+Policy slot consulted against `from` by `seizeWithMemo`.
+Dev: A `from` is seizable only when it is NOT authorized by this policy. An unset slot reads as `0`
+(always-allow), so no account is seizable until an issuer configures the slot.
+Return: Policy scope constant.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).SEIZE_HOLDER_POLICY();
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/SEIZE_ROLE.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/SEIZE_ROLE.mdx
new file mode 100644
index 000000000..66174524c
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/SEIZE_ROLE.mdx
@@ -0,0 +1,42 @@
+---
+title: "IB20.SEIZE_ROLE"
+description: "Generated B20 reference for SEIZE_ROLE()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function SEIZE_ROLE() external view returns (bytes32);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x3c7e9ba5` |
+| Canonical signature | `SEIZE_ROLE()` |
+
+## Description
+
+Required to call `seizeWithMemo`.
+Return: Role constant.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).SEIZE_ROLE();
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/TRANSFER_EXECUTOR_POLICY.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/TRANSFER_EXECUTOR_POLICY.mdx
new file mode 100644
index 000000000..07e16384e
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/TRANSFER_EXECUTOR_POLICY.mdx
@@ -0,0 +1,45 @@
+---
+title: "IB20.TRANSFER_EXECUTOR_POLICY"
+description: "Generated B20 reference for TRANSFER_EXECUTOR_POLICY()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function TRANSFER_EXECUTOR_POLICY() external view returns (bytes32);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x724e9c53` |
+| Canonical signature | `TRANSFER_EXECUTOR_POLICY()` |
+
+## Description
+
+Policy slot consulted against `msg.sender` on `transferFrom` when distinct from `from`.
+Not consulted on `transfer`.
+Dev: Bypassed for factory-originated calls during the creation (bootstrap) window; see
+`IB20Factory.createB20`.
+Return: Policy scope constant.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).TRANSFER_EXECUTOR_POLICY();
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/TRANSFER_RECEIVER_POLICY.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/TRANSFER_RECEIVER_POLICY.mdx
new file mode 100644
index 000000000..f1d559430
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/TRANSFER_RECEIVER_POLICY.mdx
@@ -0,0 +1,44 @@
+---
+title: "IB20.TRANSFER_RECEIVER_POLICY"
+description: "Generated B20 reference for TRANSFER_RECEIVER_POLICY()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function TRANSFER_RECEIVER_POLICY() external view returns (bytes32);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x210f521b` |
+| Canonical signature | `TRANSFER_RECEIVER_POLICY()` |
+
+## Description
+
+Policy slot consulted against `to` on every transfer.
+Dev: Bypassed for factory-originated calls during the creation (bootstrap) window; see
+`IB20Factory.createB20`.
+Return: Policy scope constant.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).TRANSFER_RECEIVER_POLICY();
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/TRANSFER_SENDER_POLICY.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/TRANSFER_SENDER_POLICY.mdx
new file mode 100644
index 000000000..c9d8c2df4
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/TRANSFER_SENDER_POLICY.mdx
@@ -0,0 +1,44 @@
+---
+title: "IB20.TRANSFER_SENDER_POLICY"
+description: "Generated B20 reference for TRANSFER_SENDER_POLICY()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function TRANSFER_SENDER_POLICY() external view returns (bytes32);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xd116fc21` |
+| Canonical signature | `TRANSFER_SENDER_POLICY()` |
+
+## Description
+
+Policy slot consulted against `from` on every transfer (including `transferFrom`).
+Dev: Bypassed for factory-originated calls during the creation (bootstrap) window; see
+`IB20Factory.createB20`.
+Return: Policy scope constant.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).TRANSFER_SENDER_POLICY();
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/UNPAUSE_ROLE.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/UNPAUSE_ROLE.mdx
new file mode 100644
index 000000000..2bbd4fabb
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/UNPAUSE_ROLE.mdx
@@ -0,0 +1,42 @@
+---
+title: "IB20.UNPAUSE_ROLE"
+description: "Generated B20 reference for UNPAUSE_ROLE()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function UNPAUSE_ROLE() external view returns (bytes32);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x309756fb` |
+| Canonical signature | `UNPAUSE_ROLE()` |
+
+## Description
+
+Required to call `unpause`.
+Return: Role constant.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).UNPAUSE_ROLE();
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/allowance.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/allowance.mdx
new file mode 100644
index 000000000..1626fb545
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/allowance.mdx
@@ -0,0 +1,44 @@
+---
+title: "IB20.allowance"
+description: "Generated B20 reference for allowance(address,address)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function allowance(address owner, address spender) external view returns (uint256);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xdd62ed3e` |
+| Canonical signature | `allowance(address,address)` |
+
+## Description
+
+Allowance granted by `owner` to `spender`.
+Param: owner Allowance owner.
+Param: spender Allowance spender.
+Return: Current allowance.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).allowance(arg0, arg1);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/approve.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/approve.mdx
new file mode 100644
index 000000000..9af3a02e3
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/approve.mdx
@@ -0,0 +1,46 @@
+---
+title: "IB20.approve"
+description: "Generated B20 reference for approve(address,uint256)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function approve(address spender, uint256 amount) external returns (bool);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x095ea7b3` |
+| Canonical signature | `approve(address,uint256)` |
+
+## Description
+
+Sets `spender`'s allowance to `amount`. Not gated by any policy or by pause. Emits `Approval`.
+Dev: Reverts with `InvalidApprover` when `msg.sender == address(0)`.
+Dev: Reverts with `InvalidSpender` when `spender == address(0)`.
+Param: spender Account being granted the allowance.
+Param: amount Allowance amount.
+Return: Always `true` on success.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).approve(arg0, arg1);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/balanceOf.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/balanceOf.mdx
new file mode 100644
index 000000000..0f831066f
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/balanceOf.mdx
@@ -0,0 +1,43 @@
+---
+title: "IB20.balanceOf"
+description: "Generated B20 reference for balanceOf(address)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function balanceOf(address account) external view returns (uint256);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x70a08231` |
+| Canonical signature | `balanceOf(address)` |
+
+## Description
+
+Balance of `account`.
+Param: account Account whose balance is being queried.
+Return: Current balance.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).balanceOf(arg0);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/burn.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/burn.mdx
new file mode 100644
index 000000000..8a2e124c1
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/burn.mdx
@@ -0,0 +1,46 @@
+---
+title: "IB20.burn"
+description: "Generated B20 reference for burn(uint256)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/token-lifecycle)
+
+## Signature
+
+```solidity
+function burn(uint256 amount) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x42966c68` |
+| Canonical signature | `burn(uint256)` |
+
+## Description
+
+Burns `amount` from the caller's own balance. Not subject to any policy.
+Emits `Transfer(caller, address(0), amount)`.
+Dev: Reverts with `ContractPaused(BURN)` when `BURN` is paused.
+Dev: Reverts with `AccessControlUnauthorizedAccount` when the caller does not hold `BURN_ROLE`.
+Dev: Reverts with `InsufficientBalance` when the caller's balance is below `amount`.
+Param: amount Amount to burn.
+
+## Access control
+
+`BURN_ROLE` gates self-burn calls.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).burn(arg0);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/burnWithMemo.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/burnWithMemo.mdx
new file mode 100644
index 000000000..adfeecfaf
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/burnWithMemo.mdx
@@ -0,0 +1,44 @@
+---
+title: "IB20.burnWithMemo"
+description: "Generated B20 reference for burnWithMemo(uint256,bytes32)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/token-lifecycle)
+
+## Signature
+
+```solidity
+function burnWithMemo(uint256 amount, bytes32 memo) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x38f23b0b` |
+| Canonical signature | `burnWithMemo(uint256,bytes32)` |
+
+## Description
+
+Same as `burn`, plus emits `Memo` immediately after the standard `Transfer` event.
+A memo of `bytes32(0)` is permitted.
+Param: amount Amount to burn.
+Param: memo Off-chain memo payload.
+
+## Access control
+
+`BURN_ROLE` gates self-burn calls.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).burnWithMemo(arg0, arg1);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/contractURI.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/contractURI.mdx
new file mode 100644
index 000000000..a8de4ce0c
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/contractURI.mdx
@@ -0,0 +1,42 @@
+---
+title: "IB20.contractURI"
+description: "Generated B20 reference for contractURI()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function contractURI() external view returns (string memory);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xe8a3d485` |
+| Canonical signature | `contractURI()` |
+
+## Description
+
+Off-chain URI pointing at contract-level metadata for this token, per ERC-7572.
+Return: Current contract URI.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).contractURI();
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/decimals.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/decimals.mdx
new file mode 100644
index 000000000..498b048f5
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/decimals.mdx
@@ -0,0 +1,42 @@
+---
+title: "IB20.decimals"
+description: "Generated B20 reference for decimals()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function decimals() external view returns (uint8);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x313ce567` |
+| Canonical signature | `decimals()` |
+
+## Description
+
+Number of decimal places. Immutable per token variant.
+Return: Number of decimal places.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).decimals();
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/eip712Domain.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/eip712Domain.mdx
new file mode 100644
index 000000000..f303be13d
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/eip712Domain.mdx
@@ -0,0 +1,48 @@
+---
+title: "IB20.eip712Domain"
+description: "Generated B20 reference for eip712Domain()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function eip712Domain() external view returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions );
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x84b0196e` |
+| Canonical signature | `eip712Domain()` |
+
+## Description
+
+ERC-5267 EIP-712 domain introspection.
+Return: fields Bitmap of populated domain fields (`0x0f`: `name`, `version`, `chainId`, `verifyingContract`).
+Return: name Live `name()` value.
+Return: version Constant `"1"`.
+Return: chainId Current `block.chainid`.
+Return: verifyingContract This token's address.
+Return: salt Unused (zero).
+Return: extensions Empty.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).eip712Domain();
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/getRoleAdmin.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/getRoleAdmin.mdx
new file mode 100644
index 000000000..d92413b4e
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/getRoleAdmin.mdx
@@ -0,0 +1,44 @@
+---
+title: "IB20.getRoleAdmin"
+description: "Generated B20 reference for getRoleAdmin(bytes32)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/roles-and-access-control)
+
+## Signature
+
+```solidity
+function getRoleAdmin(bytes32 role) external view returns (bytes32);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x248a9ca3` |
+| Canonical signature | `getRoleAdmin(bytes32)` |
+
+## Description
+
+The role required to grant or revoke `role`. Defaults to `DEFAULT_ADMIN_ROLE` if not
+explicitly set via `setRoleAdmin`.
+Param: role Role whose admin is being queried.
+Return: Admin role.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).getRoleAdmin(arg0);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/grantRole.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/grantRole.mdx
new file mode 100644
index 000000000..9a850c82b
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/grantRole.mdx
@@ -0,0 +1,45 @@
+---
+title: "IB20.grantRole"
+description: "Generated B20 reference for grantRole(bytes32,address)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/roles-and-access-control)
+
+## Signature
+
+```solidity
+function grantRole(bytes32 role, address account) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x2f2ff15d` |
+| Canonical signature | `grantRole(bytes32,address)` |
+
+## Description
+
+Grants `role` to `account`. Emits `RoleGranted`.
+Dev: Reverts with `AccessControlUnauthorizedAccount` when the caller does not hold the admin role for `role`,
+or when the token has been transitioned to admin-less via `renounceLastAdmin` (admin-resurrection guard).
+Param: role Role to grant.
+Param: account Recipient.
+
+## Access control
+
+Uses the B20 access-control role graph. Factory initCalls bypass role gates during creation.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).grantRole(arg0, arg1);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/hasRole.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/hasRole.mdx
new file mode 100644
index 000000000..33b0adc02
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/hasRole.mdx
@@ -0,0 +1,45 @@
+---
+title: "IB20.hasRole"
+description: "Generated B20 reference for hasRole(bytes32,address)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/roles-and-access-control)
+
+## Signature
+
+```solidity
+function hasRole(bytes32 role, address account) external view returns (bool);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x91d14854` |
+| Canonical signature | `hasRole(bytes32,address)` |
+
+## Description
+
+Whether `account` is a member of `role`. User-defined roles are supported and have no
+built-in effect on the token's own functions.
+Param: role Role to check.
+Param: account Account to check.
+Return: Whether `account` holds `role`.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).hasRole(arg0, arg1);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/isPaused.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/isPaused.mdx
new file mode 100644
index 000000000..4935b8ef7
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/isPaused.mdx
@@ -0,0 +1,43 @@
+---
+title: "IB20.isPaused"
+description: "Generated B20 reference for isPaused(PausableFeature)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function isPaused(PausableFeature feature) external view returns (bool);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x165c44bc` |
+| Canonical signature | `isPaused(PausableFeature)` |
+
+## Description
+
+Whether `feature` is currently paused. O(1).
+Param: feature Feature to query.
+Return: Whether `feature` is paused.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).isPaused(arg0);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/mint.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/mint.mdx
new file mode 100644
index 000000000..a4c59195b
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/mint.mdx
@@ -0,0 +1,48 @@
+---
+title: "IB20.mint"
+description: "Generated B20 reference for mint(address,uint256)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/token-lifecycle)
+
+## Signature
+
+```solidity
+function mint(address to, uint256 amount) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x40c10f19` |
+| Canonical signature | `mint(address,uint256)` |
+
+## Description
+
+Mints `amount` to `to`. Emits `Transfer(address(0), to, amount)`.
+Dev: Reverts with `ContractPaused(MINT)` when `MINT` is paused.
+Dev: Reverts with `AccessControlUnauthorizedAccount` when the caller does not hold `MINT_ROLE`.
+Dev: Reverts with `InvalidReceiver` when `to == address(0)`.
+Dev: Reverts with `PolicyForbids(MINT_RECEIVER_POLICY, ...)` when `to` is not authorized.
+Dev: Reverts with `SupplyCapExceeded` when `totalSupply + amount > supplyCap`.
+Param: to Mint recipient.
+Param: amount Amount to mint.
+
+## Access control
+
+`MINT_ROLE` gates state-changing mint calls.
+
+## Policy interaction
+
+Checks `MINT_RECEIVER_POLICY`, including during factory initCalls.
+
+## Example
+
+```solidity
+IB20(target).mint(arg0, arg1);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/mintWithMemo.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/mintWithMemo.mdx
new file mode 100644
index 000000000..84bd234e6
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/mintWithMemo.mdx
@@ -0,0 +1,45 @@
+---
+title: "IB20.mintWithMemo"
+description: "Generated B20 reference for mintWithMemo(address,uint256,bytes32)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/token-lifecycle)
+
+## Signature
+
+```solidity
+function mintWithMemo(address to, uint256 amount, bytes32 memo) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xe44f0b12` |
+| Canonical signature | `mintWithMemo(address,uint256,bytes32)` |
+
+## Description
+
+Same as `mint`, plus emits `Memo` immediately after the standard `Transfer` event.
+A memo of `bytes32(0)` is permitted.
+Param: to Mint recipient.
+Param: amount Amount to mint.
+Param: memo Off-chain memo payload.
+
+## Access control
+
+`MINT_ROLE` gates state-changing mint calls.
+
+## Policy interaction
+
+Checks `MINT_RECEIVER_POLICY`, including during factory initCalls.
+
+## Example
+
+```solidity
+IB20(target).mintWithMemo(arg0, arg1, arg2);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/name.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/name.mdx
new file mode 100644
index 000000000..7e86c70ad
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/name.mdx
@@ -0,0 +1,42 @@
+---
+title: "IB20.name"
+description: "Generated B20 reference for name()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function name() external view returns (string memory);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x06fdde03` |
+| Canonical signature | `name()` |
+
+## Description
+
+Token name. Set at creation, mutable via `updateName`.
+Return: Current token name.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).name();
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/nonces.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/nonces.mdx
new file mode 100644
index 000000000..760cfd94a
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/nonces.mdx
@@ -0,0 +1,43 @@
+---
+title: "IB20.nonces"
+description: "Generated B20 reference for nonces(address)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function nonces(address owner) external view returns (uint256);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x7ecebe00` |
+| Canonical signature | `nonces(address)` |
+
+## Description
+
+The current EIP-2612 permit nonce for `owner`. Incremented by 1 on each successful `permit`.
+Param: owner Account whose nonce is being queried.
+Return: Current nonce.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).nonces(arg0);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/pause.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/pause.mdx
new file mode 100644
index 000000000..5f8a4584c
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/pause.mdx
@@ -0,0 +1,45 @@
+---
+title: "IB20.pause"
+description: "Generated B20 reference for pause(PausableFeature[])."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/token-lifecycle)
+
+## Signature
+
+```solidity
+function pause(PausableFeature[] calldata features) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x9f98bd2d` |
+| Canonical signature | `pause(PausableFeature[])` |
+
+## Description
+
+Pauses each of `features`. Additive: features already paused remain paused; duplicates
+within the call are idempotent. Emits `Paused`.
+Dev: Reverts with `AccessControlUnauthorizedAccount` when the caller does not hold `PAUSE_ROLE`.
+Dev: Reverts with `EmptyFeatureSet` when `features.length == 0`.
+Param: features Features to pause.
+
+## Access control
+
+`PAUSE_ROLE` gates this call.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).pause(arg0);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/pausedFeatures.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/pausedFeatures.mdx
new file mode 100644
index 000000000..bd704dc0b
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/pausedFeatures.mdx
@@ -0,0 +1,43 @@
+---
+title: "IB20.pausedFeatures"
+description: "Generated B20 reference for pausedFeatures()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/token-lifecycle)
+
+## Signature
+
+```solidity
+function pausedFeatures() external view returns (PausableFeature[] memory);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xde9997e3` |
+| Canonical signature | `pausedFeatures()` |
+
+## Description
+
+The `PausableFeature`s currently paused on this token. Order is implementation-defined;
+callers should treat the result as a set.
+Return: Currently-paused features.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).pausedFeatures();
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/permit.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/permit.mdx
new file mode 100644
index 000000000..de0d4702a
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/permit.mdx
@@ -0,0 +1,52 @@
+---
+title: "IB20.permit"
+description: "Generated B20 reference for permit(address,address,uint256,uint256,uint8,bytes32,bytes32)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xd505accf` |
+| Canonical signature | `permit(address,address,uint256,uint256,uint8,bytes32,bytes32)` |
+
+## Description
+
+EIP-2612 permit. Recovers `owner` via ECDSA from `(v, r, s)`. EOA signatures only;
+ERC-1271 contract signatures are NOT supported. Emits `Approval`.
+Dev: Reverts with `ExpiredSignature` when `block.timestamp > deadline`.
+Dev: Reverts with `InvalidSigner` when ECDSA recovery does not yield `owner`.
+Dev: Reverts with `InvalidSpender` when `spender == address(0)`.
+Param: owner Token holder granting the allowance.
+Param: spender Account being granted the allowance.
+Param: value Allowance amount.
+Param: deadline Unix timestamp after which the signature is invalid.
+Param: v ECDSA recovery byte.
+Param: r ECDSA signature r component.
+Param: s ECDSA signature s component.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).permit(arg0, arg1, arg2, arg3, arg4, arg5, arg6);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/policyId.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/policyId.mdx
new file mode 100644
index 000000000..1767844d4
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/policyId.mdx
@@ -0,0 +1,45 @@
+---
+title: "IB20.policyId"
+description: "Generated B20 reference for policyId(bytes32)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/policies-and-scopes)
+
+## Signature
+
+```solidity
+function policyId(bytes32 policyScope) external view returns (uint64);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xdb3de624` |
+| Canonical signature | `policyId(bytes32)` |
+
+## Description
+
+The current policy ID configured for `policyScope`. Returns `0` (always-allow built-in)
+for any slot that has never been assigned.
+Dev: Reverts with `UnsupportedPolicyType` when `policyScope` is not recognized by this token.
+Param: policyScope Policy slot scope.
+Return: Configured policy ID.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+Reads or writes a token policy-scope pointer into the PolicyRegistry.
+
+## Example
+
+```solidity
+uint64 id = IB20(token).policyId(B20Constants.MINT_RECEIVER_POLICY);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/renounceLastAdmin.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/renounceLastAdmin.mdx
new file mode 100644
index 000000000..df5a79848
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/renounceLastAdmin.mdx
@@ -0,0 +1,45 @@
+---
+title: "IB20.renounceLastAdmin"
+description: "Generated B20 reference for renounceLastAdmin()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/roles-and-access-control)
+
+## Signature
+
+```solidity
+function renounceLastAdmin() external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x6f79e3d7` |
+| Canonical signature | `renounceLastAdmin()` |
+
+## Description
+
+Permanently transitions the token to a zero-admin state. Revokes `DEFAULT_ADMIN_ROLE`
+from `msg.sender`. Emits `RoleRevoked(DEFAULT_ADMIN_ROLE, msg.sender, msg.sender)` and
+`LastAdminRenounced(msg.sender)`.
+Dev: Reverts with `AccessControlUnauthorizedAccount` when `msg.sender` does not hold `DEFAULT_ADMIN_ROLE`.
+Dev: Reverts with `NotSoleAdmin` when other accounts also hold `DEFAULT_ADMIN_ROLE`.
+
+## Access control
+
+Uses the B20 access-control role graph. Factory initCalls bypass role gates during creation.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).renounceLastAdmin();
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/renounceRole.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/renounceRole.mdx
new file mode 100644
index 000000000..ac287ddff
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/renounceRole.mdx
@@ -0,0 +1,45 @@
+---
+title: "IB20.renounceRole"
+description: "Generated B20 reference for renounceRole(bytes32,address)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/roles-and-access-control)
+
+## Signature
+
+```solidity
+function renounceRole(bytes32 role, address callerConfirmation) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x36568abe` |
+| Canonical signature | `renounceRole(bytes32,address)` |
+
+## Description
+
+Caller renounces `role` for themselves. Emits `RoleRevoked`.
+Dev: Reverts with `AccessControlBadConfirmation` when `callerConfirmation != msg.sender`.
+Dev: Reverts with `LastAdminCannotRenounce` when `role == DEFAULT_ADMIN_ROLE` and the caller is the last default admin.
+Param: role Role to renounce.
+Param: callerConfirmation MUST equal `msg.sender`.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).renounceRole(arg0, arg1);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/revokeRole.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/revokeRole.mdx
new file mode 100644
index 000000000..b2d6e512b
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/revokeRole.mdx
@@ -0,0 +1,47 @@
+---
+title: "IB20.revokeRole"
+description: "Generated B20 reference for revokeRole(bytes32,address)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/roles-and-access-control)
+
+## Signature
+
+```solidity
+function revokeRole(bytes32 role, address account) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xd547741f` |
+| Canonical signature | `revokeRole(bytes32,address)` |
+
+## Description
+
+Revokes `role` from `account`. Emits `RoleRevoked`.
+Dev: Reverts with `AccessControlUnauthorizedAccount` when the caller does not hold the admin role for `role`,
+or when the token has been transitioned to admin-less via `renounceLastAdmin`.
+Dev: Reverts with `LastAdminCannotRenounce` when `role == DEFAULT_ADMIN_ROLE` and `account` is the last default admin.
+Use `renounceLastAdmin` to clear the final admin.
+Param: role Role to revoke.
+Param: account Account to revoke from.
+
+## Access control
+
+Uses the B20 access-control role graph. Factory initCalls bypass role gates during creation.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).revokeRole(arg0, arg1);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/seizeWithMemo.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/seizeWithMemo.mdx
new file mode 100644
index 000000000..4c6b439b9
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/seizeWithMemo.mdx
@@ -0,0 +1,56 @@
+---
+title: "IB20.seizeWithMemo"
+description: "Generated B20 reference for seizeWithMemo(address,address,uint256,bytes32)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/token-lifecycle)
+
+## Signature
+
+```solidity
+function seizeWithMemo(address from, address to, uint256 amount, bytes32 memo) external returns (bool);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xf916d81b` |
+| Canonical signature | `seizeWithMemo(address,address,uint256,bytes32)` |
+
+## Description
+
+Seizes `amount` of `from`'s balance and reassigns it to `to` in a single admin operation.
+Emits, in order, `Transfer(from, to, amount)`, `Memo(caller, memo)`, and
+`Seized(caller, from, to, amount)`. A memo of `bytes32(0)` is permitted.
+Dev: Admin operation: skips allowance and the transfer policies. The only membership check is that
+`from` is blocked under `SEIZE_HOLDER_POLICY`.
+Dev: `to` is not policy-checked; the destination need not be allowlisted.
+Dev: Reverts with `ContractPaused(SEIZE)` when `SEIZE` is paused.
+Dev: Reverts with `AccessControlUnauthorizedAccount` when the caller does not hold `SEIZE_ROLE`.
+Dev: Reverts with `InvalidReceiver` when `to == address(0)`.
+Dev: Reverts with `AccountNotSeizable` when `from` is currently authorized under `SEIZE_HOLDER_POLICY`.
+Dev: Reverts with `InsufficientBalance` when `from`'s balance is below `amount`.
+Param: from Account whose balance is being seized.
+Param: to Destination address for the seized balance.
+Param: amount Amount to seize.
+Param: memo Memo payload.
+Return: Always `true` on success.
+
+## Access control
+
+`SEIZE_ROLE` gates seizure calls.
+
+## Policy interaction
+
+Checks `SEIZE_HOLDER_POLICY`; the holder is seizable only when not authorized.
+
+## Example
+
+```solidity
+IB20(token).seizeWithMemo(holder, destination, amount, memo);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/setRoleAdmin.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/setRoleAdmin.mdx
new file mode 100644
index 000000000..fdbf840c2
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/setRoleAdmin.mdx
@@ -0,0 +1,45 @@
+---
+title: "IB20.setRoleAdmin"
+description: "Generated B20 reference for setRoleAdmin(bytes32,bytes32)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/roles-and-access-control)
+
+## Signature
+
+```solidity
+function setRoleAdmin(bytes32 role, bytes32 newAdminRole) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x1e4e0091` |
+| Canonical signature | `setRoleAdmin(bytes32,bytes32)` |
+
+## Description
+
+Sets the admin role for `role`. Emits `RoleAdminChanged`.
+Dev: Reverts with `AccessControlUnauthorizedAccount` when the caller does not hold the current admin role for `role`,
+or when the token has been transitioned to admin-less via `renounceLastAdmin`.
+Param: role Role whose admin is being updated.
+Param: newAdminRole New admin role.
+
+## Access control
+
+Uses the B20 access-control role graph. Factory initCalls bypass role gates during creation.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).setRoleAdmin(arg0, arg1);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/supplyCap.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/supplyCap.mdx
new file mode 100644
index 000000000..028edc360
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/supplyCap.mdx
@@ -0,0 +1,44 @@
+---
+title: "IB20.supplyCap"
+description: "Generated B20 reference for supplyCap()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function supplyCap() external view returns (uint256);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x8f770ad0` |
+| Canonical signature | `supplyCap()` |
+
+## Description
+
+The maximum total supply enforced on `mint`. Capped at `type(uint128).max`, which
+indicates no cap (the unbounded sentinel). `totalSupply` can therefore never exceed
+`type(uint128).max`.
+Return: Current supply cap.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).supplyCap();
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/symbol.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/symbol.mdx
new file mode 100644
index 000000000..e1eb7a5ea
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/symbol.mdx
@@ -0,0 +1,42 @@
+---
+title: "IB20.symbol"
+description: "Generated B20 reference for symbol()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function symbol() external view returns (string memory);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x95d89b41` |
+| Canonical signature | `symbol()` |
+
+## Description
+
+Token symbol. Set at creation, mutable via `updateSymbol`.
+Return: Current token symbol.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).symbol();
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/totalSupply.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/totalSupply.mdx
new file mode 100644
index 000000000..916299ef2
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/totalSupply.mdx
@@ -0,0 +1,42 @@
+---
+title: "IB20.totalSupply"
+description: "Generated B20 reference for totalSupply()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function totalSupply() external view returns (uint256);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x18160ddd` |
+| Canonical signature | `totalSupply()` |
+
+## Description
+
+Total token supply currently in circulation.
+Return: Current total supply.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).totalSupply();
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/transfer.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/transfer.mdx
new file mode 100644
index 000000000..f86ec477c
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/transfer.mdx
@@ -0,0 +1,50 @@
+---
+title: "IB20.transfer"
+description: "Generated B20 reference for transfer(address,uint256)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/token-lifecycle)
+
+## Signature
+
+```solidity
+function transfer(address to, uint256 amount) external returns (bool);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xa9059cbb` |
+| Canonical signature | `transfer(address,uint256)` |
+
+## Description
+
+Transfers `amount` from `msg.sender` to `to`. Emits `Transfer`.
+Dev: Reverts with `ContractPaused(TRANSFER)` when `TRANSFER` is paused.
+Dev: Reverts with `InvalidReceiver` when `to == address(0)`.
+Dev: Reverts with `InvalidSender` when `msg.sender == address(0)`.
+Dev: Reverts with `PolicyForbids(TRANSFER_SENDER_POLICY, ...)` when `msg.sender` is not authorized.
+Dev: Reverts with `PolicyForbids(TRANSFER_RECEIVER_POLICY, ...)` when `to` is not authorized.
+Dev: Reverts with `InsufficientBalance` when `msg.sender`'s balance is below `amount`.
+Param: to Destination address.
+Param: amount Amount to transfer.
+Return: Always `true` on success.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+Checks `TRANSFER_SENDER_POLICY` and `TRANSFER_RECEIVER_POLICY`; `approve` and `permit` are not policy-gated.
+
+## Example
+
+```solidity
+IB20(target).transfer(arg0, arg1);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/transferFrom.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/transferFrom.mdx
new file mode 100644
index 000000000..8f2eec178
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/transferFrom.mdx
@@ -0,0 +1,53 @@
+---
+title: "IB20.transferFrom"
+description: "Generated B20 reference for transferFrom(address,address,uint256)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/token-lifecycle)
+
+## Signature
+
+```solidity
+function transferFrom(address from, address to, uint256 amount) external returns (bool);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x23b872dd` |
+| Canonical signature | `transferFrom(address,address,uint256)` |
+
+## Description
+
+Transfers `amount` from `from` to `to` using `msg.sender`'s allowance. Emits `Transfer`.
+Dev: Reverts with `ContractPaused(TRANSFER)` when `TRANSFER` is paused.
+Dev: Reverts with `InvalidReceiver` when `to == address(0)`.
+Dev: Reverts with `InvalidSender` when `from == address(0)`.
+Dev: Reverts with `InsufficientAllowance` when the caller's allowance from `from` is below `amount`.
+Dev: Reverts with `PolicyForbids(TRANSFER_EXECUTOR_POLICY, ...)` when `msg.sender != from` and `msg.sender` is not authorized.
+Dev: Reverts with `PolicyForbids(TRANSFER_SENDER_POLICY, ...)` when `from` is not authorized.
+Dev: Reverts with `PolicyForbids(TRANSFER_RECEIVER_POLICY, ...)` when `to` is not authorized.
+Dev: Reverts with `InsufficientBalance` when `from`'s balance is below `amount`.
+Param: from Source address.
+Param: to Destination address.
+Param: amount Amount to transfer.
+Return: Always `true` on success.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+Checks `TRANSFER_EXECUTOR_POLICY` when `msg.sender != from`, plus sender and receiver transfer scopes.
+
+## Example
+
+```solidity
+IB20(target).transferFrom(arg0, arg1, arg2);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/transferFromWithMemo.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/transferFromWithMemo.mdx
new file mode 100644
index 000000000..d583f1819
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/transferFromWithMemo.mdx
@@ -0,0 +1,47 @@
+---
+title: "IB20.transferFromWithMemo"
+description: "Generated B20 reference for transferFromWithMemo(address,address,uint256,bytes32)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/token-lifecycle)
+
+## Signature
+
+```solidity
+function transferFromWithMemo(address from, address to, uint256 amount, bytes32 memo) external returns (bool);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x929c2539` |
+| Canonical signature | `transferFromWithMemo(address,address,uint256,bytes32)` |
+
+## Description
+
+Same as `transferFrom`, plus emits `Memo` immediately after the standard `Transfer` event.
+A memo of `bytes32(0)` is permitted.
+Param: from Source address.
+Param: to Destination address.
+Param: amount Amount to transfer.
+Param: memo Off-chain memo payload.
+Return: Always `true` on success.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+Checks `TRANSFER_EXECUTOR_POLICY` when `msg.sender != from`, plus sender and receiver transfer scopes.
+
+## Example
+
+```solidity
+IB20(target).transferFromWithMemo(arg0, arg1, arg2, arg3);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/transferWithMemo.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/transferWithMemo.mdx
new file mode 100644
index 000000000..20b43bdd2
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/transferWithMemo.mdx
@@ -0,0 +1,46 @@
+---
+title: "IB20.transferWithMemo"
+description: "Generated B20 reference for transferWithMemo(address,uint256,bytes32)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/token-lifecycle)
+
+## Signature
+
+```solidity
+function transferWithMemo(address to, uint256 amount, bytes32 memo) external returns (bool);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x95777d59` |
+| Canonical signature | `transferWithMemo(address,uint256,bytes32)` |
+
+## Description
+
+Same as `transfer`, plus emits `Memo` immediately after the standard `Transfer` event.
+A memo of `bytes32(0)` is permitted.
+Param: to Destination address.
+Param: amount Amount to transfer.
+Param: memo Off-chain memo payload.
+Return: Always `true` on success.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+Checks `TRANSFER_SENDER_POLICY` and `TRANSFER_RECEIVER_POLICY`; `approve` and `permit` are not policy-gated.
+
+## Example
+
+```solidity
+IB20(target).transferWithMemo(arg0, arg1, arg2);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/unpause.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/unpause.mdx
new file mode 100644
index 000000000..0461e8290
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/unpause.mdx
@@ -0,0 +1,45 @@
+---
+title: "IB20.unpause"
+description: "Generated B20 reference for unpause(PausableFeature[])."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/token-lifecycle)
+
+## Signature
+
+```solidity
+function unpause(PausableFeature[] calldata features) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xb61b2ebc` |
+| Canonical signature | `unpause(PausableFeature[])` |
+
+## Description
+
+Unpauses each of `features`. Features not listed are unaffected; duplicates are idempotent.
+Emits `Unpaused`.
+Dev: Reverts with `AccessControlUnauthorizedAccount` when the caller does not hold `UNPAUSE_ROLE`.
+Dev: Reverts with `EmptyFeatureSet` when `features.length == 0`.
+Param: features Features to unpause.
+
+## Access control
+
+`UNPAUSE_ROLE` gates this call.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).unpause(arg0);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/updateContractURI.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/updateContractURI.mdx
new file mode 100644
index 000000000..3be88f537
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/updateContractURI.mdx
@@ -0,0 +1,44 @@
+---
+title: "IB20.updateContractURI"
+description: "Generated B20 reference for updateContractURI(string)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function updateContractURI(string calldata newURI) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x7e5b1e24` |
+| Canonical signature | `updateContractURI(string)` |
+
+## Description
+
+Updates `contractURI`. Emits the parameterless `ContractURIUpdated` event per ERC-7572;
+integrators re-fetch `contractURI()` after observing it.
+Dev: Reverts with `AccessControlUnauthorizedAccount` when the caller does not hold `METADATA_ROLE`.
+Param: newURI New contract URI.
+
+## Access control
+
+`METADATA_ROLE` gates this call.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).updateContractURI(arg0);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/updateName.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/updateName.mdx
new file mode 100644
index 000000000..b366061d1
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/updateName.mdx
@@ -0,0 +1,43 @@
+---
+title: "IB20.updateName"
+description: "Generated B20 reference for updateName(string)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function updateName(string calldata newName) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x84da92a7` |
+| Canonical signature | `updateName(string)` |
+
+## Description
+
+Updates the token's `name`. Emits `NameUpdated` followed by `EIP712DomainChanged`.
+Dev: Reverts with `AccessControlUnauthorizedAccount` when the caller does not hold `METADATA_ROLE`.
+Param: newName New token name.
+
+## Access control
+
+`METADATA_ROLE` gates this call.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).updateName(arg0);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/updatePolicy.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/updatePolicy.mdx
new file mode 100644
index 000000000..78a6aa7db
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/updatePolicy.mdx
@@ -0,0 +1,47 @@
+---
+title: "IB20.updatePolicy"
+description: "Generated B20 reference for updatePolicy(bytes32,uint64)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/policies-and-scopes)
+
+## Signature
+
+```solidity
+function updatePolicy(bytes32 policyScope, uint64 newPolicyId) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xadf9c4ea` |
+| Canonical signature | `updatePolicy(bytes32,uint64)` |
+
+## Description
+
+Updates the policy ID assigned to `policyScope`. Takes effect immediately for the next
+operation that consults this slot. Emits `PolicyUpdated`.
+Dev: Reverts with `AccessControlUnauthorizedAccount` when the caller does not hold `DEFAULT_ADMIN_ROLE`.
+Dev: Reverts with `UnsupportedPolicyType` when `policyScope` is not recognized by this token.
+Dev: Reverts with `PolicyNotFound` when `newPolicyId` is not a built-in sentinel and does not exist in the registry.
+Param: policyScope Policy slot scope.
+Param: newPolicyId Policy ID to assign to the slot.
+
+## Access control
+
+`DEFAULT_ADMIN_ROLE` gates this call. Factory initCalls bypass the role gate during creation.
+
+## Policy interaction
+
+Reads or writes a token policy-scope pointer into the PolicyRegistry.
+
+## Example
+
+```solidity
+IB20(token).updatePolicy(B20Constants.MINT_RECEIVER_POLICY, policyId);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/updateSupplyCap.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/updateSupplyCap.mdx
new file mode 100644
index 000000000..c17ad80e4
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/updateSupplyCap.mdx
@@ -0,0 +1,45 @@
+---
+title: "IB20.updateSupplyCap"
+description: "Generated B20 reference for updateSupplyCap(uint256)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function updateSupplyCap(uint256 newSupplyCap) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xe5a97f07` |
+| Canonical signature | `updateSupplyCap(uint256)` |
+
+## Description
+
+Sets a new supply cap. May be raised or lowered freely, but never below current
+`totalSupply` and never above `type(uint128).max`. Emits `SupplyCapUpdated`.
+Dev: Reverts with `AccessControlUnauthorizedAccount` when the caller does not hold `DEFAULT_ADMIN_ROLE`.
+Dev: Reverts with `InvalidSupplyCap` when `newSupplyCap < totalSupply()` or `newSupplyCap > type(uint128).max`.
+Param: newSupplyCap New supply cap. Must not exceed `type(uint128).max`.
+
+## Access control
+
+`DEFAULT_ADMIN_ROLE` gates this call. Factory initCalls bypass the role gate during creation.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).updateSupplyCap(arg0);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/updateSymbol.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/updateSymbol.mdx
new file mode 100644
index 000000000..e1e97c013
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20/updateSymbol.mdx
@@ -0,0 +1,43 @@
+---
+title: "IB20.updateSymbol"
+description: "Generated B20 reference for updateSymbol(string)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20)
+
+## Signature
+
+```solidity
+function updateSymbol(string calldata newSymbol) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x537f5312` |
+| Canonical signature | `updateSymbol(string)` |
+
+## Description
+
+Updates the token's `symbol`. Emits `SymbolUpdated`.
+Dev: Reverts with `AccessControlUnauthorizedAccount` when the caller does not hold `METADATA_ROLE`.
+Param: newSymbol New token symbol.
+
+## Access control
+
+`METADATA_ROLE` gates this call.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20(target).updateSymbol(arg0);
+```
+
+## Related
+
+- [IB20 reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset.mdx
new file mode 100644
index 000000000..48619ad65
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset.mdx
@@ -0,0 +1,55 @@
+---
+title: "IB20Asset reference"
+description: "Generated B20 reference for IB20Asset functions, events, and errors."
+---
+
+
+## Functions
+
+| Function | Selector | Summary |
+|---|---|---|
+| [`OPERATOR_ROLE`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/OPERATOR_ROLE) | `0xf5b541a6` | Required to call `announce`, `setUIMultiplier`, `cancelScheduledMultiplier`, and |
+| [`WAD_PRECISION`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/WAD_PRECISION) | `0x664808a8` | Fixed-point precision used to scale `multiplier`. Equal to `1e18`. |
+| [`announce`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/announce) | `0x595135dd` | Posts a holder-impacting announcement and atomically dispatches each entry in |
+| [`isAnnouncementIdUsed`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/isAnnouncementIdUsed) | `0xc0da474e` | Whether `id` has previously been consumed by `announce`. |
+| [`multiplier`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/multiplier) | `0x1b3ed722` | The current multiplier, scaled to `WAD_PRECISION`. Holder balances are stored |
+| [`toScaledBalance`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/toScaledBalance) | `0x04f04c99` | Converts a raw balance to its scaled view: `rawBalance * multiplier / WAD_PRECISION`. |
+| [`toRawBalance`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/toRawBalance) | `0x0ca06c44` | Converts a scaled balance back to its raw representation: |
+| [`scaledBalanceOf`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/scaledBalanceOf) | `0x1da24f3e` | Convenience for `toScaledBalance(balanceOf(account))`. |
+| [`setUIMultiplier`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/setUIMultiplier) | `0x93d32890` | Schedules a multiplier update to take effect at `effectiveAt` — the standard path |
+| [`cancelScheduledMultiplier`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/cancelScheduledMultiplier) | `0xc4b1e3e7` | Cancels the single live pending update, restoring the no-pending state |
+| [`updateMultiplier`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/updateMultiplier) | `0x5ffe6146` | Instant failsafe / emergency override — sets the current multiplier immediately and |
+| [`batchMint`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/batchMint) | `0x68573107` | Mints `amounts[i]` to `recipients[i]` in one call. All-or-nothing: any element |
+| [`extraMetadata`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/extraMetadata) | `0x4ddf9da0` | The value of the named metadata entry, or the empty string if not set. A |
+| [`updateExtraMetadata`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/updateExtraMetadata) | `0xb2851ef5` | Sets, updates, or removes an extra-metadata entry. An empty `value` removes the |
+
+## Events
+
+| Event | Topic0 | Summary |
+|---|---|---|
+| `MultiplierUpdateCancelled` | `0xf8929975f3e67bbd1e5ec70d4cceaa7cce7ea0e811720f29c96cf1724de09397` | A scheduled multiplier update was cancelled. Emitted by `cancelScheduledMultiplier`, |
+| `ExtraMetadataUpdated` | `0xd7bb345be29e78d635203d40fe0567e7ef19d5cd5cc5fcd25f768b8063e82aa1` | Emitted by `updateExtraMetadata`. An empty `value` indicates removal. |
+| `Announcement` | `0xccebf8218a62875909564adef86a6f4df81503cb617221e793357d62f8e813f7` | Emitted by `announce` to open an announcement bracket. |
+| `EndAnnouncement` | `0x96d64dafe2c790596430196b982ad1da3221cb3b0f4e6e2df77f2e4f71a90037` | Emitted by `announce` to close the bracket opened by the paired `Announcement` with the same `id`. |
+
+## Errors
+
+| Error | Selector | Summary |
+|---|---|---|
+| `AnnouncementIdAlreadyUsed` | `0xd10b3c9e` | `announce` was called with an `id` that has already been consumed. |
+| `InvalidMetadataKey` | `0x86ea3abb` | `updateExtraMetadata` was called with an empty `key`. |
+| `InvalidMultiplier` | `0x6f12f3dc` | A multiplier setter (`setUIMultiplier` or `updateMultiplier`) was called with a |
+| `EffectiveAtInPast` | `0x14119cf6` | `setUIMultiplier` was called with an `effectiveAt` that is not in the future |
+| `EffectiveAtTooFar` | `0x1ce214fa` | `setUIMultiplier` was called with an `effectiveAt` above `type(uint64).max`, the |
+| `ScheduleOverlap` | `0x91a52665` | `setUIMultiplier` was called while a live pending update already exists |
+| `NoScheduledMultiplier` | `0x002e806f` | `cancelScheduledMultiplier` was called when there is no live pending update |
+| `LengthMismatch` | `0xab8b67c6` | A batched function was called with parallel arrays of differing lengths. |
+| `EmptyBatch` | `0xc2e5347d` | A batched function was called with empty arrays. |
+| `AnnouncementInProgress` | `0x5c5f0829` | An inner call dispatched by `announce` tried to re-invoke `announce`. |
+| `InternalCallMalformed` | `0x4e2f143e` | An inner call dispatched by `announce` was shorter than four bytes. |
+| `InternalCallFailed` | `0xb288a127` | An inner call dispatched by `announce` reverted with an ordinary revert; its reason is |
+
+
+
+
+
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/OPERATOR_ROLE.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/OPERATOR_ROLE.mdx
new file mode 100644
index 000000000..061ebfac6
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/OPERATOR_ROLE.mdx
@@ -0,0 +1,44 @@
+---
+title: "IB20Asset.OPERATOR_ROLE"
+description: "Generated B20 reference for OPERATOR_ROLE()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/variants-asset-vs-stablecoin)
+
+## Signature
+
+```solidity
+function OPERATOR_ROLE() external view returns (bytes32);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xf5b541a6` |
+| Canonical signature | `OPERATOR_ROLE()` |
+
+## Description
+
+Required to call `announce`, `setUIMultiplier`, `cancelScheduledMultiplier`, and
+`updateMultiplier`. The metadata setters (`updateName`, `updateSymbol`,
+`updateExtraMetadata`) are gated by the inherited `METADATA_ROLE` instead.
+Return: Role constant.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20Asset(target).OPERATOR_ROLE();
+```
+
+## Related
+
+- [IB20Asset reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/WAD_PRECISION.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/WAD_PRECISION.mdx
new file mode 100644
index 000000000..fc7054487
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/WAD_PRECISION.mdx
@@ -0,0 +1,42 @@
+---
+title: "IB20Asset.WAD_PRECISION"
+description: "Generated B20 reference for WAD_PRECISION()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/variants-asset-vs-stablecoin)
+
+## Signature
+
+```solidity
+function WAD_PRECISION() external view returns (uint256);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x664808a8` |
+| Canonical signature | `WAD_PRECISION()` |
+
+## Description
+
+Fixed-point precision used to scale `multiplier`. Equal to `1e18`.
+Return: Precision constant.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20Asset(target).WAD_PRECISION();
+```
+
+## Related
+
+- [IB20Asset reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/announce.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/announce.mdx
new file mode 100644
index 000000000..b79d2f3ba
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/announce.mdx
@@ -0,0 +1,55 @@
+---
+title: "IB20Asset.announce"
+description: "Generated B20 reference for announce(bytes[],string,string,string)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/variants-asset-vs-stablecoin)
+
+## Signature
+
+```solidity
+function announce( bytes[] calldata internalCalls, string calldata id, string calldata description, string calldata uri ) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x595135dd` |
+| Canonical signature | `announce(bytes[],string,string,string)` |
+
+## Description
+
+Posts a holder-impacting announcement and atomically dispatches each entry in
+`internalCalls` via self-`delegatecall` (preserving `msg.sender`). Emits
+`Announcement` then `EndAnnouncement` with the same `id`. Pass an empty
+`internalCalls` for a pure disclosure.
+Dev: Reverts with `AccessControlUnauthorizedAccount` when the caller does not hold `OPERATOR_ROLE`.
+Dev: Reverts with `AnnouncementIdAlreadyUsed` when `id` has previously been consumed.
+Dev: Reverts with `InternalCallMalformed` when an entry in `internalCalls` is shorter than four bytes.
+Dev: Reverts with `AnnouncementInProgress` when an entry in `internalCalls` targets `announce` itself.
+Dev: An inner call that raises a Solidity `Panic` (e.g. arithmetic overflow) propagates the
+raw Panic unchanged; any other inner revert wraps as `InternalCallFailed(call)`. An inner
+out-of-gas halts the whole call.
+Param: internalCalls ABI-encoded calldata blobs executed in order via self-`delegatecall`; may be empty.
+Param: id Caller-chosen announcement id; single-use over the token's lifetime.
+Param: description Human-readable summary of the announcement.
+Param: uri Off-chain URI containing the full announcement contents.
+
+## Access control
+
+`OPERATOR_ROLE` gates this Asset call.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20Asset(target).announce(arg0, arg1, arg2, arg3);
+```
+
+## Related
+
+- [IB20Asset reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/batchMint.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/batchMint.mdx
new file mode 100644
index 000000000..f1094d370
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/batchMint.mdx
@@ -0,0 +1,52 @@
+---
+title: "IB20Asset.batchMint"
+description: "Generated B20 reference for batchMint(address[],uint256[])."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/variants-asset-vs-stablecoin)
+
+## Signature
+
+```solidity
+function batchMint(address[] calldata recipients, uint256[] calldata amounts) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x68573107` |
+| Canonical signature | `batchMint(address[],uint256[])` |
+
+## Description
+
+Mints `amounts[i]` to `recipients[i]` in one call. All-or-nothing: any element
+revert unwinds the whole transaction. Emits `Transfer(address(0), recipients[i], amounts[i])`
+per element.
+Dev: Reverts with `ContractPaused(MINT)` when `MINT` is paused.
+Dev: Reverts with `AccessControlUnauthorizedAccount` when the caller does not hold `MINT_ROLE`.
+Dev: Reverts with `LengthMismatch` when `recipients.length != amounts.length`.
+Dev: Reverts with `EmptyBatch` when either array is empty.
+Dev: Reverts with `InvalidReceiver` when any `recipients[i] == address(0)`.
+Dev: Reverts with `PolicyForbids(MINT_RECEIVER_POLICY, ...)` when any recipient is not authorized.
+Dev: Reverts with `SupplyCapExceeded` when the cumulative mint would exceed the cap.
+Param: recipients Accounts receiving the minted tokens.
+Param: amounts Per-recipient amounts, parallel to `recipients`.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20Asset(target).batchMint(arg0, arg1);
+```
+
+## Related
+
+- [IB20Asset reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/cancelScheduledMultiplier.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/cancelScheduledMultiplier.mdx
new file mode 100644
index 000000000..0d0cb3783
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/cancelScheduledMultiplier.mdx
@@ -0,0 +1,44 @@
+---
+title: "IB20Asset.cancelScheduledMultiplier"
+description: "Generated B20 reference for cancelScheduledMultiplier()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/variants-asset-vs-stablecoin)
+
+## Signature
+
+```solidity
+function cancelScheduledMultiplier() external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xc4b1e3e7` |
+| Canonical signature | `cancelScheduledMultiplier()` |
+
+## Description
+
+Cancels the single live pending update, restoring the no-pending state
+(`effectiveAt` resets to 0).
+Dev: Reverts with `AccessControlUnauthorizedAccount` when the caller does not hold `OPERATOR_ROLE`.
+Dev: Reverts with `NoScheduledMultiplier` when there is no live pending update.
+
+## Access control
+
+`OPERATOR_ROLE` gates this Asset call.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20Asset(target).cancelScheduledMultiplier();
+```
+
+## Related
+
+- [IB20Asset reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/extraMetadata.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/extraMetadata.mdx
new file mode 100644
index 000000000..d9f53be6a
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/extraMetadata.mdx
@@ -0,0 +1,45 @@
+---
+title: "IB20Asset.extraMetadata"
+description: "Generated B20 reference for extraMetadata(string)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/variants-asset-vs-stablecoin)
+
+## Signature
+
+```solidity
+function extraMetadata(string calldata key) external view returns (string memory);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x4ddf9da0` |
+| Canonical signature | `extraMetadata(string)` |
+
+## Description
+
+The value of the named metadata entry, or the empty string if not set. A
+variant-agnostic key/value store; the issuer chooses the key namespace
+(e.g. `"category"`, `"region"`, `"reference"`).
+Param: key Metadata entry key.
+Return: Current value, or the empty string.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20Asset(target).extraMetadata(arg0);
+```
+
+## Related
+
+- [IB20Asset reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/isAnnouncementIdUsed.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/isAnnouncementIdUsed.mdx
new file mode 100644
index 000000000..d1098def3
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/isAnnouncementIdUsed.mdx
@@ -0,0 +1,43 @@
+---
+title: "IB20Asset.isAnnouncementIdUsed"
+description: "Generated B20 reference for isAnnouncementIdUsed(string)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/variants-asset-vs-stablecoin)
+
+## Signature
+
+```solidity
+function isAnnouncementIdUsed(string calldata id) external view returns (bool);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xc0da474e` |
+| Canonical signature | `isAnnouncementIdUsed(string)` |
+
+## Description
+
+Whether `id` has previously been consumed by `announce`.
+Param: id Announcement id to query.
+Return: Whether `id` is used.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20Asset(target).isAnnouncementIdUsed(arg0);
+```
+
+## Related
+
+- [IB20Asset reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/multiplier.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/multiplier.mdx
new file mode 100644
index 000000000..c06874045
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/multiplier.mdx
@@ -0,0 +1,45 @@
+---
+title: "IB20Asset.multiplier"
+description: "Generated B20 reference for multiplier()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/variants-asset-vs-stablecoin)
+
+## Signature
+
+```solidity
+function multiplier() external view returns (uint256);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x1b3ed722` |
+| Canonical signature | `multiplier()` |
+
+## Description
+
+The current multiplier, scaled to `WAD_PRECISION`. Holder balances are stored
+as raw units; the multiplier scales them into a derived "scaled" view, similar
+in shape to wstETH wrapping stETH.
+Dev: Alias of the ERC-8056 `uiMultiplier()`.
+Return: Current (effective) multiplier.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20Asset(target).multiplier();
+```
+
+## Related
+
+- [IB20Asset reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/scaledBalanceOf.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/scaledBalanceOf.mdx
new file mode 100644
index 000000000..e759f2c98
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/scaledBalanceOf.mdx
@@ -0,0 +1,43 @@
+---
+title: "IB20Asset.scaledBalanceOf"
+description: "Generated B20 reference for scaledBalanceOf(address)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/variants-asset-vs-stablecoin)
+
+## Signature
+
+```solidity
+function scaledBalanceOf(address account) external view returns (uint256);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x1da24f3e` |
+| Canonical signature | `scaledBalanceOf(address)` |
+
+## Description
+
+Convenience for `toScaledBalance(balanceOf(account))`.
+Param: account Account whose scaled balance is being queried.
+Return: Scaled balance.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20Asset(target).scaledBalanceOf(arg0);
+```
+
+## Related
+
+- [IB20Asset reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/setUIMultiplier.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/setUIMultiplier.mdx
new file mode 100644
index 000000000..04d0211d6
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/setUIMultiplier.mdx
@@ -0,0 +1,49 @@
+---
+title: "IB20Asset.setUIMultiplier"
+description: "Generated B20 reference for setUIMultiplier(uint256,uint256)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/variants-asset-vs-stablecoin)
+
+## Signature
+
+```solidity
+function setUIMultiplier(uint256 newMultiplier, uint256 effectiveAt) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x93d32890` |
+| Canonical signature | `setUIMultiplier(uint256,uint256)` |
+
+## Description
+
+Schedules a multiplier update to take effect at `effectiveAt` — the standard path
+for corporate actions (splits, reinvested dividends).
+Dev: Reverts with `AccessControlUnauthorizedAccount` when the caller does not hold `OPERATOR_ROLE`.
+Dev: Reverts with `InvalidMultiplier` when `newMultiplier` is zero or above `type(uint128).max`.
+Dev: Reverts with `EffectiveAtInPast` when `effectiveAt` is not in the future.
+Dev: Reverts with `EffectiveAtTooFar` when `effectiveAt` exceeds `type(uint64).max`.
+Dev: Reverts with `ScheduleOverlap` when a live pending update already exists.
+Param: newMultiplier New multiplier scaled to `WAD_PRECISION`.
+Param: effectiveAt Timestamp at which `newMultiplier` becomes effective; must be in the future.
+
+## Access control
+
+`OPERATOR_ROLE` gates this Asset call.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20Asset(target).setUIMultiplier(arg0, arg1);
+```
+
+## Related
+
+- [IB20Asset reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/toRawBalance.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/toRawBalance.mdx
new file mode 100644
index 000000000..9ec22ab5f
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/toRawBalance.mdx
@@ -0,0 +1,47 @@
+---
+title: "IB20Asset.toRawBalance"
+description: "Generated B20 reference for toRawBalance(uint256)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/variants-asset-vs-stablecoin)
+
+## Signature
+
+```solidity
+function toRawBalance(uint256 scaledBalance) external view returns (uint256 rawBalance);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x0ca06c44` |
+| Canonical signature | `toRawBalance(uint256)` |
+
+## Description
+
+Converts a scaled balance back to its raw representation:
+`scaledBalance * WAD_PRECISION / multiplier`.
+Dev: Integer division rounds toward zero; conversions are not exactly reversible when
+`multiplier != WAD_PRECISION`. `toRawBalance(toScaledBalance(x))` may return a
+value slightly less than `x`.
+Param: scaledBalance Scaled token amount to convert back.
+Return: rawBalance Raw balance at the current multiplier.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20Asset(target).toRawBalance(arg0);
+```
+
+## Related
+
+- [IB20Asset reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/toScaledBalance.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/toScaledBalance.mdx
new file mode 100644
index 000000000..ce16e97db
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/toScaledBalance.mdx
@@ -0,0 +1,43 @@
+---
+title: "IB20Asset.toScaledBalance"
+description: "Generated B20 reference for toScaledBalance(uint256)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/variants-asset-vs-stablecoin)
+
+## Signature
+
+```solidity
+function toScaledBalance(uint256 rawBalance) external view returns (uint256);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x04f04c99` |
+| Canonical signature | `toScaledBalance(uint256)` |
+
+## Description
+
+Converts a raw balance to its scaled view: `rawBalance * multiplier / WAD_PRECISION`.
+Param: rawBalance Raw token amount to scale.
+Return: Scaled balance at the current multiplier.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20Asset(target).toScaledBalance(arg0);
+```
+
+## Related
+
+- [IB20Asset reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/updateExtraMetadata.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/updateExtraMetadata.mdx
new file mode 100644
index 000000000..f0d094de4
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/updateExtraMetadata.mdx
@@ -0,0 +1,46 @@
+---
+title: "IB20Asset.updateExtraMetadata"
+description: "Generated B20 reference for updateExtraMetadata(string,string)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/variants-asset-vs-stablecoin)
+
+## Signature
+
+```solidity
+function updateExtraMetadata(string calldata key, string calldata value) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xb2851ef5` |
+| Canonical signature | `updateExtraMetadata(string,string)` |
+
+## Description
+
+Sets, updates, or removes an extra-metadata entry. An empty `value` removes the
+entry. Emits `ExtraMetadataUpdated`.
+Dev: Reverts with `AccessControlUnauthorizedAccount` when the caller does not hold `METADATA_ROLE`.
+Dev: Reverts with `InvalidMetadataKey` when `key` is the empty string.
+Param: key Metadata entry key (e.g. `"category"`).
+Param: value New value, or empty string to remove.
+
+## Access control
+
+`METADATA_ROLE` gates this call.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20Asset(target).updateExtraMetadata(arg0, arg1);
+```
+
+## Related
+
+- [IB20Asset reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/updateMultiplier.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/updateMultiplier.mdx
new file mode 100644
index 000000000..89177a70c
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset/updateMultiplier.mdx
@@ -0,0 +1,46 @@
+---
+title: "IB20Asset.updateMultiplier"
+description: "Generated B20 reference for updateMultiplier(uint256)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/variants-asset-vs-stablecoin)
+
+## Signature
+
+```solidity
+function updateMultiplier(uint256 newMultiplier) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x5ffe6146` |
+| Canonical signature | `updateMultiplier(uint256)` |
+
+## Description
+
+Instant failsafe / emergency override — sets the current multiplier immediately and
+cancels any live pending update without a scheduling window.
+Prefer `setUIMultiplier` for routine corporate actions.
+Dev: Reverts with `AccessControlUnauthorizedAccount` when the caller does not hold `OPERATOR_ROLE`.
+Dev: Reverts with `InvalidMultiplier` when `newMultiplier` is zero or above `type(uint128).max`.
+Param: newMultiplier New multiplier scaled to `WAD_PRECISION`; must be in `(0, type(uint128).max]`.
+
+## Access control
+
+`OPERATOR_ROLE` gates this Asset call.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20Asset(target).updateMultiplier(arg0);
+```
+
+## Related
+
+- [IB20Asset reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Asset)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Factory.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Factory.mdx
new file mode 100644
index 000000000..5f7d4bf08
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Factory.mdx
@@ -0,0 +1,38 @@
+---
+title: "IB20Factory reference"
+description: "Generated B20 reference for IB20Factory functions, events, and errors."
+---
+
+
+## Functions
+
+| Function | Selector | Summary |
+|---|---|---|
+| [`createB20`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Factory/createB20) | `0xb263cb84` | Creates a B-20 token of the given `variant` at the deterministic address derived |
+| [`getB20Address`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Factory/getB20Address) | `0x51038444` | Returns the deterministic address `createB20` would assign for `(variant, sender, salt)`. Never reverts. |
+| [`isB20`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Factory/isB20) | `0xfa19b927` | Returns whether `token` was created by this factory, recovered from the address prefix. Never reverts. |
+| [`isB20Initialized`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Factory/isB20Initialized) | `0x6a45ba98` | Returns whether `createB20` has run to completion at `token`. Flips exactly once, |
+
+## Events
+
+| Event | Topic0 | Summary |
+|---|---|---|
+| `B20Created` | `0x86ee7a93da43b07286ea4c925a31ba17c41eb00c5ea396883bf32abfe5e73cfc` | Emitted once per `createB20` invocation, after the token's identity is sealed |
+
+## Errors
+
+| Error | Selector | Summary |
+|---|---|---|
+| `NonPayable` | `0x6fb1b0e9` | ETH was attached to a call targeting a nonpayable factory selector. |
+| `TokenAlreadyExists` | `0x15ef3a57` | A token already exists at the deterministic address derived from |
+| `InvalidVariant` | `0xf10e8e43` | `variant` is not a recognized `B20Variant`. |
+| `UnsupportedVersion` | `0x6f3c1955` | The leading `version` byte in `params` does not match any known encoding for the requested variant. |
+| `MissingRequiredField` | `0x4a43ae87` | A required string argument was the empty string. |
+| `InvalidCurrency` | `0x997c1de8` | The stablecoin `currency` was non-empty but contained a non-`A`-`Z` byte. |
+| `InvalidDecimals` | `0xca950391` | The asset `decimals` was outside the allowed inclusive range |
+| `InitCallFailed` | `0x4eae0860` | One of the `initCalls` reverted. The factory bubbles the underlying revert reason |
+
+
+
+
+
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Factory/createB20.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Factory/createB20.mdx
new file mode 100644
index 000000000..b0ca18557
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Factory/createB20.mdx
@@ -0,0 +1,70 @@
+---
+title: "IB20Factory.createB20"
+description: "Generated B20 reference for createB20(B20Variant,bytes32,bytes,bytes[])."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/implementation/deployment-and-initcalls-encoding)
+
+## Signature
+
+```solidity
+function createB20(B20Variant variant, bytes32 salt, bytes calldata params, bytes[] calldata initCalls) external payable returns (address token);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xb263cb84` |
+| Canonical signature | `createB20(B20Variant,bytes32,bytes,bytes[])` |
+
+## Description
+
+Creates a B-20 token of the given `variant` at the deterministic address derived
+from `(variant, msg.sender, salt)`, then dispatches each entry in `initCalls` on
+the new token. Emits `B20Created`.
+Dev: Reverts with `NonPayable` when ETH is attached to the call.
+Dev: Reverts with IActivationRegistry.FeatureNotActivated when the variant feature is not activated.
+Dev: Reverts with `InvalidVariant` when `variant` is outside the `B20Variant` range.
+Dev: Reverts with `UnsupportedVersion` when the leading `version` byte in `params` is unrecognized for `variant`.
+Dev: Reverts with `MissingRequiredField` when a required string field is empty (e.g. stablecoin `currency`).
+Dev: Reverts with `InvalidCurrency` when a stablecoin `currency` is non-empty but contains a non-`A`-`Z` byte.
+Dev: Reverts with `InvalidDecimals` when an asset `decimals` is outside `[B20Constants.MIN_ASSET_DECIMALS, B20Constants.MAX_ASSET_DECIMALS]`.
+Dev: Reverts with `TokenAlreadyExists` when a token already exists at the derived address.
+Dev: Reverts with `InitCallFailed` (or the bubbled inner reason) when any entry in `initCalls` reverts.
+Dev: Each `initCall` executes on the new token within the creation (bootstrap) window, during which
+factory-originated calls bypass the token's role gates and its transfer-side policy gates
+(`TRANSFER_SENDER_POLICY`, `TRANSFER_RECEIVER_POLICY`, `TRANSFER_EXECUTOR_POLICY`) — so admin-gated
+setup (e.g. `grantRole`, `updatePolicy`, `updateSupplyCap`) and bootstrap transfers succeed without
+the factory holding any role. The bypass is deliberately NOT total:
+- `MINT_RECEIVER_POLICY` is ALWAYS enforced, including for factory-originated mints, so new supply is
+never issued to a policy-denied recipient even at creation. An `initCalls` bundle that sets a
+restrictive `MINT_RECEIVER_POLICY` and then mints to a non-authorized account reverts
+`PolicyForbids(MINT_RECEIVER_POLICY, ...)` (bubbled out of `createB20`).
+- Pause is never bypassed. It defaults to nothing-paused at creation, so a start-paused
+configuration must sequence its `pause(...)` call last among the `initCalls`.
+- Token invariants (supply-cap math, balance accounting) are never bypassed.
+The window closes when `createB20` returns; the factory retains no persisted access.
+Param: variant Which variant struct `params` decodes as.
+Param: salt Caller-chosen salt for deterministic address derivation.
+Param: params ABI-encoded variant-specific creation struct, leading with the version byte.
+Param: initCalls Bootstrap calls invoked on the new token after identity is sealed.
+Return: token The address of the newly created token.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+address token = StdPrecompiles.B20_FACTORY.createB20(variant, salt, params, initCalls);
+```
+
+## Related
+
+- [IB20Factory reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Factory)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Factory/getB20Address.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Factory/getB20Address.mdx
new file mode 100644
index 000000000..7ace6dd39
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Factory/getB20Address.mdx
@@ -0,0 +1,45 @@
+---
+title: "IB20Factory.getB20Address"
+description: "Generated B20 reference for getB20Address(B20Variant,address,bytes32)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/implementation/deployment-and-initcalls-encoding)
+
+## Signature
+
+```solidity
+function getB20Address(B20Variant variant, address sender, bytes32 salt) external view returns (address);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x51038444` |
+| Canonical signature | `getB20Address(B20Variant,address,bytes32)` |
+
+## Description
+
+Returns the deterministic address `createB20` would assign for `(variant, sender, salt)`. Never reverts.
+Param: variant Variant of the token whose address is being predicted.
+Param: sender Account that would call `createB20`.
+Param: salt Caller-chosen salt.
+Return: The deterministic token address.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20Factory(target).getB20Address(arg0, arg1, arg2);
+```
+
+## Related
+
+- [IB20Factory reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Factory)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Factory/isB20.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Factory/isB20.mdx
new file mode 100644
index 000000000..a5ae4db18
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Factory/isB20.mdx
@@ -0,0 +1,43 @@
+---
+title: "IB20Factory.isB20"
+description: "Generated B20 reference for isB20(address)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/implementation/deployment-and-initcalls-encoding)
+
+## Signature
+
+```solidity
+function isB20(address token) external view returns (bool);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xfa19b927` |
+| Canonical signature | `isB20(address)` |
+
+## Description
+
+Returns whether `token` was created by this factory, recovered from the address prefix. Never reverts.
+Param: token Address to check.
+Return: Whether `token` matches the B-20 address prefix.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20Factory(target).isB20(arg0);
+```
+
+## Related
+
+- [IB20Factory reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Factory)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Factory/isB20Initialized.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Factory/isB20Initialized.mdx
new file mode 100644
index 000000000..c6933533a
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Factory/isB20Initialized.mdx
@@ -0,0 +1,44 @@
+---
+title: "IB20Factory.isB20Initialized"
+description: "Generated B20 reference for isB20Initialized(address)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/implementation/deployment-and-initcalls-encoding)
+
+## Signature
+
+```solidity
+function isB20Initialized(address token) external view returns (bool);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x6a45ba98` |
+| Canonical signature | `isB20Initialized(address)` |
+
+## Description
+
+Returns whether `createB20` has run to completion at `token`. Flips exactly once,
+the moment the creating `createB20` call returns. Never reverts.
+Param: token Address to check.
+Return: Whether `token` is an initialized B-20.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20Factory(target).isB20Initialized(arg0);
+```
+
+## Related
+
+- [IB20Factory reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Factory)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Stablecoin.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Stablecoin.mdx
new file mode 100644
index 000000000..e9d66398d
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Stablecoin.mdx
@@ -0,0 +1,28 @@
+---
+title: "IB20Stablecoin reference"
+description: "Generated B20 reference for IB20Stablecoin functions, events, and errors."
+---
+
+
+## Functions
+
+| Function | Selector | Summary |
+|---|---|---|
+| [`currency`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Stablecoin/currency) | `0xe5a6b10f` | The currency code this stablecoin tracks (e.g. `"USD"`, `"EUR"`, `"JPY"`). |
+
+## Events
+
+| Event | Topic0 | Summary |
+|---|---|---|
+| — | — | — |
+
+## Errors
+
+| Error | Selector | Summary |
+|---|---|---|
+| — | — | — |
+
+
+
+
+
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Stablecoin/currency.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Stablecoin/currency.mdx
new file mode 100644
index 000000000..d4b43cbad
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Stablecoin/currency.mdx
@@ -0,0 +1,42 @@
+---
+title: "IB20Stablecoin.currency"
+description: "Generated B20 reference for currency()."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/variants-asset-vs-stablecoin)
+
+## Signature
+
+```solidity
+function currency() external view returns (string memory);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xe5a6b10f` |
+| Canonical signature | `currency()` |
+
+## Description
+
+The currency code this stablecoin tracks (e.g. `"USD"`, `"EUR"`, `"JPY"`).
+Return: Currency code.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+No direct policy interaction.
+
+## Example
+
+```solidity
+IB20Stablecoin(target).currency();
+```
+
+## Related
+
+- [IB20Stablecoin reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IB20Stablecoin)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry.mdx
new file mode 100644
index 000000000..ae4a363f0
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry.mdx
@@ -0,0 +1,54 @@
+---
+title: "IPolicyRegistry reference"
+description: "Generated B20 reference for IPolicyRegistry functions, events, and errors."
+---
+
+
+## Functions
+
+| Function | Selector | Summary |
+|---|---|---|
+| [`createPolicy`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/createPolicy) | `0xe494a1f6` | Creates a new simple policy with no initial members. Permissionless. |
+| [`createPolicyWithAccounts`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/createPolicyWithAccounts) | `0xffd4931c` | Creates a new simple policy seeded with `accounts` as initial members. Permissionless. |
+| [`createCompositePolicy`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/createCompositePolicy) | `0xc341f3f0` | Creates a new composite policy that combines existing simple policies under a logic |
+| [`stageUpdateAdmin`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/stageUpdateAdmin) | `0x1d7ae695` | Stages a proposed new admin for `policyId`. The active admin does not change |
+| [`finalizeUpdateAdmin`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/finalizeUpdateAdmin) | `0x33031a9c` | Completes a two-step admin transfer. Promotes the caller to active admin and clears the pending slot. |
+| [`renounceAdmin`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/renounceAdmin) | `0xefdb7fa3` | Permanently relinquishes administration of `policyId`. The member set is frozen |
+| [`updateAllowlist`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/updateAllowlist) | `0x3388fb5b` | Sets `accounts` membership in an ALLOWLIST policy to `allowed` in one batch. |
+| [`updateBlocklist`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/updateBlocklist) | `0x5c4e51b8` | Sets `accounts` membership in a BLOCKLIST policy to `blocked` in one batch. |
+| [`updateComposite`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/updateComposite) | `0xbfe142c0` | Replaces a composite policy's child-policy set in full with `childPolicyIds`. |
+| [`isAuthorized`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/isAuthorized) | `0x55a1179e` | Returns whether `account` is authorized under `policyId`. Never reverts; unknown |
+| [`policyExists`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/policyExists) | `0x330f5637` | Returns whether `policyId` is a built-in sentinel or a previously-assigned custom ID. Never reverts. |
+| [`policyAdmin`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/policyAdmin) | `0x09dd0a47` | Returns the current admin of `policyId`, or `address(0)` for built-in sentinels, |
+| [`pendingPolicyAdmin`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/pendingPolicyAdmin) | `0x017548b7` | Returns the currently-staged pending admin for `policyId`, or `address(0)` when |
+| [`compositePolicyChildIds`](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/compositePolicyChildIds) | `0x7c40df74` | Returns the child-policy set of the composite `policyId`. |
+
+## Events
+
+| Event | Topic0 | Summary |
+|---|---|---|
+| `PolicyCreated` | `0xdc870ce85be577234b8548f42b93f84bbff6d0c1f38ee725c809c49932a13885` | A new policy was created. |
+| `PolicyAdminStaged` | `0xdbf3b34a4c956c56ca05cd4b8f9293a4347ad61994445a4b89817d4a19561136` | A new admin was staged. `pendingAdmin == address(0)` clears a prior nomination. |
+| `PolicyAdminUpdated` | `0x98925cfb1bc09c5b43dd0dd56d3d95aa04fb3300927580cc588c3f5dd58c15e1` | The active admin changed. `newAdmin == address(0)` indicates renunciation; |
+| `AllowlistUpdated` | `0x18c46532f90187ba11e436e21da087b684801d7f0787f2043f26f079c91e9ef0` | One or more accounts had their ALLOWLIST membership set to `allowed` in a single batch. |
+| `BlocklistUpdated` | `0x2ff63c102b1b9fd7f5d39f83039c5d6aaf50a414a4f2def2704e41be2628f1e3` | One or more accounts had their BLOCKLIST membership set to `blocked` in a single batch. |
+| `CompositePolicyUpdated` | `0x4ff6adaab31b0df87aa7b8b7320c52b8b3b5eede3bf28a6baaaa8b8b7e1d6363` | A composite policy's child set was set or replaced in full with `childPolicyIds`. Emitted |
+
+## Errors
+
+| Error | Selector | Summary |
+|---|---|---|
+| `NonPayable` | `0x6fb1b0e9` | ETH was attached to a call targeting a nonpayable policy registry selector. |
+| `Unauthorized` | `0x82b42900` | Caller is not the admin required by the attempted operation. |
+| `PolicyNotFound` | `0x720caa4f` | The referenced policy ID does not exist. |
+| `IncompatiblePolicyType` | `0xf1011ef5` | The operation is incompatible with the policy's type. |
+| `ZeroAddress` | `0xd92e233d` | A required address argument was the zero address. |
+| `BatchSizeTooLarge` | `0x083e2f67` | A membership batch exceeded the registry limit. |
+| `NoPendingAdmin` | `0xb4539afa` | `finalizeUpdateAdmin` was called with no pending admin staged. |
+| `ChildPoliciesOutsideOfRange` | `0xcbdee0f6` | A composite policy was created or updated with a child-policy count outside the |
+| `InvalidChildPolicy` | `0x46508ef6` | Composite policies are not simple policies. Child policies must be existing |
+
+
+
+
+
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/compositePolicyChildIds.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/compositePolicyChildIds.mdx
new file mode 100644
index 000000000..8b3707a6a
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/compositePolicyChildIds.mdx
@@ -0,0 +1,49 @@
+---
+title: "IPolicyRegistry.compositePolicyChildIds"
+description: "Generated B20 reference for compositePolicyChildIds(uint64)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/policies-and-scopes)
+
+## Signature
+
+```solidity
+function compositePolicyChildIds(uint64 policyId) external view returns (uint64[] memory);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x7c40df74` |
+| Canonical signature | `compositePolicyChildIds(uint64)` |
+
+## Description
+
+Returns the child-policy set of the composite `policyId`.
+Dev: Child-policies are listed in the order they were last written.
+Dev: Returns an empty array for simple policies, built-in sentinels, unknown IDs, and
+malformed IDs. Never reverts.
+Dev: An empty return unambiguously means "not a composite".
+Dev: The registry preserves the caller's ordering verbatim and neither sorts nor
+de-duplicates.
+Param: policyId Policy to query.
+Return: Child policy IDs, or an empty array.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+This is part of the singleton PolicyRegistry surface used by B20 policy scopes.
+
+## Example
+
+```solidity
+IPolicyRegistry(target).compositePolicyChildIds(arg0);
+```
+
+## Related
+
+- [IPolicyRegistry reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/createCompositePolicy.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/createCompositePolicy.mdx
new file mode 100644
index 000000000..16f3da2db
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/createCompositePolicy.mdx
@@ -0,0 +1,55 @@
+---
+title: "IPolicyRegistry.createCompositePolicy"
+description: "Generated B20 reference for createCompositePolicy(address,PolicyType,uint64[])."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/policies-and-scopes)
+
+## Signature
+
+```solidity
+function createCompositePolicy(address admin, PolicyType policyType, uint64[] calldata childPolicyIds) external returns (uint64 newPolicyId);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xc341f3f0` |
+| Canonical signature | `createCompositePolicy(address,PolicyType,uint64[])` |
+
+## Description
+
+Creates a new composite policy that combines existing simple policies under a logic
+gate.
+Dev: Child policies must be simple policies (ALLOWLIST or BLOCKLIST), never another composite.
+The child-policy set is capped at 4.
+Dev: Reverts with `IncompatiblePolicyType` when `policyType` is not UNION or INTERSECT.
+Dev: Reverts with `ZeroAddress` when `admin` is `address(0)`.
+Dev: Reverts with `ChildPoliciesOutsideOfRange(2, 4)` when `childPolicyIds.length` is not in `[2, 4]`.
+Dev: Reverts with `PolicyNotFound` when any child policy does not exist.
+Dev: Reverts with `InvalidChildPolicy` when any child policy is not a simple policy or a built-in policy.
+Dev: Panics with arithmetic overflow (Panic 0x11) when the policy counter has reached its maximum value.
+Param: admin Initial admin authorized to update child policies and transfer or renounce
+administration.
+Param: policyType UNION or INTERSECT.
+Param: childPolicyIds Existing simple policy IDs to combine.
+Return: newPolicyId The newly assigned composite policy ID.
+
+## Access control
+
+Permissionless creation, but state-changing registry calls require the feature to be active.
+
+## Policy interaction
+
+This is part of the singleton PolicyRegistry surface used by B20 policy scopes.
+
+## Example
+
+```solidity
+IPolicyRegistry(target).createCompositePolicy(arg0, arg1, arg2);
+```
+
+## Related
+
+- [IPolicyRegistry reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/createPolicy.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/createPolicy.mdx
new file mode 100644
index 000000000..24f4ad072
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/createPolicy.mdx
@@ -0,0 +1,46 @@
+---
+title: "IPolicyRegistry.createPolicy"
+description: "Generated B20 reference for createPolicy(address,PolicyType)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/policies-and-scopes)
+
+## Signature
+
+```solidity
+function createPolicy(address admin, PolicyType policyType) external returns (uint64 newPolicyId);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xe494a1f6` |
+| Canonical signature | `createPolicy(address,PolicyType)` |
+
+## Description
+
+Creates a new simple policy with no initial members. Permissionless.
+Dev: Reverts with `ZeroAddress` when `admin` is `address(0)`.
+Dev: Reverts with `IncompatiblePolicyType` when `policyType` is a composite gate.
+Param: admin Initial admin authorized to modify membership and transfer or renounce administration.
+Param: policyType BLOCKLIST or ALLOWLIST.
+Return: newPolicyId The newly assigned policy ID.
+
+## Access control
+
+Permissionless creation, but state-changing registry calls require the feature to be active.
+
+## Policy interaction
+
+This is part of the singleton PolicyRegistry surface used by B20 policy scopes.
+
+## Example
+
+```solidity
+uint64 policyId = StdPrecompiles.POLICY_REGISTRY.createPolicy(admin, IPolicyRegistry.PolicyType.ALLOWLIST);
+```
+
+## Related
+
+- [IPolicyRegistry reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/createPolicyWithAccounts.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/createPolicyWithAccounts.mdx
new file mode 100644
index 000000000..f32e9fbae
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/createPolicyWithAccounts.mdx
@@ -0,0 +1,49 @@
+---
+title: "IPolicyRegistry.createPolicyWithAccounts"
+description: "Generated B20 reference for createPolicyWithAccounts(address,PolicyType,address[])."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/policies-and-scopes)
+
+## Signature
+
+```solidity
+function createPolicyWithAccounts(address admin, PolicyType policyType, address[] calldata accounts) external returns (uint64 newPolicyId);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xffd4931c` |
+| Canonical signature | `createPolicyWithAccounts(address,PolicyType,address[])` |
+
+## Description
+
+Creates a new simple policy seeded with `accounts` as initial members. Permissionless.
+Dev: Reverts with `ZeroAddress` when `admin` is `address(0)`. Takes precedence over `BatchSizeTooLarge`.
+Dev: Reverts with `IncompatiblePolicyType` when `policyType` is a composite policyType.
+Dev: Reverts with `BatchSizeTooLarge` when `accounts.length` exceeds the registry limit.
+Dev: Panics with arithmetic overflow (Panic 0x11) when the policy counter has reached its maximum value.
+Param: admin Initial admin authorized to modify membership and transfer or renounce administration.
+Param: policyType BLOCKLIST or ALLOWLIST.
+Param: accounts Initial member set.
+Return: newPolicyId The newly assigned policy ID.
+
+## Access control
+
+Permissionless creation, but state-changing registry calls require the feature to be active.
+
+## Policy interaction
+
+This is part of the singleton PolicyRegistry surface used by B20 policy scopes.
+
+## Example
+
+```solidity
+uint64 policyId = StdPrecompiles.POLICY_REGISTRY.createPolicyWithAccounts(admin, IPolicyRegistry.PolicyType.ALLOWLIST, accounts);
+```
+
+## Related
+
+- [IPolicyRegistry reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/finalizeUpdateAdmin.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/finalizeUpdateAdmin.mdx
new file mode 100644
index 000000000..35dde88e2
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/finalizeUpdateAdmin.mdx
@@ -0,0 +1,45 @@
+---
+title: "IPolicyRegistry.finalizeUpdateAdmin"
+description: "Generated B20 reference for finalizeUpdateAdmin(uint64)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/policies-and-scopes)
+
+## Signature
+
+```solidity
+function finalizeUpdateAdmin(uint64 policyId) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x33031a9c` |
+| Canonical signature | `finalizeUpdateAdmin(uint64)` |
+
+## Description
+
+Completes a two-step admin transfer. Promotes the caller to active admin and clears the pending slot.
+Dev: Reverts with `PolicyNotFound` when `policyId` does not exist.
+Dev: Reverts with `NoPendingAdmin` when no transfer is in flight.
+Dev: Reverts with `Unauthorized` when the caller is not the staged pending admin.
+Param: policyId Policy whose admin transfer is being finalized.
+
+## Access control
+
+Callable by the policy admin for the target policy.
+
+## Policy interaction
+
+This is part of the singleton PolicyRegistry surface used by B20 policy scopes.
+
+## Example
+
+```solidity
+IPolicyRegistry(target).finalizeUpdateAdmin(arg0);
+```
+
+## Related
+
+- [IPolicyRegistry reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/isAuthorized.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/isAuthorized.mdx
new file mode 100644
index 000000000..e2f58cc3e
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/isAuthorized.mdx
@@ -0,0 +1,47 @@
+---
+title: "IPolicyRegistry.isAuthorized"
+description: "Generated B20 reference for isAuthorized(uint64,address)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/policies-and-scopes)
+
+## Signature
+
+```solidity
+function isAuthorized(uint64 policyId, address account) external view returns (bool);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x55a1179e` |
+| Canonical signature | `isAuthorized(uint64,address)` |
+
+## Description
+
+Returns whether `account` is authorized under `policyId`. Never reverts; unknown
+or malformed IDs collapse to empty-member-set semantics (ALLOWLIST -> false,
+BLOCKLIST -> true).
+Dev: Callers that store policy IDs MUST validate `policyExists(policyId)` at write time.
+Param: policyId Policy to query.
+Param: account Account to check.
+Return: Whether `account` is authorized.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+This is part of the singleton PolicyRegistry surface used by B20 policy scopes.
+
+## Example
+
+```solidity
+bool ok = StdPrecompiles.POLICY_REGISTRY.isAuthorized(policyId, account);
+```
+
+## Related
+
+- [IPolicyRegistry reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/pendingPolicyAdmin.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/pendingPolicyAdmin.mdx
new file mode 100644
index 000000000..3d2d31c38
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/pendingPolicyAdmin.mdx
@@ -0,0 +1,45 @@
+---
+title: "IPolicyRegistry.pendingPolicyAdmin"
+description: "Generated B20 reference for pendingPolicyAdmin(uint64)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/policies-and-scopes)
+
+## Signature
+
+```solidity
+function pendingPolicyAdmin(uint64 policyId) external view returns (address);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x017548b7` |
+| Canonical signature | `pendingPolicyAdmin(uint64)` |
+
+## Description
+
+Returns the currently-staged pending admin for `policyId`, or `address(0)` when
+no transfer is in flight or for built-in sentinels, unknown IDs, and malformed IDs.
+Never reverts.
+Param: policyId Policy to query.
+Return: Pending admin, or `address(0)`.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+This is part of the singleton PolicyRegistry surface used by B20 policy scopes.
+
+## Example
+
+```solidity
+IPolicyRegistry(target).pendingPolicyAdmin(arg0);
+```
+
+## Related
+
+- [IPolicyRegistry reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/policyAdmin.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/policyAdmin.mdx
new file mode 100644
index 000000000..4f1e13e41
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/policyAdmin.mdx
@@ -0,0 +1,44 @@
+---
+title: "IPolicyRegistry.policyAdmin"
+description: "Generated B20 reference for policyAdmin(uint64)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/policies-and-scopes)
+
+## Signature
+
+```solidity
+function policyAdmin(uint64 policyId) external view returns (address);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x09dd0a47` |
+| Canonical signature | `policyAdmin(uint64)` |
+
+## Description
+
+Returns the current admin of `policyId`, or `address(0)` for built-in sentinels,
+renounced policies, unknown IDs, and malformed IDs. Never reverts.
+Param: policyId Policy to query.
+Return: Current admin, or `address(0)`.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+This is part of the singleton PolicyRegistry surface used by B20 policy scopes.
+
+## Example
+
+```solidity
+IPolicyRegistry(target).policyAdmin(arg0);
+```
+
+## Related
+
+- [IPolicyRegistry reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/policyExists.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/policyExists.mdx
new file mode 100644
index 000000000..aa9df727c
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/policyExists.mdx
@@ -0,0 +1,43 @@
+---
+title: "IPolicyRegistry.policyExists"
+description: "Generated B20 reference for policyExists(uint64)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/policies-and-scopes)
+
+## Signature
+
+```solidity
+function policyExists(uint64 policyId) external view returns (bool);
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x330f5637` |
+| Canonical signature | `policyExists(uint64)` |
+
+## Description
+
+Returns whether `policyId` is a built-in sentinel or a previously-assigned custom ID. Never reverts.
+Param: policyId Policy to query.
+Return: Whether the policy exists.
+
+## Access control
+
+Read-only or ERC-20-standard access rules unless the NatSpec states otherwise.
+
+## Policy interaction
+
+This is part of the singleton PolicyRegistry surface used by B20 policy scopes.
+
+## Example
+
+```solidity
+IPolicyRegistry(target).policyExists(arg0);
+```
+
+## Related
+
+- [IPolicyRegistry reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/renounceAdmin.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/renounceAdmin.mdx
new file mode 100644
index 000000000..f6d453d0d
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/renounceAdmin.mdx
@@ -0,0 +1,45 @@
+---
+title: "IPolicyRegistry.renounceAdmin"
+description: "Generated B20 reference for renounceAdmin(uint64)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/policies-and-scopes)
+
+## Signature
+
+```solidity
+function renounceAdmin(uint64 policyId) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xefdb7fa3` |
+| Canonical signature | `renounceAdmin(uint64)` |
+
+## Description
+
+Permanently relinquishes administration of `policyId`. The member set is frozen
+and the policy can never be re-administered; `isAuthorized` queries continue to work.
+Dev: Reverts with `PolicyNotFound` when `policyId` does not exist.
+Dev: Reverts with `Unauthorized` when the caller is not the current admin.
+Param: policyId Policy whose administration is being renounced.
+
+## Access control
+
+Callable by the policy admin for the target policy.
+
+## Policy interaction
+
+This is part of the singleton PolicyRegistry surface used by B20 policy scopes.
+
+## Example
+
+```solidity
+IPolicyRegistry(target).renounceAdmin(arg0);
+```
+
+## Related
+
+- [IPolicyRegistry reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/stageUpdateAdmin.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/stageUpdateAdmin.mdx
new file mode 100644
index 000000000..c2a257fb0
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/stageUpdateAdmin.mdx
@@ -0,0 +1,46 @@
+---
+title: "IPolicyRegistry.stageUpdateAdmin"
+description: "Generated B20 reference for stageUpdateAdmin(uint64,address)."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/policies-and-scopes)
+
+## Signature
+
+```solidity
+function stageUpdateAdmin(uint64 policyId, address newAdmin) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x1d7ae695` |
+| Canonical signature | `stageUpdateAdmin(uint64,address)` |
+
+## Description
+
+Stages a proposed new admin for `policyId`. The active admin does not change
+until `pendingAdmin` calls `finalizeUpdateAdmin`.
+Dev: Reverts with `PolicyNotFound` when `policyId` does not exist.
+Dev: Reverts with `Unauthorized` when the caller is not the current admin.
+Param: policyId Policy whose admin is being staged.
+Param: newAdmin Proposed new admin, or `address(0)` to clear any pending nomination.
+
+## Access control
+
+Callable by the policy admin for the target policy.
+
+## Policy interaction
+
+This is part of the singleton PolicyRegistry surface used by B20 policy scopes.
+
+## Example
+
+```solidity
+IPolicyRegistry(target).stageUpdateAdmin(arg0, arg1);
+```
+
+## Related
+
+- [IPolicyRegistry reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/updateAllowlist.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/updateAllowlist.mdx
new file mode 100644
index 000000000..7a3ac068d
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/updateAllowlist.mdx
@@ -0,0 +1,48 @@
+---
+title: "IPolicyRegistry.updateAllowlist"
+description: "Generated B20 reference for updateAllowlist(uint64,bool,address[])."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/policies-and-scopes)
+
+## Signature
+
+```solidity
+function updateAllowlist(uint64 policyId, bool allowed, address[] calldata accounts) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x3388fb5b` |
+| Canonical signature | `updateAllowlist(uint64,bool,address[])` |
+
+## Description
+
+Sets `accounts` membership in an ALLOWLIST policy to `allowed` in one batch.
+Dev: Reverts with `PolicyNotFound` when `policyId` does not exist.
+Dev: Reverts with `IncompatiblePolicyType` when the policy is not ALLOWLIST.
+Dev: Reverts with `Unauthorized` when the caller is not the current admin.
+Dev: Reverts with `BatchSizeTooLarge` when `accounts.length` exceeds the registry limit.
+Param: policyId Policy to update.
+Param: allowed Membership state to apply to every account in the batch.
+Param: accounts Accounts to update.
+
+## Access control
+
+Callable by the policy admin for the target policy.
+
+## Policy interaction
+
+This is part of the singleton PolicyRegistry surface used by B20 policy scopes.
+
+## Example
+
+```solidity
+IPolicyRegistry(target).updateAllowlist(arg0, arg1, arg2);
+```
+
+## Related
+
+- [IPolicyRegistry reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/updateBlocklist.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/updateBlocklist.mdx
new file mode 100644
index 000000000..af43081d4
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/updateBlocklist.mdx
@@ -0,0 +1,48 @@
+---
+title: "IPolicyRegistry.updateBlocklist"
+description: "Generated B20 reference for updateBlocklist(uint64,bool,address[])."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/policies-and-scopes)
+
+## Signature
+
+```solidity
+function updateBlocklist(uint64 policyId, bool blocked, address[] calldata accounts) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0x5c4e51b8` |
+| Canonical signature | `updateBlocklist(uint64,bool,address[])` |
+
+## Description
+
+Sets `accounts` membership in a BLOCKLIST policy to `blocked` in one batch.
+Dev: Reverts with `PolicyNotFound` when `policyId` does not exist.
+Dev: Reverts with `IncompatiblePolicyType` when the policy is not BLOCKLIST.
+Dev: Reverts with `Unauthorized` when the caller is not the current admin.
+Dev: Reverts with `BatchSizeTooLarge` when `accounts.length` exceeds the registry limit.
+Param: policyId Policy to update.
+Param: blocked Membership state to apply to every account in the batch.
+Param: accounts Accounts to update.
+
+## Access control
+
+Callable by the policy admin for the target policy.
+
+## Policy interaction
+
+This is part of the singleton PolicyRegistry surface used by B20 policy scopes.
+
+## Example
+
+```solidity
+IPolicyRegistry(target).updateBlocklist(arg0, arg1, arg2);
+```
+
+## Related
+
+- [IPolicyRegistry reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)
diff --git a/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/updateComposite.mdx b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/updateComposite.mdx
new file mode 100644
index 000000000..b5c05a646
--- /dev/null
+++ b/docs/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry/updateComposite.mdx
@@ -0,0 +1,52 @@
+---
+title: "IPolicyRegistry.updateComposite"
+description: "Generated B20 reference for updateComposite(uint64,uint64[])."
+---
+
+
+[Related concept](/base-chain/specs/upgrades/beryl/b20/specification/concepts/policies-and-scopes)
+
+## Signature
+
+```solidity
+function updateComposite(uint64 policyId, uint64[] calldata childPolicyIds) external;
+```
+
+| Field | Value |
+|---|---|
+| Selector | `0xbfe142c0` |
+| Canonical signature | `updateComposite(uint64,uint64[])` |
+
+## Description
+
+Replaces a composite policy's child-policy set in full with `childPolicyIds`.
+Dev: Reverts with `PolicyNotFound` when `policyId` does not exist.
+Dev: Reverts with `IncompatiblePolicyType` when `policyId` is not a composite (UNION or INTERSECT).
+Dev: Reverts with `Unauthorized` when the caller is not the current admin. A renounced composite
+(admin `address(0)`) can never be updated.
+Dev: Reverts with `ChildPoliciesOutsideOfRange(2, 4)` when `childPolicyIds.length` is not in `[2, 4]`;
+there is no clear-the-list path (the composite child-policy range, not the 64-account batch limit).
+Dev: Reverts with `PolicyNotFound` when any child policy does not exist.
+Dev: Reverts with `InvalidChildPolicy` when any child policy is itself a composite
+(not a simple policy).
+Param: policyId Composite policy to update.
+Param: childPolicyIds Complete new set of existing simple policy IDs.
+
+## Access control
+
+Callable by the policy admin for the target policy.
+
+## Policy interaction
+
+This is part of the singleton PolicyRegistry surface used by B20 policy scopes.
+
+## Example
+
+```solidity
+IPolicyRegistry(target).updateComposite(arg0, arg1);
+```
+
+## Related
+
+- [IPolicyRegistry reference](/base-chain/specs/upgrades/beryl/b20/specification/reference/interfaces/IPolicyRegistry)
+- [Constants & addresses](/base-chain/specs/upgrades/beryl/b20/specification/reference/constants-and-addresses)