Deployments
Canonical contract addresses per network. Use these, or your CIDs will not match anyone else's.
A BAMFS CID commits to the storage backend address as well as the bytes:
chunk ids are keccak256(abi.encodePacked(backend, data)). A different backend
address is therefore not a configuration preference — it is a different
content-address space. Two uploads of byte-identical content against different
backends produce different CIDs and do not deduplicate against each other.
Use the addresses below. The SDK ships them, so the CLI and the gateway need no configuration to read.
Prerelease. The contracts are unaudited, nothing is locked, and ownership has not been renounced on any network. Base is a production chain with real funds at risk — treat nothing here as permanent yet.
Live networks
| Network | Chain id | |
|---|---|---|
| Base | 8453 | production |
| Base Sepolia | 84532 | the paired testnet |
The same addresses on both
Every contract below sits at one address on both chains. That is the point rather than a coincidence: same bytecode, same salts, same CREATE2 deployer. Because the backend address is part of every chunk id, identical bytes uploaded to either chain produce identical CIDs.
| Contract | Address |
|---|---|
StorageBackend | 0x91520CDaaaB44267e99D08FEA7730D7A7C60E9c2 |
ContentStore | 0xd4a0FFa88a58ee7Bb7e802E7079EE90C8DA52250 |
FileStore | 0xaa79Ce91da95367fD79bF5d718B055d31EB9CfD3 |
DirectoryStore | 0x16FA2Ecac2B898FB91dc17bae843C7D0E6d8531f |
BamfsProjectHook | 0xc2Aa83414a6860b6e6Fd9151ea4e53fC3A0bdb28 |
BamfsProjectEnumeration | 0xDa9bA88eC0cA3cFf7F2E59dC1504d641a9883E7E |
IpfsCidResolver | 0x857f409377F268D1dB0BdfDF820c1A6aE779FE88 |
The collection differs
It is an ABX NFT minted per chain, so it is the one address that is not shared:
| Network | BamfsProjectCollection | Deploy block |
|---|---|---|
| Base | 0x10DDfcbcD62E784c522D0B466eD109FC65B2a855 | 52009344 |
| Base Sepolia | 0x7015Ab36fA7d62dAf286561114E7f3c250511E31 | 47434387 |
Testnet only
| Contract | Base Sepolia |
|---|---|
IpfsCidVerifier | 0xf66d2c3fE607480e013eb0b29C69B6f188290327 |
CrossChainRegistry | 0xcb8DA355Bd728E79bf14c55d4f9a2e23F6132f5b |
Neither is deployed on Base, deliberately. IpfsCidVerifier takes its proof
backend as an immutable constructor argument, and the deploy script passes a
mock that accepts any proof whose seal decodes to the journal preimage. On a
production chain that is a permanently fake proof surface at a canonical-looking
address, with no way to repoint it. The ZK path is not shipped — see
ZK proofs.
Read them from the SDK rather than copying them:
import { requireCanonicalDeployment } from "@bamfs/sdk";
const { name, addresses, publicRpc } = requireCanonicalDeployment(84532);Other networks
There are none. An entry appears in the registry only once a deployment exists
on that chain, so canonicalChainIds() is the honest list at any moment.
Picking an RPC endpoint
Every BAMFS read is an eth_call, and resolving a 1 MB file out of contract
storage costs roughly 72M gas. Public endpoints differ by more than an order of
magnitude in what they will execute, so the choice is load-bearing rather than
cosmetic.
| Endpoint | eth_call cap |
|---|---|
https://sepolia.base.org | 500M+ |
https://base-sepolia-rpc.publicnode.com | ~50M |
These are unkeyed and rate-limited. Use a keyed provider for anything sustained — on Base that is not optional, since the public endpoint rate-limits an ordinary deploy.
The write-side ceiling is not the block gas limit
eth_estimateGas caps at exactly 224 (16,777,216) on every Base
Sepolia endpoint tried, including keyed ones. This is a node setting, not a
chain property — Base Sepolia's block gas limit is 1.2 billion. A bundle whose
estimate exceeds the cap fails to estimate at all, so the SDK clamps its bundle
budget below it regardless of which RPC you point at.
The cap is per-endpoint, not universal: a keyed Base endpoint measured no such ceiling, and a 150 KB upload there bundled at ~12M gas per transaction without trouble. Measure it before assuming either way.
