Blend
Create basket
BlendDocumentation

Search Blend documentation

Protocol
Integration
Reference
ABI downloads
↑↓ Navigate↵ OpenEsc Close
Documentation/Blend protocol

Blend developer docs

Read baskets, quote trades, submit transactions, and index Blend on Robinhood Chain.

Are you an LLM or using an LLM? Use these two for context: llms.txt and llms-full.txt.

Protocol architecture

Blend baskets are ERC-20 tokens backed by fixed quantities of constituent assets.

One share maps to a fixed amount of every active asset in its vault. Prices can change the basket's value and percentage weights, but they do not rebalance the underlying tokens.

A user who already holds every constituent can mint through the vault. A user who starts with USDG or ETH can use the router, which trades every constituent and then mints or redeems the share. All constituent swaps and share issuance or redemption execute atomically in one transaction.

Backing requirement

Every active asset must cover its units across all outstanding basket shares.

ContractResponsibilitiesKey restriction
FactoryDeploys baskets and lists canonical vaultsAsset custody is delegated to each vault
VaultHolds assets, issues shares, and processes redemptionHolder backing is unavailable for administrative withdrawal
HookStores routes and settles multi-asset tradesRegistration is restricted to approved factories
RouterConverts between a quote asset and complete basket sharesThe caller supplies slippage limits and deadlines
LensReturns previews, checks, and quotes through eth_callRead-only; no asset transfers

Basket accounting

Each basket specifies a quantity of every constituent token per share.

Units and backing

units(token) tells you how much of a constituent belongs to one full basket share. backing(token) is the amount reserved for every holder. Owner revenue, protocol revenue, and recovery value live in separate buckets.

Market price changes do not modify these accounting values. Onchain maintenance methods can modify them: accrete adds surplus to holder units, resyncmatches the books to the real balance, and recovery calls write value down or restore it.

Basket lifecycle

  1. DeployChoose 1–16 assets, their units per share, fee settings, rate limits, and the basket owner.
  2. RegisterAdd one route per asset for USDG or native ETH. Routes are not required for direct minting or redemption.
  3. OperateUsers mint, redeem, buy, and sell. The vault checks backing, limits, deadlines, and hourly capacity.
  4. MaintainAnyone can reconcile balances, accrete surplus, sweep protocol fees, observe dead routes, and restore recovered assets.

Transaction methods

Vault methods accept constituent assets directly. Router methods accept or return a single quote asset.

OperationMethodInputValidation parameters
Direct mintBasketVault.mintEvery active constituentmaxIn[] and deadline
Direct redeemBasketVault.redeemBasket sharesminOut[] and deadline
Exact-input buyBlendRouter.buyUSDG or native ETHminShares and deadline
Exact-output buyBlendRouter.buyExactUSDG or native ETHmaxIn and deadline
SellBlendRouter.sellBasket sharesminOut, deadline, optional skip list
Compose atomicallyflashMint / flashRedeemSettlement in a callbackFull repayment in the same transaction
Token approvals. Approve every ERC-20 constituent for a direct mint. Approve the quote token for a routed buy, or basket shares for a sell. An ETH buy sends msg.value and needs no token approval.

Fees and revenue

Fees are calculated independently for each active constituent using the current vault configuration.

Every mint and redemption charges each active constituent separately. The vault adds a basket-owner fee and a separately calculated fixed Blend protocol fee. Routed trades also pay each constituent pool's fee and price impact. The Blend hook pool itself uses fee 0 and therefore adds no separate basket-level trading fee.

Fee calculation

Fee componentFormula for one constituentAccounting bucket
Mint backingceil(shares * units / 1e18)Holder backing
Mint owner feeceil(base * mintFeeBps / 10,000)treasury[token]
Mint protocol feeceil(base * 35 / 10,000)protocolFees[token]
Redeem grossfloor(shares * units / 1e18)Removed from holder backing
Redeem owner feefloor(gross * redeemFeeBps / 10,000)treasury[token]
Redeem protocol feefloor(gross * 20 / 10,000)protocolFees[token]
Redeem payoutgross - owner fee - protocol feeSent to the recipient

Each basket sets its mint and redeem owner fees separately, up to 100 bps (1%). Read mintFeeBps() and redeemFeeBps() instead of assuming the maximum. Mint calculations round up; redemption calculations round down. Use previewMint and BlendLens.previewRedeem for the exact token amounts.

Onchain fee buckets

