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.
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.
Before you begin
You need Base’s Foundry build (base-forge, base-cast, base-anvil). Install it via base-foundryup:
Terminal
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.Set up your project
Terminal
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:
foundry.toml
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:
- Base Sepolia
- Vibenet
- Local (base-anvil)
| Setting | Value |
|---|---|
| RPC URL | https://sepolia.base.org |
| Chain ID | 84532 |
| Faucet | CDP Faucet or other providers |
| Explorer | sepolia.basescan.org |
.env
If you don’t have an account,
base-cast wallet new prints a fresh address and key.Terminal
The command prints a non-zero balance. This account signs the deploy and the mint, and receives the minted supply.
Create your token
The factory’s single entry point iscreateB20(variant, salt, params, initCalls):
variant:ASSETorSTABLECOIN. This guide usesASSET.salt: caller-chosen entropy that fixes the deterministic token address.params: ABI-encoded name, symbol, initial admin, and decimals.initCalls: optional batch of config calls applied at creation.
Write the create script
Use
B20FactoryLib to encode params and initCalls. Create script/CreateToken.s.sol:script/CreateToken.s.sol
Asset decimals are fixed at creation and must be in
[6, 18]. The supply cap is optional; the no-cap sentinel is type(uint128).max (the cap can never exceed uint128.max).Want a stablecoin instead?
Want a stablecoin instead?
Use the Everything else in this guide — roles, supply cap, minting, and verification — works identically.
STABLECOIN variant and its params encoder. A stablecoin fixes decimals at 6 and carries an immutable ISO currency code (uppercase A–Z) instead of a configurable decimals value:Deploy the factory call
Terminal
0xB20f.... 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.Output
Capture the token address
Save the address to an environment variable so the next step needs no copy-paste. The broadcast artifact holds the return value:Appending to
Terminal
.env keeps TOKEN_ADDRESS available in later steps, even in a new terminal session.The broadcast path includes the chain ID, which the
CHAIN_ID value in your .env supplies: 84532 for Sepolia, 84538453 for Vibenet, 31337 for local base-anvil.Mint and verify
Minting requiresMINT_ROLE, which initCalls granted to your account.
What you built
In this guide you:- Created a B20 Asset token with one
createB20call - Configured its admin, minter, and supply cap atomically via
initCalls - Minted supply
- Verified the balance onchain
Next steps
- Accept B20 payments in an app: 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.
- Issue a stablecoin variant (fixed 6 decimals, immutable currency code).