Launch app

Integrate

Borro for desks and bots.

Every market is on Morpho and every position is in your own name. Read the markets as JSON, send transactions straight to the contracts, and run your strategy from a wallet, a Safe or your own executor contract.

Quickstart

Three reads and you are trading. Chain id 4663, your own RPC endpoint, your own keys.

1

Read the registry

/contracts.json has every address, deploy block, code hash, ABI, owner and timelock, and every market's Morpho ids, oracles and LLTVs. Check each code hash against the chain.

2

Read the markets

/markets.json has prices, rates, what is free to borrow and the market clock; /prices.json has route quotes against the feed for arbitrage.

3

Call the contracts

Approve USDG, then BorroShort.open. Watch /health/<wallet>.json or Morpho directly, and close with BorroShort.close.

Open a short with viem
const reg = await fetch("https://borro.markets/contracts.json").then((r) => r.json());
const nvda = reg.markets.find((m) => m.symbol === "NVDA");
const id = nvda.short.market_id;

// quoteSell always reverts with QuoteResult(amount): that revert is the answer.
const gross = await quote(id, "sell", borrowAmount);
const net = gross - (gross * openFeeBps) / 10000n;
const minProceeds = (net * 9950n) / 10000n;                // 0.5% slippage
const deposit = (notionalUsdg * 10000n) / 4000n - minProceeds; // open at 40% LTV

await wallet.writeContract({ address: USDG, abi: erc20, functionName: "approve", args: [BORRO_SHORT, deposit] });
const gas = await pub.estimateContractGas(openCall);
await wallet.writeContract({ ...openCall, gas: (gas * 13n) / 10n }); // add 30%: see Gas
Run it end to end on a fork first
cd examples/typescript && npm install
BORRO_RPC_URL=<your fork> BORRO_API=https://borro.markets fork/e2e.sh
BORRO_RPC_URL=<your RPC> PRIVATE_KEY=0x... node quickstart.ts

The quickstarts cover every flow a desk needs: read the markets, open a short, watch its health, add to its deposit and close it; lend a stock and USDG and withdraw them; borrow USDG against a stock and repay; read the fees paid and Locker Rebates. They take the RPC from BORRO_RPC_URL and have no default. To come: the public link to the examples.

Contracts

The ones a desk calls. The full registry, with ABIs at /abi/<Name>.json, is /contracts.json.

ContractAddressWhat it doesOwnerSource
BorroShort0xd2D686cEdf225c5C9815187A08812783904E62EbOpens and closes shorts in one transaction; positions are keyed to the caller.Hoard SafeVerified
BorroRouter0x85ccddcb0588A434BD57F86A59381E40154650CaLend a stock and post it as collateral for a USDG loan in one call.Hoard SafeVerified
Morpho0x9D53d5E3bd5E8d4Cbfa6DB1ca238AEA02E651010Every market, position, health check and liquidation.MorphoVerified
bUSDG0xF8e0ab443098c0738489B5BAFFbd32A1341F2289Borro's USDG vault: lend USDG.Hoard SafeVerified
Steakhouse USDG0xBeEff033F34C046626B8D0A041844C5d1A5409ddHolds the money behind every short. Curated by Steakhouse Financial, not Borro.SteakhouseVerified
USDG0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168Global Dollar, 6 decimals.Its issuerVerified
BorroLiquidator0x0320edb6543Ba5482dd2e3C626934F0eDD501A4fLiquidates for anyone with no capital of their own.NoneVerified
BorroLock0x2560E389aFEF15D80eFd33e6befaAF017A9eE37f$BORRO locks: the Drip boost and Locker Rebates.NoneVerified
MarketShort market idShort LLTVUSDG loan market idLoan LLTVFeed
Every market's ids, oracles, caps and routes are in /contracts.json.

Every contract here is source-verified on Blockscout, and every one of Borro's own on Sourcify too. Borro's are partial matches: the deployed bytecode is identical to the published source, and only the metadata hash differs.

From the registry.

How a short works on chain

open(id, deposit, borrowAmount, minProceeds, deadline) takes your USDG deposit, holds it as Steakhouse USDG shares, borrows the stock on Morpho for your BorroAccount, sells it through the stock's route, takes the open fee, and holds the sale money too.

  • Morpho checks the borrow against the deposit plus minProceeds, so size the deposit as notional over your target LTV, less minProceeds.
  • close(id, shares, heldOut, topUp, maxCost, deadline) buys the stock back from the money held, repays, and pays the rest out in USDG. Pass the maximum number for all of it.
  • addDeposit, takeDeposit and borrow (the stock to your wallet, unsold) work on the same position.
  • A basket is one multicall of opens: all legs or none.