treasury[token]
The basket owner can withdraw this bucket. Before withdrawal, anyone may call accrete to move it into holder backing.
protocolFees[token]
Anyone may sweep the complete bucket to protocolFeeRecipient(). Accretion never spends this bucket. If the vault excludes the constituent before a sweep, the unswept balance moves to forfeited with the leg's backing and owner treasury.
forfeited[token]
Recovery value reserved for holders: skipped legs, excluded legs (including any unswept fee buckets on them), and the recovery share new mints pay in. Accretion consumes it before owner treasury.
Route execution
Routed trades pay each constituent pool's fee and price impact. Those costs follow pool accounting and are not split by the vault.
Example. If one share needs 100 units of a constituent and the owner fee is 10 bps, minting transfers 100 + 0.10 + 0.35 = 100.45 units. Redeeming a gross 100 units pays 100 - 0.10 - 0.20 = 99.70 units. Integer rounding, recovery contributions, and routed pool costs are omitted here.

A mint may also contribute to existing forfeited + writtenDown recovery value. This prevents new entrants from claiming value reserved for earlier holders; it is not a fee. The keeper attempts accretion every ten minutes. The vault limits growth to 0.50% per fully refilled 9.125-day step and 20% per year, with at least one share of supply. A leg skipped by redeemExcluding charges no fee and moves its full gross amount from backing to forfeited value.

Execution limits

LimitDefinitionIntegration impact
Route costPool fee and price impact on each constituent legOnly applies to router trades
Minimum issue0.001 sharesBounds rounding error on small mints
ThrottlesIssue and redeem capacity refill over one hourCan limit flow even when route liquidity is available
Redemption floorAt least 10% of supply per hourPrevents configuration from disabling exits
Route capacityQuoted for the selected slippage budgetThe shallowest weighted leg sets the limit

BlendLens.previewBuy returns cost per share and conservative route capacity. Current throttle headroom is excluded and must be read or indexed separately.

Failure recovery

Recovery methods preserve access to transferable constituents when a token or route fails.

ConditionProtocol behaviorIntegration requirement
Issuance is pausedStops mint, buy, and flash entry paths. Redemption stays open.Disable entry actions, but keep exits visible.
A token will not transferredeemExcluding returns the working assets.Show exactly which leg is skipped and forfeited.
A token is excludedThe operator can act now, or anyone can prove failure and repeat after one day.Index ConstituentExcluded and remove that leg from new issuance.
Vault accounting does not match its balanceresync reconciles the books to the token balance.Check isReconciled before presenting current state.
A route has no liquidityAnyone can report it; the owner can replace it after one day.Keep direct mint and redemption available.
Deficit reconciliation. A deficit consumes protocol fees first, then owner treasury, recovery value from earlier write-offs, and finally holder backing. If assets return, holders are repaid first. Withdrawals and protocol sweeps reconcile before moving funds, so fee buckets cannot leave while a deficit is unresolved.

Network setup

The following values are used for wallet configuration, contract reads, and event backfills.

Network
Robinhood Chain mainnet
Chain ID
4663
Native asset
ETH
Public RPC
https://rpc.mainnet.chain.robinhood.com
Factory start block
55,989,258
Basket share decimals
18
Canonical quotes
USDG (6 decimals) and native ETH (18 decimals)

Contract reference

Fetch an ABI directly from this site, or use the manifest to resolve every contract.

GET /abis
GET /abis/basket-factory.json
GET /abis/basket-vault.json
GET /abis/blend-hook.json
GET /abis/blend-router.json
GET /abis/blend-lens.json
ContractAddress or discoveryABIPrimary methods
BasketFactoryDeploys vaults and records every canonical basket.0x40bd43B7ff1D673e03B129dCE371761a6E81E305JSON ↗7 functions · 1 eventsdeploy, predict, deployed, deployedCount, isBasket
BasketVaultERC-20 basket share, custody, fees, throttles, and recovery accounting.Read BasketDeployed.vaultJSON ↗80 functions · 22 eventspreviewMint, mint, redeem, treasury, protocolFees, accrete, sweepProtocolFees
BlendHookRegisters basket pools and constituent routes; prices and settles routed trades.0x219B93D7c067f3cCc9E25aecDbecf1279D1Fc888JSON ↗33 functions · 10 eventsregister, poolKeyFor, routesFor, capacity, quoteLegs, replaceRoute
BlendRouterUser-facing exact-input, exact-output, and sell transactions.0x70DDEa1f1C509cE6554de3E12370Bf8A29bA4604JSON ↗6 functions · 2 eventsbuy, buyExact, sell
BlendLensRead and quote surface that requires no funded or approved caller.0xbB95752f5F1464e2Bb4f17652daF68c7f75f6c05JSON ↗12 functions · 0 eventspreviewBuy, previewRedeem, quoteBuy, quoteBuyExactOut, quoteSell

