Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Architecture — the Diamond · Boson Protocol
Skip to content

Architecture — the Diamond

The Boson on-chain protocol is a single contract: a Diamond (EIP-2535) proxy that delegates to 21 handler facets, each implementing one domain. All write paths go through this single address.

Why a Diamond

  • One address per chain — easier to integrate, easier to authorize, easier to audit.
  • Upgradeable per-facet — protocol can ship a fix to dispute logic without touching offer logic.
  • No 24 KB contract-size limit — facets are independent contracts; the Diamond is a router.
  • Single storage namespace — all facets share the protocol storage, so cross-domain reads are cheap.

The 21 facets

FacetDomain
OfferHandlerFacetCreate / void offers; offer queries
ExchangeCommitFacetcommitToOffer, including buyer-initiated
ExchangeHandlerFacetRedeem, complete, cancel, revoke vouchers
DisputeHandlerFacetRaise / resolve / escalate / decide disputes
FundsHandlerFacetDeposit / withdraw treasuries
AccountHandlerFacetHigh-level entity creation
SellerHandlerFacetSeller-specific config, royalties, allowlists
BuyerHandlerFacetBuyer queries
DisputeResolverHandlerFacetDR registration, fees, allowlists
AgentHandlerFacetProtocol agents
GroupHandlerFacetToken-gating conditions
BundleHandlerFacetMulti-item bundles
TwinHandlerFacetConditional twin items (rare)
MetaTransactionsHandlerFacetEIP-712 envelopes, token-auth
OrchestrationHandlerFacet1 / 2Atomic combos (createOfferAndCommit, createOfferCommitAndRedeem)
PriceDiscoveryHandlerFacetAuction / discovery pricing
SequentialCommitHandlerFacetBatch / expiration semantics
ConfigHandlerFacetProtocol params, fees, pause regions
PauseHandlerFacetRegion-based pause control
ProtocolInitializationHandlerFacetOne-time setup

Full reference: Reference → Contracts → Diamond facets.

Read paths

For reads, prefer the subgraph (see Eventing & indexing). The Diamond exposes getters too, but reading dozens of fields is expensive without batching.

Surrounding contracts

The Diamond does most of the work, but a few helpers ship alongside:

  • Voucher (rNFT) ERC-721 — an individual collection contract used by sellers; minted on commit, burned on redemption. A seller can have multiple voucher contracts.
  • Permit2 — the Uniswap permit-as-a-service contract, used by token-auth meta-tx.
  • Forwarder — meta-tx forwarder for the Biconomy relay path.
  • PriceDiscoveryClient — adapter contract for discovery-based price flows.

Addresses for all of these are in the per-chain JSON files; see Networks → Contract addresses.

Storage

All facets share a single ERC-7201-style storage namespace, with a per-domain struct: protocolEntities, protocolLookups, protocolCounters, protocolStatus, etc. Defined in BosonTypes.sol + ProtocolLib.sol.

You don't read storage directly — use the appropriate getter facet — but knowing the layout helps you decode events.

Upgrades

Per-facet upgrades are governed by a multisig. Upgrade scripts live in boson-protocol-contracts/scripts/upgrade-facets.js. Each upgrade gets a new configId only on breaking changes; routine logic changes preserve the existing configId.

Common footguns

  • Don't hard-code a facet's contract address. All facets are reachable via the Diamond; the facet addresses change on upgrade.
  • Don't decode events from a single-facet ABI. Use the merged ABI in @bosonprotocol/common.
  • Pause regions matter. During an incident, individual regions (offers, exchanges, disputes) can be paused independently. Read protocol.pausedRegions() before assuming a call will succeed.

Next