Built on Robinhood Chain

Cusp

Deposit into a vault, hold a plain ERC-20, redeem at the price the contract computes. Cusp also prints the thing every other vault rounds away: the staircase between what you paid and what you were issued.

24 properties, executed on chain Deploys from your wallet No key, no proxy, no backend
A vault over USDG cu-USDG · 6 decimals Executed
Deposited1 USDG
Shares minted1,000,000,000,000
Redeemed back1 USDG
Read atblock 55,463,157

Not a mock-up. Every byte of that came from js/vault.js — the module this site's app imports — executed against real USDG on Robinhood Chain the last time this page was built.

ERC-4626 accounting Transferable share token No lockup The step shown before you sign

The problem

A share price is quoted as a number. The contract uses a staircase.

Between the assets you send and the shares you are issued sits one integer division, and it has a floor. A whole interval of deposit sizes mints exactly the same number of shares, and you pay for the top of the step. Every vault in this category has one. None of them will tell you how wide it is.

What the page says

One share is worth totalAssets / totalSupply

  • Printed to four decimals, as though the price were a real number.
  • Silent about the smallest deposit that mints anything at all.
  • Silent about the parameter that sets the width — which is not the one you would guess.

What the contract does

Shares are the floor of that, always

  • step() returns the exact interval you are standing on, and a property deposits at both ends to prove it.
  • dust() returns the largest deposit that mints nothing. A property sends exactly that and counts zero back.
  • The app shows you both before you sign.

Measured on Robinhood Chain

Seed a vault with a thousandth of a token and the grid never recovers

The same vault, the same 1000 USDG in it, one constructor argument apart. The dead zone is the largest deposit that is accepted, transfers your money in, and issues you nothing.

0.999USDG you can deposit and be issued nothing at all, with the virtual offset switched off
619.38062USDG you must deposit before rounding costs you under one basis point
0.000001the same figure with the offset at 6 — the parameter every audit asks for
619,380,620×between those two numbers, from one argument nobody explains this way

USDG is the most-transferred contract on this chain — 74,029 transfers in the sampled windows — and it has 6 decimals. How that was measured →

Two locks, one door

The attack everyone hardens against is already closed by the accounting

The virtual offset is sold as protection against the ERC-4626 inflation attack. So we ran the attack, four times, on this chain's own EVM: assets tracked in storage or read from the token balance, crossed with the offset off and on. The attacker takes the first share for one wei, donates, and the victim deposits after.

AccountingVirtual offsetVictim keepsVerdict
Tracked in storage0100.0000%defended
Tracked in storage6100.0000%defended
Read from balanceOf00.0000%wiped out
Read from balanceOf699.9999%defended

Either defence alone is enough. Tracking assets in storage closes the attack with the offset switched off entirely — 100.0000% recovered — which is what the fourth property asserts. So the offset is a second lock on a door that is already shut, and its measurable effect is somewhere else entirely: it is what keeps the staircase above from being a cliff. The four runs, and the contract they ran →

What Cusp is

A vault, its token, and the arithmetic underneath both

The vault

An ERC-4626 vault over any ERC-20 on Robinhood Chain. Assets are tracked in storage, so a stray transfer moves nobody's price. The protocol cut applies to harvested income only and is capped by a constant.

  • 24 properties executed on this chain, not asserted
  • 11 deliberate defects, each one confirmed caught
  • The owner has no path to principal

The fold

Three view functions no other vault exposes. dust() is the largest deposit that mints nothing, step() is the exact interval you are standing on, and foldLoss() is what it costs you.

  • Exact, not estimated — proved by real deposits at both ends
  • Shown in the app before you sign
  • 18 rows measured, 8 of them re-executed on chain

Your keys, your deploy

The app deploys the vault from your own address. Every write is an ordinary signed transaction, simulated from your address first. There is no key, no relayer and no backend anywhere in this repository.

  • No API key and no proxy — the public node allows the browser directly
  • 14 checks of the app's own calldata against real USDG and WETH
  • 7,961 bytes of creation code, from the compile that proved it

