Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion docs/apps/guides/accept-b20-payments.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [
Expand Down
29 changes: 25 additions & 4 deletions docs/base-chain/specs/upgrades/beryl/b20.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ 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.

To deploy your first B20 token, see the [Launch a B20 Token](/get-started/launch-b20-token) quickstart.

B20 supports two variants:

Expand All @@ -17,9 +19,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.

<Check>
B20 implements the full ERC-20 standard surface with complete selector parity - it is a drop-in replacement for existing tooling and integrations.
B20 is a superset of ERC-20. Every ERC-20 call (`transfer`, `transferFrom`, `approve`, `balanceOf`, `allowance`, and the standard events) behaves exactly as the standard specifies, so existing ERC-20 tooling and integrations work against B20 with no changes.
</Check>

B20 adds methods that ERC-20 does not include: memos, mint/burn, policy gating, granular pause, and ERC-2612 `permit`. These extend ERC-20 without altering it - every ERC-20 method exists on B20, but the reverse does not hold. 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.
Expand Down Expand Up @@ -168,7 +172,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)`.
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 |
|-----------|-------------|
Expand All @@ -187,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

Expand All @@ -199,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.
Expand Down Expand Up @@ -242,3 +253,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` |

60 changes: 52 additions & 8 deletions docs/get-started/launch-b20-token.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,46 @@ 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).

## 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
base-foundryup --install v1.1.0
base-foundryup
```

<Note>
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.
</Note>

## Verify the Activation Registry is enabled

<Warning>
**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:
</Warning>

```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}
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}
Expand All @@ -45,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).

<Tabs>
<Tab title="Mainnet">
| 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"
```

<Note>
If you don't have an account, `base-cast wallet new` prints a fresh address and key.
</Note>

Confirm your account has ETH for gas:

```bash Terminal theme={null}
source .env
base-cast balance $ACCOUNT_ADDRESS --rpc-url $RPC_URL
```

<Check>
The command prints a non-zero balance. This account signs the deploy and the mint, and receives the minted supply.
</Check>
</Tab>
<Tab title="Base Sepolia">
| Setting | Value |
|---|---|
Expand Down Expand Up @@ -211,7 +256,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...`:

<Note>
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.
Expand Down Expand Up @@ -277,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).
* Gate transfers or mints with PolicyRegistry policies, add granular pause, or manage roles. See the [B20 token standard](/base-chain/specs/upgrades/beryl/b20).
Loading