Shared infrastructure

Native ETH currency
0x0000...0000

Integration workflow

Start at the factory, read each vault, then use the hook and lens for route state and quotes.

Loading ABIs

const manifest = await fetch("/abis").then((r) => r.json());
const vaultAbi = await fetch("/abis/basket-vault.json").then((r) => r.json());
OperationContract call
Discover basketsIndex BasketFactory.BasketDeployed, or read deployedCount() and deployed(i).
Validate an addressBasketFactory.isBasket(vault)
Read compositionCall constituents(), then multicall units(token), backing(token), and excluded(token).
Read vault feesCall mintFeeBps(), redeemFeeBps(), the protocol fee constants, and protocolFeeRecipient().
Read fee balancesFor each token, read treasury(token), protocolFees(token), and forfeited(token).
Preview direct flowsCall previewMint(shares) or BlendLens.previewRedeem(vault, shares).
Resolve a basket poolCall BlendHook.poolKeyFor(vault, quote).
Read constituent routesBlendHook.routesFor(key)
Quote a tradeSimulate quoteBuy, quoteBuyExactOut, or quoteSell on the lens.
Submit a tradeSend the same pool key and basket address to BlendRouter, with a limit and deadline.
Pool key construction. A key contains the basket and quote sorted by address, fee 0, tick spacing 60, and the BlendHook address. One wrong field derives a different pool identifier. Integrations should read poolKeyForinstead of rebuilding it locally.

Indexed API

These endpoints are backed by the indexer and are useful for product surfaces. Responses include x-indexed-block. Use contract reads and logs when you need the exact chain head or a trust-minimized source.

GET /api/blend/baskets
GET /api/blend/basket/:address
GET /api/blend/assets
GET /api/blend/holdings/:address
GET /api/blend/activity/:address
GET /api/blend/units
GET /api/blend/leaderboard
GET /api/blend/eth

Every basket row (in baskets, basket and holdings) carries deployedAt, the unix time of its BasketDeployed event, and deployedBlock, both as decimal strings. Each of its legs carries the vault's buckets for that token as raw decimal strings: treasury, protocolFees, forfeited and writtenDown.

activity/:address is the basket's event history, newest first: its latest 150 events of every kind except Accreted, merged with its latest 50 Accreted events. units is the units-per-share history of every vault whose units have changed, in 4-hour UTC buckets: { block, bucketSeconds, vaults }, where each vault has exact and, per token, a start level and steps, pairs of bucket end and units after it, oldest first. exact is false when the replayed history does not end on the units the vault holds now.

Indexing

Start at factory block 55,989,258 and backfill in small ranges. Wide log requests can time out on the public RPC.

ContractEventsIndexed state
BasketFactoryBasketDeployedCanonical vault, creator, symbol, and deployment order
BasketVaultMinted, Redeemed, TransferShare activity and holder balances
BasketVaultFeesSet, ThrottlesSet, PausedSet, OperatorLockSetCurrent configuration and availability
BasketVaultConstituentAdded, ConstituentExcluded, UnitsWrittenDown, AccretedComposition and unit changes
BasketVaultTreasuryWithdrawn, ProtocolFeesSweptOwner withdrawals and protocol-fee settlement by constituent
BlendHookRegistered, RoutesExtended, RouteDeadObserved, RouteReplacedBasket pool and route topology
BlendHookBought, SoldRouted volume in shares and quote units

Events provide historical state transitions. Live prices, pool depth, reconciliation status, and refilled throttle headroom require current contract reads.

Permissions

Administrative roles can change how a basket operates. They cannot withdraw holder backing or disable ordinary redemption.

ActorAuthorized operationsRestrictions
Basket ownerWhile unlocked: set fees and throttles, pause issuance, add constituents. At any time, locked or not: register the basket, append routes for added constituents, replace a route a day after it is observed empty, unpause issuance, withdraw owner treasuryExclude assets, bypass fee caps, withdraw backing, or block redemption
OperatorLock configuration, pause issuance, exclude a failed asset, reduce owner fees to zeroRaise fees, move backing, block redemption, or change the fixed operator
Hook governanceApprove factories and transfer hook governanceDeregister baskets, alter a basket's routes, or move vault funds
AnyoneAccrete, resync, sweep protocol fees, prove asset failure, unexclude recovered assets, observe dead routesRedirect proceeds or override contract checks