Markets

Any ERC-20 on this chain, and these are the ones being used

Discovered by counting 293,800 transfers across 4,167 contracts, not from a list. Decimals are read from each token, because decimals is what decides how small a first deposit can be — and therefore how coarse a grid it can leave behind.

USDGGlobal Dollar 6dec
WETHWETH 18dec
SPCXSpace Exploration Tec… 18dec
SPYSPDR S&P 500 ETF Trust 18dec
ZZZZZZ 18dec
NVDANVIDIA 18dec
TSLATesla 18dec
GMEGameStop 18dec
SLINKShivolink 18dec
SGOViShares 0-3 Month Tre… 18dec
AMCAMC Entertainment 18dec
UPSUPS 18dec
PLTRPalantir Technologies 18dec
QQQInvesco QQQ 18dec
DJTTrump Media & Technol… 18dec
BABAAlibaba 18dec
GLDSPDR Gold Trust 18dec
AMZNAmazon 18dec
METAMeta Platforms 18dec
INDAiShares MSCI India ETF 18dec
MSTRStrategy Inc. 18dec
SLViShares Silver Trust 18dec
RBLXRoblox 18dec
IBMIBM 18dec

How the list was built

How it works

Four calls, and you can read every one

STEP 01

Deploy

Pick an asset and an offset. The app builds the creation code, predicts the address, and your wallet signs. The vault is yours; you are its owner.

STEP 02

Approve and deposit

Before the deposit is signed, the app reads step() from your vault and shows you the interval your amount lands on, and what the top of it costs.

STEP 03

Hold the share

You get an ordinary ERC-20 back. It transfers like any token, and harvested income raises what every share redeems for.

STEP 04

Redeem

Burn shares, take the underlying at the current price. No lockup, no queue, no epoch, and rounding that never favours the vault by more than the wei it is owed.

What the contract guarantees

24 properties, executed rather than claimed

Each one runs on Robinhood Chain's own EVM through an eth_call state override, on every build, at block 55,462,976. Then the contract is broken 11 ways and each defect has to be caught — 10 by a property, and 1 by nothing but a mechanical read of the compiled ABI.

The fold is exact

P18 sends exactly dust() and requires zero shares back, then one wei more and requires exactly one. P19 deposits at both ends of step() and one wei outside each.

Rounding never favours the holder

P2 checks eight sizes from one wei up. A vault that rounds the other way is a slow drain on everybody already in it, and it is invisible per trade.

Nothing reaches the principal

P12 asks collect for one wei more than has accrued and requires a revert. The added-rescue() sabotage breaks no property at all — only the ABI surface check sees it.

A stray transfer moves no price

P3 sends 900 tokens straight to the vault and requires the share price not to move by one wei. Assets are tracked, never read from the balance.

All 24 properties and all 11 sabotages

FAQ

The short answers

What is the fold, in one sentence?
The set of deposit sizes that mint the same number of shares. It exists because assets → shares is an integer division with a floor, and it is as wide as one share is valuable.
Is this a real contract or a diagram?
Real. contracts/Cusp.sol compiles with solc 0.8.26 and its 24 properties execute on Robinhood Chain on every build. It is not deployed to a fixed address and has not been audited; the app deploys it from your own wallet.
Is there a token?
No. There is no Cusp token, no contract address to copy, and no presale. The only tokens here are the share tokens your own vault mints.
So should I set the offset high?
On rounding, yes — a larger offset strictly narrows the dead zone, which is property 21. It is not free in every direction: the conversion multiplies by 10offset, so the bound in the constructor is 12 and anything above it reverts rather than being clamped.
What does the site actually measure?
Two things. The fold, over the assets that are really on this chain and their real decimals — 18 rows, 8 of them re-executed against the contract. And the inflation attack, four times, to check whether the offset is doing the job it is sold for.

More questions