Docs

How Gage works

Gage is a website. It deploys no contract. The lending is Morpho Blue, one-transaction Multiply runs on Morpho's own Bundler3, trading is Uniswap, the pooled savings vault is Steakhouse Financial's — all already deployed on Robinhood Chain (chain id 4663). Every number in the app is read from those contracts when the page loads; every button sends a transaction from your own wallet, simulated first, with approvals for the exact amount only.

Getting started

You need a wallet (Rabby, MetaMask, Coinbase Wallet, Trust — on a phone, open Gage in the wallet app's own browser) and ETH on Robinhood Chain. Robinhood's bridging guide lists the routes in; the canonical one is the Arbitrum bridge from Ethereum (about 10 minutes), with faster partner routes such as Relay and Across. Everything in Gage is priced in USDG: swap some ETH for it in the Trade tab, through Uniswap's deepest USDG pool on the chain. Selling "Max" keeps 0.0003 ETH back for gas.

Borrowing

A Morpho market is five facts fixed forever at creation: the token lent (always USDG here), the collateral, an oracle that prices it, an interest-rate model, and a liquidation threshold (LLTV). Gage lists every market that lends USDG against a stock it can trade or an allowlisted dollar token (USDe, syrupUSDG, mGLO) and has at least $1,000 free to borrow — so a stock with two funded markets shows both — plus, for each other stock, its best-funded small market, marked as needing lenders. Morpho's API is used only to find candidates; each one's parameters are read back from Morpho at a pinned block and its id re-derived (tools/scan-lending.mjs).

The Borrow tab calls Morpho directly from your wallet — supplyCollateral, borrow, repay, withdrawCollateral. Gage refuses to send a loan above 90% of the market's LLTV. "Repay the whole loan" repays by shares, so no dust of debt is left; its approval covers two extra minutes of interest and no more.

Multiply: one transaction through Morpho's Bundler3

Morpho's Bundler3 runs a list of calls in one transaction; its GeneralAdapter1 performs Morpho actions for whoever sent that transaction (its initiator). Both are Morpho's audited contracts, already live here: GeneralAdapter1 reports this chain's Morpho and this Bundler3 as its own. Gage only builds the list of calls, in js/bundles.js — the same file the tests load.

Open. You approve the adapter for exactly your USDG. The bundle pulls it into Bundler3, flash-borrows the extra USDG from Morpho, swaps all of it into the stock on Uniswap (exact approval, paid to the adapter), pledges every share to your position, and borrows the flash amount back against it. Your slippage limit is the minimum number of shares; below it nothing happens.

Close. The bundle flash-borrows your debt plus a 0.1% cushion, repays every borrow share, withdraws your collateral, sells only the shares needed (capped by your slippage limit), returns every other share, and sweeps the leftover dollars to you. A repaid loan needs no price, so closing works even while a price feed is paused.

Authorisation. Borrowing or withdrawing on your behalf needs setAuthorization(GeneralAdapter1, true) from your own wallet, once — the same step Morpho's own app asks for. The adapter can then act only inside bundles you send. Revoke from the Multiply tab or with setAuthorization(GeneralAdapter1, false).

Fork checks
Sabotage
Real app clicked through
Gas
Builder source hash

tools/test-bundles.mjs sends the bundles js/bundles.js builds through the live Bundler3, adapter, Morpho and Uniswap on a fresh fork, including thirty days of real interest, a second market, slippage and liquidation-threshold refusals, a stranger trying to reach someone else's loan or leftover approval, and a close after the price feed has gone stale; after every bundle it checks that the adapter and Bundler3 hold nothing and that no allowance is left. tools/sabotage-bundles.mjs breaks the builder on purpose — no final sweep, leftover shares kept, a doubled approval, shares pledged to the adapter, every share sold — and requires each to be caught, with the unmodified builder as a control. tools/e2e.mjs then clicks through the real page with a test wallet.

Price feeds

Each market's oracle decides liquidation, and Morpho asks it on every borrow and on every collateral withdrawal while a loan is open. Some oracles refuse a price that has gone stale. Measured on a fork by moving time forward (tools/scan-oracles.mjs):

When a feed refuses, the app says so on that market and holds back what needs a price — new borrowing, and taking collateral back while a loan is still open. Repaying, pledging, lending, and taking everything back once repaid keep working. Most stock feeds update with market hours, so a refusal usually means the stock market has been shut for a while; borrowing resumes at the next update.

Addresses

Risks

  • Liquidation. When a loan's value falls to the market's LLTV at the oracle price, anyone may repay part of it and take collateral plus an incentive. The liquidation price the app shows is where that begins.
  • Paused feeds. See above: while a feed refuses, you cannot add to a loan against it — plan for that before a weekend.
  • Liquidity. You can borrow, and lenders can withdraw, only what a market has free. Several stock markets are small; the app shows exactly how many dollars are free in each.
  • Bad debt. If collateral falls faster than liquidators act, lenders in that market absorb the shortfall.
  • Leverage. Multiply magnifies both gains and losses and brings the liquidation price closer.
  • Issuers. A tokenized stock is its issuer's claim on the share; USDe, syrupUSDG and mGLO are Ethena's, Maple's and Midas's products, with their own terms and risks.
  • Smart contracts. Morpho Blue, Bundler3, GeneralAdapter1 and Uniswap are code. Tested is not the same as risk-free.

Credits

Ground photograph: “Old wood, wild flower and city lights” by Paulo Valdivieso, licensed CC BY-SA 2.0; blurred and recoloured for this site, and the adapted image is shared under the same licence. See credits.