BAMFS
Reference

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

NetworkChain id
Base8453production
Base Sepolia84532the 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.

ContractAddress
StorageBackend0x91520CDaaaB44267e99D08FEA7730D7A7C60E9c2
ContentStore0xd4a0FFa88a58ee7Bb7e802E7079EE90C8DA52250
FileStore0xaa79Ce91da95367fD79bF5d718B055d31EB9CfD3
DirectoryStore0x16FA2Ecac2B898FB91dc17bae843C7D0E6d8531f
BamfsProjectHook0xc2Aa83414a6860b6e6Fd9151ea4e53fC3A0bdb28
BamfsProjectEnumeration0xDa9bA88eC0cA3cFf7F2E59dC1504d641a9883E7E
IpfsCidResolver0x857f409377F268D1dB0BdfDF820c1A6aE779FE88

The collection differs

It is an ABX NFT minted per chain, so it is the one address that is not shared:

NetworkBamfsProjectCollectionDeploy block
Base0x10DDfcbcD62E784c522D0B466eD109FC65B2a85552009344
Base Sepolia0x7015Ab36fA7d62dAf286561114E7f3c250511E3147434387

Testnet only

ContractBase Sepolia
IpfsCidVerifier0xf66d2c3fE607480e013eb0b29C69B6f188290327
CrossChainRegistry0xcb8DA355Bd728E79bf14c55d4f9a2e23F6132f5b

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.

Endpointeth_call cap
https://sepolia.base.org500M+
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.

On this page