New baskets start operator-locked. A creator may also choose immutable parameters at deployment, permanently disabling later parameter changes.

Risks

Blend limits some failure modes, but market, token, infrastructure, and governance risk remain.

  • Asset exposure. Tokenized stocks provide price exposure, not direct stock ownership, voting rights, or guaranteed dividends. Access may be restricted by location.
  • Issuer control. Asset issuers may upgrade contracts, pause transfers, freeze accounts, rebase balances, or stop supporting an asset.
  • Liquidity. A single shallow or empty constituent route can stop the routed basket trade even while direct redemption remains available.
  • Token behavior. Fee-on-transfer tokens are rejected on mint; unusual transfer behavior can still close issuance or require exclusion.
  • Execution. Quotes are estimates. Always set deadlines and minimum-output or maximum-input bounds.
  • Operational dependencies. Interfaces, indexers, RPCs, wallets, and automation can be delayed or unavailable. Verify critical state onchain.
Review status

SB Security reviewed the protocol in August 2026. Twenty-one of twenty-five findings were fixed; four were accepted with documented constraints. A review reduces risk but does not eliminate it.

For holders

What holders get from the way the vault works, and where each rule lives in the contract.

Reinvested dividends

Robinhood stock tokens implement ERC-8056. Robinhood reinvests dividends by raising a token's uiMultiplier(), the number of underlying shares one token represents, and leaves raw balances unchanged. BasketVault accounts in raw token units, so a basket keeps holding the same number of tokens while each token represents more shares. Route pools price the token, not the share, so the live NAV reflects reinvested dividends once pool prices adjust to the new multiplier. The app's NAV chart multiplies each per-share stock close by the token's multiplier in force at that close, read from its UIMultiplierUpdated events, so each dividend counts from its effectiveAt. Amounts and timing are set by the issuer and aren't guaranteed; see Risks. Read current values with each token's uiMultiplier() or BlendLens.uiMultipliers(vault).

Fee accretion

Every mint and redemption charges the basket owner's fee, booked to treasury[token], and Blend's protocol fee, booked to protocolFees[token]. Anyone may call accrete(token, unitsDelta) to move value into holder backing, raising units[token] for every share. It spends forfeited first, then treasury, and never protocolFees. Growth is capped at 0.50% of the leg's anchor units (or its current units, if lower) per 9.125-day refill, at most 20% of the anchor a year without compounding, and needs at least one whole share outstanding. The owner can withdraw treasury before it is accreted. forfeited holds value left by redemptions that skipped a leg, legs written off by exclusion, new minters' buy-ins, and recovered write-downs. The app's NAV chart replays each leg's units from the indexer's Accreted and UnitsWrittenDown history, so fee growth counts from the first close after it; when that history can't be read, the note under the chart says fee growth is missing.

NAV chart

Each point is a market close (a 4-hour bar on the 7D range), except that the latest can be a bar still trading. When a range starts before the basket was deployed, the line has one more point: the basket's value at the moment of deployment, each constituent at the close of its last full hourly bar before then (a stock outside trading hours at its last extended-hours price), with its units and multiplier at that moment. The headline change counts from that point, the same on every range, and the line before it is drawn dashed as a backtest: of the starting holdings, or of today's holdings when the units history can't be read. If a constituent's price at deployment can't be read yet, no change is shown until it can. A portfolio's chart counts from the latest launch among the baskets held. Neither returns nor future dividends are guaranteed.

Redemption

redeem and redeemExcluding have no pause check. A pause stops minting and flashRedeem, never ordinary redemption. The redemption throttle cannot be set below 10% of supply per hour (MIN_REDEMPTION_PCT_RATE), and its absolute rate must cover at least a tenth of supply (MIN_REDEMPTION_AMT_DIVISOR). Both are checked whenever throttles are set, and the absolute rate again on every mint, so the whole supply can redeem within ten hourly periods.

Frozen constituents

If a constituent reverts on transfer, a plain redeem reverts with it. Holders can call redeemExcluding(shares, to, skip), or BlendRouter.sell with a skip list, to take every other leg and forfeit the skipped leg's gross amount to forfeited. Only accrete (or unexclude, once the leg is excluded) pays that out to holders, and only while shares are outstanding; if every share is redeemed, resync or unexclude moves what is left to Blend's protocol-fee bucket. While the token stays frozen, that value cannot leave the vault. The operator can exclude a failed constituent at once with setExcluded, or anyone can with forceExclude after two failed transfer probes at least a day apart. unexclude restores it once it transfers again.