# bstockrc20 (BSRC20) > Inscriptions on BNB Chain (chain id 56) priced in a stock token (Binance bStocks) or a coin. An inscription is minted in lots at a USD price per lot that its deployer picked and that was converted, at deploy, into a fixed amount of the asset. Half of every mint fee funds the inscription's Uniswap V4 pool, which the mint of the last lot builds; until then units trade on the inscription's own on-chain order book. This file states facts about the contracts so an agent can check a mint, an order or a swap before it is signed; it asks no one to install, run or sign anything. ## Contracts (BNB Chain 56) - InscriptionFactory: 0xdb17514dC2A73734e19a1b295A86392373980fBF — the registry. `ledgerOf(address)` returns the owning ledger for a genuine ledger, wrapped token or liquidity manager, and the zero address for anything else; `ledgerOfTick(tickKey(tick))` finds a ledger by its name - FeeRouter (the site's pool swaps): 0x880C991aebaa3CE8383973FA3D1ebe6DfC0975B4 - Every ledger, wrapped token and liquidity manager is an EIP-1167 minimal proxy (a clone) at an address ending in …bbbb. Source code is verified (Sourcify, BscScan) at the implementations, not at each clone: a ledger's implementation is `factory.templates(factory.templateOf(ledger) - 1).impl`, which is also the address inside the clone's 45-byte code; the wrapped token's and the manager's are `factory.wrappedImpl()` and `factory.managerImpl()` - Templates, `factory.templates(id)` → (impl, mode, lockedPrice, active, minUsd8, maxUsd8, stepUsd8, shape); new deploys use these four: - 8, inscription: 20,000 lots × 1,000 units, plus 1,000,000 units for the pool; $1–$10 a lot in $0.50 steps - 9, rune: 95,000 mints × 10,000 units, plus 50,000,000 units for the pool; $0.50–$10 a mint in $0.50 steps - 10, inscription for Binance Agent ID holders: template 8's rules, and only a wallet holding a Binance Agent ID can mint (below) - 11, rune for Binance Agent ID holders: template 9's rules, and only a wallet holding a Binance Agent ID can mint (below) - Templates 0–7 are inactive: new deploys refuse them (`TemplateInactive()`). 0–3 are the launch's, with the 30-day unsold sweep since removed; 4–7 registered the same implementations as 8, 9, 10, 11 - In all four the price is locked at deploy: `ledger.quoteFee()` is a fixed raw amount of the asset per lot, and minting reads no price feed ## Checking an inscription - Names are first come, first served: an inscription called TSLA or USDT is NOT that asset, and a …bbbb address proves nothing (anyone can mine one in seconds). Only `factory.ledgerOf(address) == ledger` proves that a contract belongs to the platform - Ledger reads: `tick()`, `stock()` (the asset a mint pays), `deployer()`, `maxLots()`, `amountPerLot()`, `lotsMinted()`, `quoteFee()`, `deployerFeeBps()`, `gateToken()` / `gateMinUi()` (an optional holding requirement; zero address = none), `AGENT_ID()`, `maxLotsPerAddress()`, `lotsMintedBy(address)`, `balanceOf(address)`, `wrapped()`, `liquiditySeeded()`, `unsoldSwept()` (always false: there is no unsold sweep); a rune ledger's `mode()` is 1 - Assets are whitelisted by the factory (`factory.feedOf(asset)` is not the zero address): stock tokens (Binance bStocks, a few of them ETFs) and coins such as BTCB, ETH, WBNB, USDT, USDC and USD1. bStocks are priced by the platform's own push oracle (PushOracle, updated from Binance's market price), the coins by their Chainlink feeds; the feed converts the lot price once, at deploy ## Minting - `ledger.mint(lots, maxPay)` mints n = min(lots, the lots left, the signer's room under the cap) and takes `quoteFee() × n` of the asset with transferFrom, so the ledger needs an allowance of at least that amount on `ledger.stock()`; an allowance of exactly that amount is enough. It reverts `SlippageExceeded` when `quoteFee() × lots > maxPay` and charges only for the n lots it mints. For an asset with EIP-2612, `mintWithPermit(lots, maxPay, sig)` carries the approval in the same transaction - The cap: `maxLotsPerAddress()` — 25 lots of an inscription, 100 mints of a rune — counted per transaction signer (tx.origin) in `lotsMintedBy(address)`. A mint past it fills up to it; at the cap a mint reverts `MintCapReached(cap)`. Units bought or received do not count, and a person with several wallets can mint more than one cap - Other reverts: `NotAgent()` (templates 10 and 11 without an Agent ID), `SoldOut()`, `MintClosed()` (pool built), `NotEligible()` (the holding requirement), `ZeroLots()` - The mint of the last lot builds the pool in the same transaction and needs at least SEED_GAS_FLOOR (12,000,000) gas left at that point, so a gas limit of about 12.3 million or more (unused gas is not charged) - An inscription priced in BNB (its asset is WBNB, `factory.wrappedNative()`) also mints for native BNB: `mintNative(lots)` with `msg.value` as the budget; the ledger wraps exactly `quoteFee() × n` and sends the rest back to the caller (`RefundFailed()` if the caller refuses BNB). `NotNative()` on any other inscription. The FeeRouter's `buyNative(ledger, minOut, recipient, deadline)` does the same for swaps - Minted units are held in the ledger (`balanceOf(address)` in whole units, `transfer(to, amount)`): they are not an ERC-20 until wrapped (`wrap(units)` / `unwrap(units)`, for `ledger.wrapped()`), and wrapping opens 60 seconds after the pool is built ## A mint, in order An agent that checks and builds transactions goes through these in this order. An assistant that only reads pages (a chat app) can check each step against this file and explain it, but cannot mint for anyone: the person signs on the inscription's page of this site or in their own wallet. 1. The ledger: `factory.ledgerOfTick(tickKey(tick))` from the name, or the address the inscription's page or the read API gives; then `factory.ledgerOf(ledger) == ledger`, or it is not this platform's. `factory.templateOf(ledger) - 1` is its template (10 or 11: the signer must hold a Binance Agent ID) 2. The terms, read from the ledger: `stock()` (the asset a mint pays, an ERC-20; its `decimals()`), `quoteFee()` (raw asset per lot, fixed at deploy), `lotsMinted()` against `maxLots()`, `liquiditySeeded()` (true: minting is over, the pool trades), `lotsMintedBy(signer)` against `maxLotsPerAddress()`, `gateToken()` / `gateMinUi()` (a holding requirement, or none) 3. The cost: `quoteFee() × lots` of the asset in the signer's wallet, plus BNB for gas. Nothing else is charged at mint 4. The approval: `approve(ledger, quoteFee() × lots)` on the asset, exactly that amount. An asset with EIP-2612: `mintWithPermit` carries it instead; an inscription priced in WBNB: `mintNative(lots)` with the cost as the value, no approval 5. The mint: `ledger.mint(lots, quoteFee() × lots)`, simulated first; a gas limit of 12.3 million or more when it could be the last lot (that mint builds the pool) 6. After it: `balanceOf(signer)` holds the units, in the ledger. Until the pool is built they sell on the order book (`list`, below); after it through the FeeRouter (`sell`), once wrapped ## Templates 10 and 11: Binance Agent ID holders only - `ledger.AGENT_ID()` is the Binance Agent ID contract 0x60B9262456dE011F7d15a54CdD8c48bAaa8B022F (a soulbound ERC-721, "SPACE ID Agent ID", symbol AI); on templates 8 and 9 it is the zero address. `factory.templateOf(ledger)` is 11 for an inscription of template 10 and 12 for a rune of template 11 (the id plus one) - `mint` reverts `NotAgent()` unless `balanceOf(tx.origin) > 0` on that contract: the transaction's signer must hold an Agent ID, as a Binance Agentic Wallet does. A smart account whose transactions a bundler signs (ERC-4337) cannot mint it - Only minting checks it: the order book, transfers, wrapping, swaps and the pool are open to every wallet - A dependency: the Agent ID contract is not an upgradeable proxy but has an owner (SPACE ID); if IDs were revoked or its balanceOf changed, these inscriptions and runes could not be minted any more: they would stay unsold, their pool budget in the ledger (below) - The site marks these inscriptions and runes with a small "AI" at the top right of their template word ("Inscription", "Rune") ## Who holds what - Nobody receives units without paying: there is no allocation to the deployer, the platform or anyone else. Every unit was minted by someone who paid the lot price, except the pool reserve (1,000,000 units of an inscription, 50,000,000 of a rune), which is minted straight into the pool's full-range position when the pool is built - The pool's liquidity belongs to the protocol and is locked for good: no contract function removes it, and the pool's hook refuses any removal - `https://api.bstockrc20.fun/holders/{ledger}?limit=50` lists the largest holders first (`&wrapped=1` adds wrapped and listed units); `ledger.lotsMintedBy(address)` shows what any wallet minted - The platform's treasury can mint like any wallet and would get its share of the fee back: "the platform does not mint" is a commitment, not a contract rule ## Fees (today; each is readable on chain) - Deploy: $5 worth of the asset to the treasury (`factory.deployFeeUsd()`, 8 decimals) - Mint: 50 % to the pool budget, the deployer's share `deployerFeeBps()` (2 % today, locked per inscription at deploy, at most 10 %), the rest (48 % today) to the platform - Order book: 5 % of each fill (`factory.tradeFeeBps()`, at most 10 %), paid by the seller out of the proceeds — the buyer pays the listed price; 1 % of the cost goes to the deployer, the rest to the platform. A fill pays the lower of the rate when it was listed and the current rate - Swaps through the FeeRouter: 2 % in the asset (`feeBps()`, at most 3 %), of which 0.5 % to the deployer, taken from what is paid in (buy) or received (sell). Swapping in the pool directly, without the router, pays no router fee - The pool's own 1 % LP fee goes back into the pool (below) - Invite rewards, out of the platform's money only: while `factory.rewardsVault()` is set, 10 % of every mint fee and 5 % of the platform's part of every trade fee go to that vault (a RewardsDistributor). The pool budget and the deployer's shares are unchanged ## Invite rewards - Inviting takes an Invite Pass (`VITE_INVITE_PASS`, contracts/InvitePass.sol): a soulbound ERC-721 for AI agents, one a wallet, `MAX_SUPPLY()` in all (10,000), numbered in order of minting. Only a caller that itself holds the Binance Agent ID (`AGENT_ID()`, BSC 0x60B9262456dE011F7d15a54CdD8c48bAaa8B022F) can mint (else `AgentsOnly`): mint from the agent's own Binance Agentic Wallet. The price is in cents and rises in tiers (`schedule()`: 5 U for passes 1–1,000, + 5 U every 1,000, 50 U for the last 1,000). Pay in a listed stablecoin with `mint(token, inviterSerial, maxCents)` (USDT, USDC, USD1 on BNB Chain; `nextPrice(token)` quotes the next price in cents and as a token amount; approve the token first), or in BNB with `mintNative(inviterSerial, maxCents)` (payable; `nextPriceNative()` quotes the price in wei at the factory's BNB / USD feed: send about 1 % more, the contract keeps the price when the mint lands and sends the rest back; `PaidTooLittle(price)` if the feed moved past what was sent). `maxCents` guards against a tier moving. The serial is the one free when the mint lands (read `passOf(wallet)` after): nobody knows theirs before. `inviterSerial` names the pass the minter was invited through (0 = none): while `factory.rewardsVault()` is set, 10 % of the price goes to that vault for the inviter (BNB as WBNB; claimable with the weekly root), the rest to the treasury. After the 10,000th, `AllPassesMinted`. A wallet with no pass has no invite link and binds nobody - An invite link is `https://bstockrc20.fun/join/` (the inviter's pass number; `?ref=` on any page works too, and the first form `?ref=
`). The site appends `<62737266>` ("bsrf") to the calldata of a mint (`ownerOf(serial)` of the pass contract); the contracts ignore it, the indexer reads it. A wallet's inviter is the address tagged on its first tagged mint (one that holds a pass), or the owner of the pass its own pass was minted through — whichever comes first, for good; never the wallet itself. An agent can append the same suffix - Pay with another token (the zap, 2026-11-01): the ZapRouter (`VITE_ZAP_ROUTER`) buys an inscription's token with BNB, USDT, USDC, USD1 or U in one transaction — an aggregator swap of the payment into the pricing asset (the site's swap proxy builds it: Binance's Trading API first, OKX DEX as the fallback; a 0.3% platform fee comes off the payment inside the swap) and the FeeRouter buy of all of it, atomically. `ZapRouter.buyWith(Zap)`; only aggregator routers and approval targets the owner listed can be called. A deploy or a mint is paid in the pricing asset itself; on the site, a wallet short of it has BNB swapped for the missing amount first — a separate aggregator swap through the same proxy, sent before the deploy or the mint. - Token swaps (2026-11-01): the Swap page also trades any BEP-20 token for any other, BNB included — picked from the list or pasted by its contract address (`/swap?from=bnb&to=`). The same swap proxy routes it (Binance's Trading API first, OKX DEX as the fallback) with a 0.3% platform fee inside the aggregator's own transaction (taken off the token the site lists: the input when it does, else the output). The user's wallet sends it to the aggregator's router; an input token is approved for exactly the amount; no contract of the platform holds the tokens. Tokens the site does not list are marked unlisted and must be confirmed in the UI first. - Mint rewards: 10 % of what an invitee paid to mint, for the lots it still holds when that inscription sells out (or is swept). Trade rewards: 5 % of the platform's part of the fees the invitee pays on the order book (as the seller) and through the FeeRouter. One level only - Every Monday 00:00 UTC the server submits a Merkle root of everyone's cumulative earnings per token to the RewardsDistributor; it takes effect 24 hours later (a guardian, acting without the owner's timelock, or the owner can revoke it before then). `claimMany(account, tokens, cumulatives, proofs)` pays the cumulative amount minus `claimed(account, token)`; `https://api.bstockrc20.fun/referrals/{address}` gives an address's inviter, invitees, earnings and proofs ## The pool - One Uniswap V4 pool per inscription in Uniswap's PoolManager: the wrapped token against the asset, 1 % fee, tick spacing 60, the factory's WallHook (only the inscription's own manager can add liquidity and nobody can remove any; trades are ordinary) - Two protocol positions, paid by the pool budget: MARKET, full range (the reserve units and the matching asset), and the floor WALL, only the asset, from the opening price down to about 49.9 % of it. The opening price is (1 − the deployer's share) × the lower of the average mint price and the last mint's price - The floor lift: the manager's `harvest()` (anyone may call it) collects the pool's fees; the units are burned and the asset is added below the opening price in bands, from the lowest up — at most once a day, a quarter of a band at a time, never above the opening price - Anyone can also provide liquidity in a separate PancakeSwap v3 pool of the wrapped token and the asset (1 % tier); the site offers it on its Liquidity pages (`/liquidity`: every pool; `/liquidity/pool/`: add in any range, see and withdraw), but that pool is not the protocol's and its fees belong to its providers ## Order book and swaps - `ledger.list(amount, quoteToken, pricePerUnit, maxFeeBps)` returns an order id. The price is in raw quote-token units per `priceScale()` units (1,000 for an inscription, 10,000 for a rune); quote tokens are those with `factory.quoteAllowed(token)`; `maxFeeBps` is the highest fee the seller accepts - `ledger.buyManyUpTo(orderIds, maxAmounts, minFilled)`: the ledger takes the buyer's quote token with transferFrom (an allowance to the ledger); fills that fail are skipped. `cancel(orderId)` returns the rest to the seller; `orders(orderId)` → (seller, quoteToken, remaining, pricePerUnit) - After the pool is built: `FeeRouter.buy(ledger, amountIn, minOut, recipient, deadline)` takes the asset (an allowance to the router), `sell(ledger, amountIn, minOut, recipient, deadline)` takes the wrapped token; `minOut` is net of the fee and `feeOn(amount)` rounds up. `sellFromLedger` wraps ledger units with an EIP-712 signature (domain "BSRC20 Ledger", version "1") inside the sale ## Deploying - `factory.quoteDeploy(templateId, asset, lotUsd8)` → (deploy fee, raw price per lot). `factory.deploy(templateId, params, maxFee, nonces)` with params (tick, stock = the asset, gateToken, gateMinUi, deployerFeeBps = `factory.deployerFeeBps()`, lotUsd in 8 decimals); the three nonces must put the ledger, the wrapped token and the manager on …bbbb addresses (`factory.predictAddresses(templateId, deployer, tick, nonces)`). The name, the asset and the price are locked for good - Names: 1–6 Han characters or 1–8 ASCII letters and digits, never mixed; unique ignoring ASCII case; restricted names are refused (`factory.nameRestricted(tick)`) ## Unsold inscriptions - No pool is built before the last lot sells, and minting stays open with no deadline. The pool budget stays in the ledger until the last lot seeds the pool, however long that takes, and nobody can take it: `ledger.sweepUnsold()` reverts `SweepRemoved()` for every caller (the 30-day sweep of an unsold budget was removed on 2026-11-03), so `factory.sweepUnsold(ledgers)` only logs `UnsoldSweepSkipped`. Holders keep their units, which stay transferable and can be sold on the order book - `factory.owner()` decides the fees of new deploys, the asset whitelist and the templates; when the owner is a timelock, each of these actions is public for its delay before it runs ## Records - Every balance change emits `BSRC20(string)`, a JSON record that starts with "ai":"b", e.g. {"ai":"b","p":"bsrc20","op":"mint","tick":"…","amt":"25000","to":"0x…"} (a rune's records say "p":"bsrunes"); the ops are deploy, mint, transfer, list, cancel, fill, wrap and unwrap. The ledger's balances are the truth and the records describe them; only records from a ledger the factory registered count ## Read API - https://api.bstockrc20.fun (JSON, CORS open, rate-limited per IP): `/inscriptions?q=&status=minting|seeded|closed&sort=lots24h|recent`, `/inscriptions/{tick}`, `/holders/{ledger}`, `/orders/{ledger}?status=open&sort=price`, `/portfolio/{address}`, `/markets`, `/tokens`, `/stats`, `/index-status`. A convenience only: amounts that money depends on are read from the contracts ## Risks - Stock tokens are issued by a third party, which can pause its token or block addresses; while it does, a ledger can neither take nor pay that asset - The platform runs the bStock price oracle that converts a lot price at deploy; a minter sees the resulting fixed price in `quoteFee()` before minting - This site does not offer trading in the United States and its territories, Canada, the United Kingdom, the Netherlands, Japan, comprehensively sanctioned countries and regions, or where the location cannot be determined, and North Korea cannot open it at all; the contracts themselves are permissionless ## Links - [Rules and fees](/rules) - [AI Agent](/ai): the two ways an agent trades here. An agent that runs commands sends each transaction from the person's Binance Agentic Wallet; an MCP client on the person's computer (Claude Desktop, Claude Code, Cursor) uses the local MCP server, which builds and simulates each transaction for their wallet to sign (its README: /agent/README.md) - A hosted, read-only MCP server for assistants that connect by URL (Claude or ChatGPT on the web, as a custom connector): https://mcp.bstockrc20.fun/mcp (Streamable HTTP, no sign-in). It looks up inscriptions, prices, order books, portfolios and transactions and verifies contracts; it builds and sends nothing - bstockrc20 is an independent project, not affiliated with Binance, SPACE ID, PancakeSwap or Uniswap, nor with the issuers of the stock tokens. Nothing here is investment advice