Where your position lives. Morpho.position(marketId, BorroShort.accountOf(wallet)). The account's address is known before it exists. A USDG loan is your wallet's own Morpho position.

Health. Morpho's own test: collateral times oracle.price() over 1036, times the LLTV, against what is owed. A short is liquidated when the stock rises to its liquidation price; a USDG loan when the stock falls to it.

Lending. Each Borro vault is a Morpho Vault V2: deposit(assets, onBehalf) and redeem(shares, receiver, onBehalf). Stock on loan to shorters cannot be withdrawn until it is returned.

Borrowing USDG. BorroRouter.lendAndPost, then borrow, repay and withdrawCollateral on Morpho directly.

Events to subscribe to

Every event of these contracts, with its fields, is in /contracts.json under events.

ContractEventtopic0Indexed
BorroShortOpened(shorter, id, deposit, borrowed, proceeds, fee)0x7ab3a51df0a150b760784d7ac9684631c3e5b3749cb9256747cbc49d1de6f204shorter, id
BorroShortClosed(shorter, id, returned, cost, paidOut)0x4bcd5ff109723fc19ac22b570e437c0d1ea2d595d26f610b2589bee1f41fe076shorter, id
BorroShortAccountOpened(shorter, account)0x4c85972a811b8f152b75ea02817b25ede88583f498d8da0de57b41bccda176deshorter
BorroShortPaused(id, paused)0xa499c64cb41b6d862c41c8a979bb269a3ec682e7f77aae46a081ecae2984f1e7id
BorroShortRouteQueued(id, v3Pool, readyAt)0x4d0a388a42aea3132c1b0c833aa00ad152edf4fa284543856809e3b2520072b7id
MorphoBorrow(id, caller, onBehalf, receiver, assets, shares)0x570954540bed6b1304a87dfe815a5eda4a648f7097a16240dcd85c9b5fd42a43id, onBehalf, receiver
MorphoRepay(id, caller, onBehalf, assets, shares)0x52acb05cebbd3cd39715469f22afbf5a17496295ef3bc9bb5944056c63ccaa09id, caller, onBehalf
MorphoSupplyCollateral(id, caller, onBehalf, assets)0xa3b9472a1399e17e123f3c2e6586c23e504184d504de59cdaa2b375e880c6184id, caller, onBehalf
MorphoWithdrawCollateral(id, caller, onBehalf, receiver, assets)0xe80ebd7cc9223d7382aab2e0d1d6155c65651f83d53c8b9b06901d167e321142id, onBehalf, receiver
MorphoLiquidate(id, caller, borrower, repaidAssets, repaidShares, seizedAssets, badDebtAssets, badDebtShares)0xa4946ede45d0c6f06a0f5ce92c9ad3b4751452d2fe0e25010783bcab57a67e41id, caller, borrower
BorroRouterLentAndPosted(who, id, stock, assets, shares)0xe205b9b15a06a521cc9b734bce0a570204d4090521073faabaf9962f09220753who, id
BorroLockLockChanged(account, amount, unlockAt)0xac9f677e99a4df77ed2008bfe08de2e751aab75dce03486489e20585d79e91ceaccount
Vault V2Deposit(sender, onBehalf, assets, shares)0xdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7sender, onBehalf
Vault V2Withdraw(sender, receiver, onBehalf, assets, shares)0xfbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8dbsender, receiver, onBehalf

A short's Morpho events name its BorroAccount, not the wallet. To watch a wallet's short liquidations, filter Liquidate by market id and borrower = accountOf(wallet). A USDG loan's events name the wallet itself.

Errors and what they mean

Simulate before you send: a revert comes back by name. Morpho's own reverts are plain strings.

