> ## Documentation Index
> Fetch the complete documentation index at: https://base-a060aa97-docs-sync-code-change-868d513.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Changelog

> Per-hardfork, per-feature migration notes for the B20 token standard, newest first, including new methods, deprecations, and activation dates.

Per-hardfork, per-feature migration notes for the [B20 token standard](/specifications/b20/specification-overview). Each Cobalt entry is a focused, code-forward changelog for one scoped feature change that crosses a hardfork boundary. Newest first.

<Note>
  B20 method and event signatures are part of the chain's consensus surface. Existing selectors and behavior do not change; the standard grows by addition.
</Note>

## Hardfork Ordinals

| Ordinal | Hardfork | Status   |
| ------- | -------- | -------- |
| `01`    | Beryl    | Live     |
| `02`    | Cobalt   | Upcoming |

## [Cobalt](/upgrades/cobalt/overview) (Upcoming) — Ordinal 02

| Product(s)                | Change                                    | Affected interfaces     | Entry                                                                                                     |
| ------------------------- | ----------------------------------------- | ----------------------- | --------------------------------------------------------------------------------------------------------- |
| B20 Asset                 | Schedule Multiplier Updates (ERC-8056)    | `IB20Asset`             | [Multiplier / ERC-8056](/base-chain/specs/reference/b20/changelog/02-cobalt-b20asset-multiplier)          |
| B20 Asset, B20 Stablecoin | Seize surface + `burnBlocked` deprecation | `IB20` (shared surface) | [Seize surface](/base-chain/specs/reference/b20/changelog/02-cobalt-b20-seize)                            |
| PolicyRegistry            | Composite Policies (UNION / INTERSECT)    | `IPolicyRegistry`       | [Composite policies](/base-chain/specs/reference/b20/changelog/02-cobalt-policyregistry-composite-policy) |

## [Beryl](/upgrades/beryl/overview) — Initial Release

| Network      | Activated  |
| ------------ | ---------- |
| Base mainnet | 2026-06-25 |
| Base Sepolia | 2026-06-18 |

Shipped with the [Beryl upgrade](/upgrades/beryl/overview).

**Added**

* The B20 standard as a native precompile: a superset of ERC-20 with full selector and behavior parity for `transfer`, `transferFrom`, `approve`, `allowance`, `balanceOf`, `totalSupply`, `name`, `symbol`, `decimals`, `Transfer`, and `Approval`
* [Role-based access control](/specifications/b20/specification-overview#roles-model) with built-in roles, user-defined roles in the role graph, and `renounceLastAdmin` for permanent admin-less operation
* [PolicyRegistry](/specifications/b20/specification-overview#policy-registry) singleton precompile with `BLOCKLIST`, `ALLOWLIST`, `UNION`, and `INTERSECT` policy types, two-step admin transfer, and the `ALWAYS_ALLOW` and `ALWAYS_BLOCK` built-ins
* [Six policy scopes](/specifications/b20/specification-overview#policy-integration) on every token, covering transfer sender, receiver, and executor, mint receiver, and seize holder and receiver
* [`seizeWithMemo`](/specifications/b20/specification-overview#seize) for compliance-driven balance transfers
* [Memo variants](/specifications/b20/specification-overview#memos) of transfer, transferFrom, mint, burn, and seize, emitting `Memo` immediately after the primary event
* [Granular pausing](/specifications/b20/specification-overview#pause) by `PausableFeature`: `TRANSFER`, `MINT`, `BURN`, and `SEIZE`
* [Optional supply caps](/specifications/b20/specification-overview#supply-cap), with `type(uint128).max` as the uncapped sentinel and maximum supply
* [ERC-2612 `permit`](/specifications/b20/specification-overview) with an EIP-712 domain at version `"1"`
* [ERC-7572 `contractURI`](/specifications/b20/specification-overview#contract-uri-erc-7572) and `METADATA_ROLE`-gated name, symbol, and URI updates
* [B20Factory](/specifications/b20/specification-overview#factory) singleton precompile with deterministic, variant-encoding addresses and `initCalls` bootstrap semantics
* ActivationRegistry gating for state-changing PolicyRegistry calls
* The [`ASSET` variant](/specifications/b20/specification-overview#asset): `OPERATOR_ROLE`, WAD-precision UI multipliers with scheduled and instant updates, announcements, `batchMint`, and issuer-defined extra metadata
* The [`STABLECOIN` variant](/specifications/b20/specification-overview#stablecoin): fixed 6 decimals and a `currency()` code set once at creation

**Deprecated**

* `burnBlocked` and `BURN_BLOCKED_ROLE`, retained for backwards compatibility. New seizure flows use `seizeWithMemo`.

<Warning>
  **Pooled-balance integrators:** `seizeWithMemo` and `burnBlocked` both allow funds to move out of a contract address without the regular transfer flow. This affects lending-protocol vaults, AMM pools, staking contracts, custodial wallets, and bridges — any system that maintains internal accounting against a single on-chain token balance. The mechanism acts at the pooling contract's address, not at individual depositor-share granularity, so the accounting impact falls on the pool as a whole.

  This is not a new risk. `burnBlocked` already allowed an issuer to zero a blocked address's balance through block, burn, and reissue elsewhere. `seizeWithMemo` does not expand who is exposed — it collapses that workaround into one call, redirects the balance instead of burning and reissuing it, and emits a dedicated `Seized` event. Both paths remain live.

  To check current exposure, read the policy IDs assigned to `SEIZE_HOLDER_POLICY` and `TRANSFER_SENDER_POLICY` using `token.policyId(...)` (`IB20.policyId`, `src/interfaces/IB20.sol`), then query the Policy Registry's `isAuthorized(policyId, account)` with the pooling contract's own address against each ID. If the contract is not authorized under the seize-holder policy, or is blocked under the transfer-sender policy, funds can be seized or burned from that vault balance under the current configuration. This check is point-in-time only — an issuer can later change either slot with `updatePolicy`, so "not seizable today" is not a durable guarantee.
</Warning>
