Base L2 Development
Overview
Base is an Ethereum Layer 2 network built by Coinbase on top of the OP Stack. It is fully EVM-compatible, but there are several important differences to be aware of. AI models frequently overlook L2-specific gas calculations, cross-chain bridge logic, or use generic Ethereum code that lacks Base-specific functionality.
⚠️ Gotchas (Most Common AI Mistakes)
1. Gas Price: L2 Execution Fee + L1 Data Fee
❌ Wrong (only checking L2 gas price):
const gasPrice = await provider.getGasPrice();
const gasCost = gasLimit * gasPrice; // Inaccurate!
✅ Correct (must account for L1 data fee):
// Base total fee = L2 execution fee + L1 data fee
// L1 data fee is queried via a precompile contract
import { createPublicClient, http } from 'viem';
import { base } from 'viem/chains';
const client = createPublicClient({ chain: base, transport: http() });
// Use viem's built-in L2 gas estimation
import { estimateTotalFee } from 'viem/op-stack';
const totalFee = await estimateTotalFee(client, { account, to, data });
2. Using viem + wagmi (Coinbase Recommended Toolchain)
import { createPublicClient, createWalletClient, http } from 'viem';
import { base, baseSepolia } from 'viem/chains';
import { privateKeyToAccount } from 'viem/accounts';
const publicClient = createPublicClient({
chain: base,
transport: http('https://mainnet.base.org'),
});
const account = privateKeyToAccount('0xYOUR_PRIVATE_KEY');
const walletClient = createWalletClient({
account,
chain: base,
transport: http('https://mainnet.base.org'),
});
3. Using OnchainKit to Build Base Apps Quickly
import { OnchainKitProvider } from '@coinbase/onchainkit';
import { base } from 'viem/chains';
function App() {
return (
<OnchainKitProvider
apiKey={process.env.NEXT_PUBLIC_ONCHAINKIT_API_KEY}
chain={base}
>
{/* Your app */}
</OnchainKitProvider>
);
}
4. Cross-Chain Bridge: Standard Bridge vs Third-Party
// Official Standard Bridge (L1 → L2, ~1-3 minutes)
import { getL2TransactionHashes, publicActionsL1 } from 'viem/op-stack';
import { mainnet } from 'viem/chains';
const l1Client = createPublicClient({ chain: mainnet, transport: http() })
.extend(publicActionsL1());
// Initiate deposit
const hash = await walletClient.depositTransaction({
request: {
to: recipientOnL2,
value: parseEther('0.01'),
gas: 21000n,
},
});
// L2 → L1 withdrawals require a 7-day challenge period (OP Stack security mechanism)
// Use a third-party bridge (e.g. Across, Stargate) to bypass the waiting period
RPC Endpoints
Mainnet: https://mainnet.base.org
Testnet (Sepolia): https://sepolia.base.org
Chainlink: Chain ID 8453 (mainnet), 84532 (testnet)
Base Name Service (Basename)
import { getName } from '@coinbase/onchainkit/identity';
// Resolve the Basename for an address
const name = await getName({
address: '0x...',
chain: base,
});
// Returns 'user.base.eth' or null
Installation
npm install viem wagmi @coinbase/onchainkit
# Hardhat configuration
npm install --save-dev hardhat @nomicfoundation/hardhat-toolbox
// hardhat.config.ts
networks: {
base: {
url: 'https://mainnet.base.org',
accounts: [process.env.PRIVATE_KEY!],
chainId: 8453,
},
baseSepolia: {
url: 'https://sepolia.base.org',
accounts: [process.env.PRIVATE_KEY!],
chainId: 84532,
},
}
Reference
Feedback
If this skill contains incorrect or outdated information, call:
id: base/l2-dev name: Base L2 Development version: 1.0.0 ecosystem: base type: technical-doc time_sensitivity: evergreen source: official confidence: high maintainer: AgentRel Community last_updated: 2026-03-19 feedback_endpoint: https://agentrel.vercel.app/api/feedback
Overview
Base is an Ethereum Layer 2 network built by Coinbase on top of the OP Stack. It is fully EVM-compatible, but there are several important differences to be aware of. AI models frequently overlook L2-specific gas calculations, cross-chain bridge logic, or use generic Ethereum code that lacks Base-specific functionality.
⚠️ Gotchas (Most Common AI Mistakes)
1. Gas Price: L2 Execution Fee + L1 Data Fee
❌ Wrong (only checking L2 gas price):
const gasPrice = await provider.getGasPrice();
const gasCost = gasLimit * gasPrice; // Inaccurate!
✅ Correct (must account for L1 data fee):
// Base total fee = L2 execution fee + L1 data fee
// L1 data fee is queried via a precompile contract
import { createPublicClient, http } from 'viem';
import { base } from 'viem/chains';
const client = createPublicClient({ chain: base, transport: http() });
// Use viem's built-in L2 gas estimation
import { estimateTotalFee } from 'viem/op-stack';
const totalFee = await estimateTotalFee(client, { account, to, data });
2. Using viem + wagmi (Coinbase Recommended Toolchain)
import { createPublicClient, createWalletClient, http } from 'viem';
import { base, baseSepolia } from 'viem/chains';
import { privateKeyToAccount } from 'viem/accounts';
const publicClient = createPublicClient({
chain: base,
transport: http('https://mainnet.base.org'),
});
const account = privateKeyToAccount('0xYOUR_PRIVATE_KEY');
const walletClient = createWalletClient({
account,
chain: base,
transport: http('https://mainnet.base.org'),
});
3. Using OnchainKit to Build Base Apps Quickly
import { OnchainKitProvider } from '@coinbase/onchainkit';
import { base } from 'viem/chains';
function App() {
return (
<OnchainKitProvider
apiKey={process.env.NEXT_PUBLIC_ONCHAINKIT_API_KEY}
chain={base}
>
{/* Your app */}
</OnchainKitProvider>
);
}
4. Cross-Chain Bridge: Standard Bridge vs Third-Party
// Official Standard Bridge (L1 → L2, ~1-3 minutes)
import { getL2TransactionHashes, publicActionsL1 } from 'viem/op-stack';
import { mainnet } from 'viem/chains';
const l1Client = createPublicClient({ chain: mainnet, transport: http() })
.extend(publicActionsL1());
// Initiate deposit
const hash = await walletClient.depositTransaction({
request: {
to: recipientOnL2,
value: parseEther('0.01'),
gas: 21000n,
},
});
// L2 → L1 withdrawals require a 7-day challenge period (OP Stack security mechanism)
// Use a third-party bridge (e.g. Across, Stargate) to bypass the waiting period
RPC Endpoints
Mainnet: https://mainnet.base.org
Testnet (Sepolia): https://sepolia.base.org
Chainlink: Chain ID 8453 (mainnet), 84532 (testnet)
Base Name Service (Basename)
import { getName } from '@coinbase/onchainkit/identity';
// Resolve the Basename for an address
const name = await getName({
address: '0x...',
chain: base,
});
// Returns 'user.base.eth' or null
Installation
npm install viem wagmi @coinbase/onchainkit
# Hardhat configuration
npm install --save-dev hardhat @nomicfoundation/hardhat-toolbox
// hardhat.config.ts
networks: {
base: {
url: 'https://mainnet.base.org',
accounts: [process.env.PRIVATE_KEY!],
chainId: 8453,
},
baseSepolia: {
url: 'https://sepolia.base.org',
accounts: [process.env.PRIVATE_KEY!],
chainId: 84532,
},
}
Reference
Feedback
If this skill contains incorrect or outdated information, call: agentrel_feedback(skill="base/l2-dev", issue="<description>", code_snippet="<optional>", error_message="<optional>", fix="<optional>")