From 8a6c925b2e0ff1d9a2cbb0bc525315975620f8ff Mon Sep 17 00:00:00 2001 From: sohey Date: Tue, 23 Jun 2026 20:31:59 +0200 Subject: [PATCH 1/7] added design and updated agents.md --- docs/apps/guides/accept-b20-payments.mdx | 2 +- docs/base-chain/specs/upgrades/beryl/b20.mdx | 16 ++++++++++++++-- docs/get-started/launch-b20-token.mdx | 4 +++- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/docs/apps/guides/accept-b20-payments.mdx b/docs/apps/guides/accept-b20-payments.mdx index d6dae4e18..2661c81fd 100644 --- a/docs/apps/guides/accept-b20-payments.mdx +++ b/docs/apps/guides/accept-b20-payments.mdx @@ -14,7 +14,7 @@ This uses your configured viem `walletClient` and `publicClient`. It reads the t ```js import { parseUnits, stringToHex, hexToString, parseEventLogs } from 'viem'; -const TOKEN = '0xB20f...'; // the B20 token you accept +const TOKEN = '0xB200...'; // the B20 token you accept const MERCHANT = '0x...'; // where payments land const ABI = [ diff --git a/docs/base-chain/specs/upgrades/beryl/b20.mdx b/docs/base-chain/specs/upgrades/beryl/b20.mdx index 2f62086be..82b607775 100644 --- a/docs/base-chain/specs/upgrades/beryl/b20.mdx +++ b/docs/base-chain/specs/upgrades/beryl/b20.mdx @@ -3,7 +3,7 @@ title: "B20 Native Token Standard" description: "B20 is Base's native token standard - designed for stablecoin issuers, real-world asset (RWA) and equity issuers, and long-tail token creators." --- -B20 is the Base ecosystem's own version of [ERC-20](https://eips.ethereum.org/EIPS/eip-20). It ships with a built-in compliance toolkit: transfer policies, freeze-and-seize, role-based access control, memos, and supply caps. The full interface specs are available in the [Base Standard Library](https://github.com/base/base-std) repository. +B20 is the Base ecosystem's own version of [ERC-20](https://eips.ethereum.org/EIPS/eip-20). It ships with a built-in compliance toolkit: transfer policies, freeze-and-seize, role-based access control, memos, and supply caps. The full interface specs are available in the [Base Standard Library](https://github.com/base/base-std/tree/main) repository. B20 supports two variants: @@ -17,9 +17,11 @@ B20 supports two variants: B20 tokens are implemented as **Rust precompiles** rather than EVM smart contracts, making them faster, cheaper, and more native to the chain. All tokens are deployed via the singleton B20Factory precompile. -B20 implements the full ERC-20 standard surface with complete selector parity - it is a drop-in replacement for existing tooling and integrations. +B20 implements the **full ERC-20 standard surface** - every ERC-20 call (`transfer`, `transferFrom`, `approve`, `balanceOf`, `allowance`, and the standard events) works unchanged, so existing ERC-20 tooling and integrations are drop-in compatible. +B20 is an **extension** of ERC-20, not a 1:1 mapping. It adds entrypoints that have no ERC-20 equivalent (memos, mint/burn, policy gating, granular pause, and ERC-2612 `permit`), so every ERC-20 method exists on B20 but not every B20 method exists on ERC-20. For the complete ABIs, see the [interface definitions](https://github.com/base/base-std/tree/main/src/interfaces) in the Base Standard Library. + ## Roles Model B20 role-based access control extends OpenZeppelin `AccessControl` with a fixed set of roles and one behavioral override on admin renunciation. @@ -170,6 +172,16 @@ B20 implements ERC-2612 (signed approvals) using an EIP-712 domain shaped as `(n All B20 tokens are created through the singleton B20Factory precompile via `createB20(variant, salt, params, initCalls)`. +The B20Factory lives at a fixed precompile address: + +```text +0xB20f000000000000000000000000000000000000 +``` + + +This is a precompile, not a deployed contract, so the address is identical on every network where B20 is active - mainnet, Base Sepolia, Vibenet, and local `base-anvil`. In `base-std` it is exposed as `StdPrecompiles.B20_FACTORY`. + + | Parameter | Description | |-----------|-------------| | `variant` | `ASSET` or `STABLECOIN` | diff --git a/docs/get-started/launch-b20-token.mdx b/docs/get-started/launch-b20-token.mdx index 2de35e341..c5b9ac4e0 100644 --- a/docs/get-started/launch-b20-token.mdx +++ b/docs/get-started/launch-b20-token.mdx @@ -29,6 +29,8 @@ base-forge init b20-quickstart && cd b20-quickstart base-forge install base/base-std --no-git ``` +This installs the [Base Standard Library](https://github.com/base/base-std/tree/main), which provides the B20 interfaces, constants, and encoding helpers used below. + Add the remappings and the `base = true` flag to `foundry.toml` (under `[profile.default]`). `base = true` tells Base's `forge` build to run the B20 precompiles inside its EVM, so the deploy script's local simulation can call the factory: ```toml foundry.toml theme={null} @@ -211,7 +213,7 @@ The factory's single entry point is `createB20(variant, salt, params, initCalls) base-forge script script/CreateToken.s.sol --rpc-url $RPC_URL --private-key $PRIVATE_KEY --broadcast ``` - On success the script logs the new token's address. The factory's address starts `0xB20f...`. The tokens it creates start `0xB200...`: + On success the script logs the new token's address. The factory is the fixed precompile at `0xB20f000000000000000000000000000000000000` (the same on every network); the tokens it creates start `0xB200...`: If you see `TokenAlreadyExists`, the salt `keccak256("my-first-b20")` is already registered on this network or anvil instance. Either restart `base-anvil` for a fresh state, or change the salt in the script to a unique value. From b244b5a57c2b0468810007377a097e35a27269d2 Mon Sep 17 00:00:00 2001 From: sohey Date: Tue, 23 Jun 2026 20:31:59 +0200 Subject: [PATCH 2/7] chore: regenerate docs/AGENTS.md (post-commit of 8a6c925) --- docs/AGENTS.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/AGENTS.md b/docs/AGENTS.md index f08937d18..1aa41788d 100644 --- a/docs/AGENTS.md +++ b/docs/AGENTS.md @@ -42,10 +42,10 @@ npx skills add base/base-skills |agents:index,quickstart |agents/guides:batch-calls,check-balance,index,send-tokens,sign-messages,swap-tokens,view-history,x402-payments |agents/plugins:custom-plugins,index -|agents/plugins/native:aerodrome,avantis,bankr,index,moonwell,morpho,uniswap,virtuals +|agents/plugins/native:aerodrome,avantis,balancer,bankr,bitrefill,brickken,clawnch,flaunch,gmgn,hydrex,index,kyberswap,moonwell,morpho,o1-exchange,opensea,printr,uniswap,venice,virtuals,yo |agents/skills:SKILL -|agents/skills/plugins:aerodrome,avantis,bankr,moonwell,morpho,uniswap,virtuals -|agents/skills/references:approval-mode,batch-calls,custom-plugins,install,tone +|agents/skills/plugins:aerodrome,avantis,balancer,bankr,bitrefill,brickken,clawnch,flaunch,gmgn,hydrex,kyberswap,moonwell,morpho,o1-exchange,opensea,printr,uniswap,venice,virtuals,yo +|agents/skills/references:approval-mode,batch-calls,custom-plugins,install,plugin-spec,tone |apps:index |apps/builder-codes:agent-developers,app-developers,builder-codes,wallet-developers |apps/growth:rewards From fb0caab5b7ecad45bebc3568ea1b4ac6b6f2231b Mon Sep 17 00:00:00 2001 From: roethke Date: Tue, 23 Jun 2026 13:43:19 -0700 Subject: [PATCH 3/7] add precompile addresses section --- docs/base-chain/specs/upgrades/beryl/b20.mdx | 22 ++++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/base-chain/specs/upgrades/beryl/b20.mdx b/docs/base-chain/specs/upgrades/beryl/b20.mdx index 82b607775..ae3276d3f 100644 --- a/docs/base-chain/specs/upgrades/beryl/b20.mdx +++ b/docs/base-chain/specs/upgrades/beryl/b20.mdx @@ -170,17 +170,7 @@ B20 implements ERC-2612 (signed approvals) using an EIP-712 domain shaped as `(n ## Factory -All B20 tokens are created through the singleton B20Factory precompile via `createB20(variant, salt, params, initCalls)`. - -The B20Factory lives at a fixed precompile address: - -```text -0xB20f000000000000000000000000000000000000 -``` - - -This is a precompile, not a deployed contract, so the address is identical on every network where B20 is active - mainnet, Base Sepolia, Vibenet, and local `base-anvil`. In `base-std` it is exposed as `StdPrecompiles.B20_FACTORY`. - +All B20 tokens are created through the singleton B20Factory precompile via `createB20(variant, salt, params, initCalls)`. In `base-std` it is exposed as `StdPrecompiles.B20_FACTORY`. | Parameter | Description | |-----------|-------------| @@ -254,3 +244,13 @@ The fixed-decimals, fiat-backed carveout. Decimals are hard-wired to `6` and are Adds `currency()`, which returns an ISO-style currency code string (e.g. `"USD"`, `"EUR"`). The code is set once at creation via `B20StablecoinCreateParams.currency`, restricted to characters `A`-`Z` only. It is self-declared and not verified against any external registry. +## Precompile addresses + +These addresses are identical on every network where B20 is active (Mainnet, Base Sepolia, Vibenet, and local `base-anvil`). + +| Precompile | Address | +|---|---| +| [B20Factory](#factory) | `0xB20f000000000000000000000000000000000000` | +| Activation Registry | `0x8453000000000000000000000000000000000001` | +| [Policy Registry](#policy-registry) | `0x8453000000000000000000000000000000000002` | + From 5a69a4301b3debf9381a824c44376bc1bc7bde0c Mon Sep 17 00:00:00 2001 From: roethke Date: Tue, 23 Jun 2026 15:12:44 -0700 Subject: [PATCH 4/7] add x-referencing, variant table --- docs/base-chain/specs/upgrades/beryl/b20.mdx | 11 ++++++++++- docs/get-started/launch-b20-token.mdx | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/base-chain/specs/upgrades/beryl/b20.mdx b/docs/base-chain/specs/upgrades/beryl/b20.mdx index ae3276d3f..3af65bc87 100644 --- a/docs/base-chain/specs/upgrades/beryl/b20.mdx +++ b/docs/base-chain/specs/upgrades/beryl/b20.mdx @@ -5,6 +5,8 @@ description: "B20 is Base's native token standard - designed for stablecoin issu B20 is the Base ecosystem's own version of [ERC-20](https://eips.ethereum.org/EIPS/eip-20). It ships with a built-in compliance toolkit: transfer policies, freeze-and-seize, role-based access control, memos, and supply caps. The full interface specs are available in the [Base Standard Library](https://github.com/base/base-std/tree/main) repository. +To deploy your first B20 token, see the [Launch a B20 Token](/get-started/launch-b20-token) quickstart. + B20 supports two variants: | Variant | Decimals | Additional Features | @@ -189,7 +191,7 @@ B20 addresses are deterministic and encode the variant directly: [10-byte B20 prefix][1-byte variant][9-byte keccak256(deployer, salt)] ``` -The variant is recoverable from the address alone without an RPC call. Helper functions `getB20Address(variant, deployer, salt)`, `isB20(addr)`, and `isB20Initialized(addr)` are available on the factory. +The variant is recoverable from the address alone without an RPC call — inspect byte 10 (zero-indexed) to identify the token type. Helper functions `getB20Address(variant, deployer, salt)`, `isB20(addr)`, and `isB20Initialized(addr)` are available on the factory. ### initCalls Semantics @@ -201,6 +203,13 @@ The variant is recoverable from the address alone without an RPC call. Helper fu ## Variants +Each variant is identified by a 1-byte value encoded directly in the token's address (see [Address Derivation](#address-derivation)): + +| Variant | Byte | +|---------|------| +| `ASSET` | `0x00` | +| `STABLECOIN` | `0x01` | + ### Asset The general-purpose variant for assets of all kinds. Decimals are configurable between 6 and 18 at deployment time and are immutable after creation. diff --git a/docs/get-started/launch-b20-token.mdx b/docs/get-started/launch-b20-token.mdx index c5b9ac4e0..3ca34abcb 100644 --- a/docs/get-started/launch-b20-token.mdx +++ b/docs/get-started/launch-b20-token.mdx @@ -5,7 +5,7 @@ description: "Launch a B20 token on Base by calling the B20 Factory precompile." B20 is an ERC-20 superset that runs as a native precompile on Base, which makes transfers cheaper and higher-throughput than a standard contract token while keeping full ERC-20 compatibility. Roles, supply caps, pausing, policy gating, memos, and `permit` are built into the chain. -A standard ERC-20 leaves that logic for you to build, audit, and maintain. With B20, you call the singleton **B20 Factory** to create a token, fully configured, in a single transaction. +A standard ERC-20 leaves that logic for you to build, audit, and maintain. With B20, you call the singleton [**B20 Factory**](/base-chain/specs/upgrades/beryl/b20#factory) to create a token, fully configured, in a single transaction. This guide creates an Asset token, mints its initial supply, and verifies the balance onchain. To accept the token as payment in an app, continue with [Accept B20 payments](/apps/guides/accept-b20-payments). From 6eea5b50325f43b4d65384b3fbc57bf3aef4c7f8 Mon Sep 17 00:00:00 2001 From: roethke Date: Tue, 23 Jun 2026 15:26:31 -0700 Subject: [PATCH 5/7] add mainnet tab, activation registry callout, remove flag --- docs/get-started/launch-b20-token.mdx | 52 ++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/docs/get-started/launch-b20-token.mdx b/docs/get-started/launch-b20-token.mdx index 3ca34abcb..9f6025676 100644 --- a/docs/get-started/launch-b20-token.mdx +++ b/docs/get-started/launch-b20-token.mdx @@ -15,13 +15,27 @@ You need **Base's Foundry build** (`base-forge`, `base-cast`, `base-anvil`). Ins ```bash Terminal theme={null} curl -L https://raw.githubusercontent.com/base/base-anvil/HEAD/foundryup/install | bash - base-foundryup --install v1.1.0 + base-foundryup ``` Standard `forge` cannot simulate calls to B20 precompile addresses (they hold no contract bytecode) and aborts with `call to non-contract address`. Base's `base-forge` registers the precompiles into its EVM. It installs alongside your existing Foundry toolchain without overwriting it — use `base-forge`, `base-cast`, and `base-anvil` for all commands in this guide. +## Verify the Activation Registry is enabled + + +**The Activation Registry must be enabled before you can deploy.** After the Beryl hardfork activates, the Activation Registry can take up to ~1 hour to be fully enabled. Attempting to deploy before it's ready will revert with `FeatureNotActivated`. Run the check for the variant you plan to deploy and confirm it returns `true` before proceeding: + + +```bash Terminal theme={null} +REG=0x8453000000000000000000000000000000000001 # Activation Registry precompile +RPC=https://mainnet.base.org # replace with your target network (e.g. https://sepolia.base.org, https://rpc.vibes.base.org) + +base-cast call $REG "isActivated(bytes32)(bool)" $(base-cast keccak "base.b20_asset") --rpc-url $RPC +base-cast call $REG "isActivated(bytes32)(bool)" $(base-cast keccak "base.b20_stablecoin") --rpc-url $RPC +``` + ## Set up your project ```bash Terminal theme={null} @@ -47,9 +61,38 @@ The interfaces compile with any Solidity `>=0.8.20 <0.9.0`. ## Choose a network -Pick a network with the B20 precompiles active, then create a `.env` **inside your `b20-quickstart` project directory**: +Pick a network with the B20 precompiles active, then create a `.env` **inside your `b20-quickstart` project directory**. For full network details, see [Connecting to Base](/base-chain/quickstart/connecting-to-base). + + | Setting | Value | + |---|---| + | RPC URL | `https://mainnet.base.org` | + | Chain ID | `8453` | + | Explorer | [basescan.org](https://basescan.org) | + + ```bash .env theme={null} + export RPC_URL="https://mainnet.base.org" + export PRIVATE_KEY="0x..." + export ACCOUNT_ADDRESS="0x..." + export CHAIN_ID="8453" + ``` + + + If you don't have an account, `base-cast wallet new` prints a fresh address and key. + + + Confirm your account has ETH for gas: + + ```bash Terminal theme={null} + source .env + base-cast balance $ACCOUNT_ADDRESS --rpc-url $RPC_URL + ``` + + + The command prints a non-zero balance. This account signs the deploy and the mint, and receives the minted supply. + + | Setting | Value | |---|---| @@ -279,10 +322,9 @@ In this guide you: * Minted supply * Verified the balance onchain -You did all of this without writing, deploying, or auditing a token contract. +All without writing, deploying, or auditing a token contract. ## Next steps * [Accept B20 payments in an app](/apps/guides/accept-b20-payments): wire this token into a checkout flow that tags each payment with an order ID and reconciles it from onchain events. -* Gate transfers or mints with PolicyRegistry policies, add granular pause, or manage roles. See the [B20 token standard](/base-chain/specs/upgrades/beryl/b20). -* Issue a stablecoin variant (fixed 6 decimals, immutable currency code). \ No newline at end of file +* Gate transfers or mints with PolicyRegistry policies, add granular pause, or manage roles. See the [B20 token standard](/base-chain/specs/upgrades/beryl/b20). \ No newline at end of file From bb25083a998110c9ee85e44f22a1c3d4fc7a4b64 Mon Sep 17 00:00:00 2001 From: roethke Date: Tue, 23 Jun 2026 15:38:54 -0700 Subject: [PATCH 6/7] link to base-anvil repo --- docs/get-started/launch-b20-token.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/get-started/launch-b20-token.mdx b/docs/get-started/launch-b20-token.mdx index 9f6025676..88af2d713 100644 --- a/docs/get-started/launch-b20-token.mdx +++ b/docs/get-started/launch-b20-token.mdx @@ -11,7 +11,7 @@ This guide creates an Asset token, mints its initial supply, and verifies the ba ## Before you begin -You need **Base's Foundry build** (`base-forge`, `base-cast`, `base-anvil`). Install it via `base-foundryup`: +You need **Base's Foundry build** (`base-forge`, `base-cast`, [`base-anvil`](https://github.com/base/base-anvil)). Install it via `base-foundryup`: ```bash Terminal theme={null} curl -L https://raw.githubusercontent.com/base/base-anvil/HEAD/foundryup/install | bash From a9cb4a2281ffc4e41b56e9f5b3f1553b833579fa Mon Sep 17 00:00:00 2001 From: roethke Date: Wed, 24 Jun 2026 10:38:56 -0700 Subject: [PATCH 7/7] docs: add ephemeral port range guidance to networking section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a Warning callout in the Egress tab explaining that operators using network ACLs (not stateful SGs) must open outbound ephemeral ports 32768–60999 to avoid response packets being silently dropped. Generated with Claude Code Co-Authored-By: Claude --- docs/base-chain/node-operators/run-a-base-node.mdx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/base-chain/node-operators/run-a-base-node.mdx b/docs/base-chain/node-operators/run-a-base-node.mdx index 4d36be28e..89efac9d2 100644 --- a/docs/base-chain/node-operators/run-a-base-node.mdx +++ b/docs/base-chain/node-operators/run-a-base-node.mdx @@ -53,6 +53,10 @@ Configure your firewall to allow the following ports for peer discovery and sync Ports `9200` (UDP) and `30301` (TCP/UDP) are required to reach Base bootnodes. If outbound traffic to these ports is blocked, your node will fail to establish initial peer connections. + + + If you use network ACLs (rather than stateful security groups such as AWS SGs) for egress control, you must also allow outbound traffic on the ephemeral port range **32768–60999** (TCP/UDP). Stateful firewalls track return traffic automatically; ACLs do not, so without this rule, response packets from peers are silently dropped. +