ErrorSelectorMeaningWhat to do
TooLittle(got, wanted)0x618bc7c9The sale brought less than minProceeds after the fee.Quote again; widen slippage or cut size.
TooMuch(cost, limit)0x6073b21fBuying back costs more than maxCost, or more than the money held plus topUp.Quote again; raise maxCost or add topUp.
Expired()0x203d82d8The deadline passed before it landed.Resend with a fresh deadline.
IsPaused()0x1309a563New shorts are paused on this stock.Closing still works.
NotListed()0x665c1c57The market id is not listed.Use the ids in the registry.
NothingOwed()0x797dba54This caller has no position there.Close from the address that opened it.
PoolRanDry()0x76a15698The route could not fill the size.Cut size; check depth in /prices.json.
QuoteResult(amount)0x17080d7eThe answer of quoteSell or quoteBuy, not a failure.Decode the amount.
TooFewShares(got, wanted)0xe2ce129eThe vault gave fewer shares than minShares.Lower minShares.
AbsoluteCapExceeded()0x4616e4afThe vault's cap on its market is full.Deposit less.
"insufficient collateral"Error(string)Morpho: the borrow or withdrawal would pass the LLTV.Add collateral or borrow less.
"insufficient liquidity"Error(string)Morpho: not that much is free to borrow or withdraw.Size to what is free.
"zero assets"Error(string)Morpho: an amount of zero, such as an open with no deposit and no minProceeds.Pass a deposit or minProceeds.

Oracle and weekend rules

Prices are Chainlink's Robinhood feeds: 8 decimals, 24 hours on weekdays, a 0.5% deviation and a 24-hour heartbeat. Each market's Morpho oracle has no owner and cannot be changed.

While the stock market is shut, from Friday 8pm to Sunday 8pm New York time and on market holidays, the feeds pause at their last print and every contract keeps using it: opens, borrows, health checks and liquidations. The first print after a weekend lands at midnight UTC on Monday and can move past a liquidation price in one step.

The site's rule is not on chain. Borro's site sizes a new short at the top of Borro's weekend band and values posted stock at its bottom while the market is shut. The contracts do not enforce that, so a bot that opens on a weekend carries the Monday gap itself.

The clock. /markets.json market_clock gives open, the next close and the reopen. /weekend.json gives the same, and each stock's weekend price and 95% band while the market is shut.

Fees, and Locker Rebates for market makers

  • Open fee: 0.10% of the sale money today, read live from openFeeBps(). The contract caps it at 0.30%.
  • Borrow fee: shorters and USDG borrowers pay the market's Morpho rate to its lenders. Borro's vaults keep 10% of what their lenders earn.

Locker Rebates. Lock $BORRO with at least 30 days left and Borro gives back its own fees on your shorts and loans, weekly in USDG once a dollar or more is owed. Your share is the lock's value over 10% of what you borrow, up to all of it: a $10,000 position needs $1,000 of $BORRO locked for the full rebate.

Round trips get their opening fee back, times your share, however soon they close. A rebate is never more than the fee paid, and round trips are left off the leaderboards. To come: the date rebates start paying.

Limits, caps and liquidations

Liquidation is Morpho's own: anyone can liquidate once what a position owes passes its collateral times the LLTV.

StocksShort LLTVUSDG loan LLTVLiquidation bonus, shortLiquidation bonus, loan
SPY, QQQ77%62.5%7.4%12.7%
NVDA, AAPL, GOOGL, MSFT62.5%62.5%12.7%12.7%
TSLA, MSTR, COIN, PLTR, SPCX, GME62.5%38.5%12.7%15%
  • Caps: each stock vault's cap on what it lends, and Borro's USDG vault's cap on each loan market, are in the registry and live in /markets.json. What you can borrow now is the market's free liquidity.
  • Changes: raising a cap waits 3 days in public; lowering one is immediate.
  • Liquidators: BorroLiquidator does it with no capital of your own, or call Morpho's liquidate. A shortfall a liquidation cannot cover falls on that market's lenders.
  • Watch health: /health/<wallet>.json or the MCP health tool lists every position worst first, with the limit used and the price that liquidates it.

Smart-contract wallets

Every call works from a contract. Positions belong to whoever calls, so a position an executor opens is the executor's.

CallerOn chain$BORRO DripLocker Rebates
Regular walletWorksYesYes, with its own lock
EIP-7702 walletWorksYesYes, with its own lock
SafeWorksYesYes, with its own lock
Executor contractWorksNoYes, with its own lock. Coming: linked to a main wallet's lock.
ERC-4337 accountWorksNo, unless it is a SafeYes, with its own lock. Coming: linked.

