Using CRUMB
The CrumbVault contract
Functions, guarantees, address and verified source of the minimal, immutable, non-custodial vault.
CrumbVault is the only smart contract in the simulation. It is deliberately boring: about a hundred lines of logic, one token, three user functions, zero privileged ones.
CrumbVault · Robinhood Chain
Not deployed yet. The address will be published here and on X.
USDG (official token) · Robinhood Chain
0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168The source is verified on the block explorer, so the code you read there is the code that runs.
Guarantees
Each of these is a property of the code, not a promise from the team:
- No owner, no admin. The contract has no privileged role and no function restricted to anyone.
- Only you can withdraw your balance, and only to your own address. There is no other path that moves USDG out.
- Withdrawals cannot be paused, delayed, locked or charged. There is no pause switch to flip.
- Immutable. No proxy, no upgrade mechanism, no
delegatecall, noselfdestruct. - Deposit caps only limit new deposits. Optional per-wallet and total caps are fixed at deployment and are never checked on withdrawal.
- Exact accounting. A deposit reverts unless the vault receives exactly the requested amount, so recorded balances can never exceed holdings.
Functions
| Function | What it does |
|---|---|
deposit(uint256 amount) | Pulls amount USDG from you (requires a prior approval of at least amount), credits your balance, emits Deposited. |
withdraw(uint256 amount) | Sends amount of your balance back to you immediately, emits Withdrawn. |
withdrawAll() | Sends your entire balance back to you and returns the amount. |
balanceOf(address user) | The amount user can withdraw right now. |
totalDeposits() | Sum of all balances. |
asset(), perWalletCap(), totalCap() | Immutable parameters set at deployment. A cap of 0 means no cap. |
checkpoints(address user) | Your balance history, used by the app to compute the simulation. Also available paginated through checkpointsPaged. |
Errors
| Error | Meaning |
|---|---|
ZeroAmount() | You tried to deposit or withdraw zero. |
InsufficientBalance(requested, available) | You tried to withdraw more than your balance. |
WalletCapExceeded / TotalCapExceeded | A new deposit would exceed an immutable cap. Withdrawals are never affected. |
UnexpectedTransferAmount(expected, received) | The token delivered a different amount than requested. Protects against fee-on-transfer behaviour. |
Security practices
- OpenZeppelin
SafeERC20for every transfer andReentrancyGuardon every state-changing function. - Checks-effects-interactions ordering: balances are updated before any token is moved.
- Custom errors, full NatSpec, fixed compiler version (Solidity 0.8.28).
- A Foundry test suite covering deposits, partial and full withdrawals, multiple users, caps, zero amounts, fee-on-transfer tokens and three reentrancy attack paths using a malicious token.
- Stateful invariant fuzzing: across tens of thousands of random deposit and withdrawal sequences by multiple users, the sum of user balances always equals the vault's token balance, and every user can always withdraw everything.
- A fork test that runs the full deposit and withdraw cycle against the real USDG contract on Robinhood Chain.
A note on checkpoints
The checkpoint list is bookkeeping for the simulation. It never gates a fund movement, and it is written with non-reverting arithmetic on purpose, so that record-keeping can never be the reason a withdrawal fails.