Tested on a fork. An executor contract opened and closed a short in one transaction; a Safe batched approve and open; an ERC-4337 smart account opened and closed through user operations; an EIP-7702 wallet batched approve and open; one call opened a two-stock basket.

The Drip is for wallets only: regular wallets, Safes and EIP-7702 wallets. Executor contracts earn no Drip.

Linked executors are coming. Your main wallet, or a Safe through EIP-1271, holds the lock and signs a list of its executor contracts. The lock then covers the wallet and every executor together, their borrowing is added up, and rebates are paid to the main wallet. To come: the address to send the signed list to, and the date it goes live.

Bookrunner borrow bindings need a signature from a wallet's own key today, so Safes and other contracts cannot bind yet.

The JSON API

Public, read only, open to any origin. Described as OpenAPI 3.1 at /openapi.json.

RouteWhat it isNew copyTimestamp
/contracts.jsonThe contract registryPer releasegenerated_at
/markets.jsonEvery market, live60 secondsread_at
/prices.jsonRoute quotes against the feed30 secondsat
/health/<wallet>.jsonA wallet's health and liquidation prices10 secondsread_at
/weekend.jsonThe market clock and weekend prices5 minutesat
/stats.jsonTotals and per-stock numbers5 minutesupdatedAt
/rebates.jsonLocker Rebates statementDailyupdatedAt
  • Every answer carries an ETag: send it back as If-None-Match for a 304.
  • X-Borro-Updated-At and X-Borro-Data-Age say when the data was made and how old it is.
  • /v1/ before any path answers the same; version 1 only ever gains fields.
  • Live answers and the MCP server share one allowance per address with /rpc: 250 units each 10 seconds. Past it, the last good copy or a 429 with Retry-After.
  • For exact integers, read the chain: the JSON gives decimals in whole units.

MCP for agents

An MCP server at https://borro.markets/mcp: tools that read Borro, and tools that prepare unsigned transactions, approvals first, each simulated from the wallet. It never holds or asks for keys.

Connect
claude mcp add --transport http borro https://borro.markets/mcp

Every tool is listed at /tools.json; more on the Agents page.

Gas

Measured on a fork of Robinhood Chain. Add 30% to every estimate.

ActionGas
Approve USDG or a stock58,000 to 64,000
Open a short1,183,000 to 1,197,000
Add to a short's deposit432,000 to 461,000
Close a short545,000 to 556,000
Open and close in one executor transaction1,359,000
Open a two-stock basket1,674,000
Lend a stock / withdraw it262,000 to 290,000 / 221,000 to 263,000
Lend USDG / withdraw it368,000 to 376,000 / 317,000 to 337,000
Lend and post a stock383,000
Borrow USDG / repay / take collateral back197,000 / 79,000 / 71,000

Why the 30%. The vault behind every short accrues interest lazily, and the first transaction in a new second pays for it. On the fork, transactions sent with the plain estimate ran out of gas.

Security, plainly

  • Owner: the Hoard Safe, 0x8A22d6e75e9427b9D57e42a7984200029e7E173C, needs 2 of its 3 signers. It owns BorroShort, BorroRouter and every Borro vault.
  • What it can do on BorroShort: list markets, change a stock's route only after a 2-day public wait, pause new opens (never closes), and set the open fee up to 0.30%. It cannot reach a position, and the code cannot be upgraded.
  • Vaults: raising caps, changing adapters, fees or gates waits 3 days in public. Every timelock is in the registry.
  • No owner: BorroLock and BorroLiquidator.
  • Source: public at github.com/Borro-Markets/contracts. Borro's own contracts are verified on Sourcify and Blockscout, so you can read the exact source of what is deployed; the Morpho-made ones are verified too. Borro's are partial matches: the bytecode is identical to the published source and only the metadata hash differs. Each contract's status is in the registry.
  • Audit: Borro's own contracts have not been audited by an outside firm. They have had internal adversarial reviews, and caps are kept small. An application to the Arbitrum Security Program is in.
  • Morpho: Morpho Blue and Morpho Vault V2 are Morpho's own contracts, audited by outside firms.
  • To come: a security contact for reports.

Status and contact

The chain is the source of truth: every number on this page can be read from it directly. No uptime or response time is promised for the JSON routes or the MCP server.

To come: a status page for pauses, keeper outages and route changes, and a contact for desks. Until then, write to team@borro.markets.