what it is
One contract on Robinhood Chain, chain id 4663. That contract is the entire company: its capital, its business, its books and its rules. There is no server, no admin key, no upgrade path and no second contract.
It does three things. It sells its own shares to anyone who sends it money, at net asset value. It runs a dice house with a two percent edge fixed in the code. It pays what it earns to shareholders, continuously, without anyone deciding to.
Nothing is minted at deploy. There is no founder allocation, no treasury and no fee address, because there is no function anywhere in the contract that can create a share for someone who did not pay net asset value for it.
the four doors money uses
Money enters through share purchases, player stakes and gifts. It leaves through exactly four doors, and every one of them is a number the contract works out for itself.
buy(uint256 minShares) payable
Send ETH, receive shares. Priced at the book plus retained earnings, divided by shares outstanding, so a latecomer pays for the slice of the pot they are about to start receiving. minShares is your floor: the call reverts rather than giving you fewer. The first ever purchase prices at 0.0001 ETH per share. Every position must be a whole share or nothing.
redeem(uint256 shares)
Burn shares, receive their slice of the book net of every bet still on the table. No lockup, no notice and no permission: the company cannot refuse. Leaving mid-hand means leaving at the worst case of that hand, and leaving mid-stream forfeits the unvested part of your retained earnings to the holders who stay. The last holder out takes the retained earnings with them, and cannot leave while a bet is live.
claim() · claimFor(address holder)
Take the dividends that have streamed to you so far. claimFor lets anyone push someone else's dividends to them, which matters because share tokens end up in contracts that have never heard of a dividend. A stranger can deliver your money. A stranger can never turn it into anything other than your money: if the push does not land, it waits under your name for withdrawHeld().
settle(uint256 id, bytes32 secret)
The fourth door is a winning bet. Revealing your secret finishes the hand, pays the winner, and pays whoever called it a flat settlement fee of 0.0001 ETH.
There is no fifth door. No owner withdrawal, no fee sweep, no emergency exit, no migration.
the house
The one business, and the only place the company's money comes from.
bet(uint256 winBps, bytes32 commit) payable
Stake ETH on a chance you choose, between 1% and 90%, expressed in basis points. The payout is stake * 9800 / winBps, which is a fair game minus two percent at every price. commit is keccak256(secret) for a secret only you hold, and a secret is never accepted twice from the same address. Returns the bet id.
The whole payout it could ever owe, plus the settlement fee, is placed under a lien on the book right there. One bet may put at most one percent of the book on the line, and every open bet together at most five percent.
the die, and why neither side can pick it
The roll is keccak256(dieHash, secret, id, player) % 10000, and you win if it lands under winBps.
dieHash is the hash of L2 block now + 10, which does not exist when you commit, so the player cannot see it. secret is yours alone, so whoever assembles that block is grinding blind. Compromising the roll needs both halves at once.
forfeit(uint256 id)
After the window closes, anyone may sweep a bet whose secret was never revealed. The stake goes to the shareholders and the caller takes the settlement fee. This has to cost the whole stake: a refund would make silence a free option, because a player who computed the roll and lost would simply never reveal.
what it pays
| 90% chance | 1.09x |
| 49% chance | 2.00x |
| 25% chance | 3.92x |
| 10% chance | 9.80x |
| 1% chance | 98.00x |
what the company remembers
Six numbers, and an identity that has to hold after every single call.
book | the company's own money. Player stakes are not part of it. |
reserved | the slice of the book that open bets could take. A lien, not a transfer: the money is still the company's and still in the book, but it cannot be redeemed out from under a live bet. |
staked | stakes held for open bets. Player money, not company money. |
retained | profit earned and not yet streamed to shareholders. |
divPool | dividends already streamed and not yet claimed. |
capital | money contributed by shareholders and not yet returned. Equity above this line is profit. |
address(this).balance == book + staked + retained + divPool + unclaimed
An invariant suite throws random sequences of every action at the contract and checks that identity after every step, to the wei. Profit is defined as (book - reserved) - capital, and the moment it exists it stops being the company's and becomes the shareholders', through retained and then the stream.
reading the books
navBuy() | what one whole share costs on the way in, in wei. |
navRedeem() | what one whole share is worth on the way out: the book net of every bet still on the table. |
maxRisk() | the largest exposure a single new bet may add right now. |
withdrawableOf(address) | the dividends that holder can take this second. |
sync() | bank any new profit and release the slice of retained earnings this moment is owed. Every money path calls it; it is public so anyone can keep the stream flowing. |
skim() | fold ETH that arrived outside the doors into the book, where the stream turns it into dividends. |
the charter
Constants in the source. No constructor arguments, no setters, no governance. This is what the company is for as long as the chain runs.
| PAR, the first share price | 0.0001 ETH |
| EDGE_BPS, the house edge | 200 (2.00%) |
| MIN_BET, smallest stake | 0.01 ETH |
| MAX_RISK_BPS, one bet | 100 (1% of book) |
| MAX_TOTAL_RISK_BPS, the table | 500 (5% of book) |
| WIN_MIN_BPS / WIN_MAX_BPS | 100 / 9000 |
| SETTLE_DELAY, blocks to the die | 10 (about 1s) |
| SETTLE_WINDOW, blocks to reveal | 200 (about 20s) |
| BOUNTY, the settlement fee | 0.0001 ETH |
| VEST, the dividend stream | 1 hour |
| SUPPLY_FLOOR, smallest position | 1 whole share |
the share token
A plain ERC20 called DUCS with eighteen decimals, so any wallet or exchange can hold it. It carries its dividend entitlement through transfers, which means the entitlement moves with the share and is never stranded on an old address.
Three rules are stricter than a normal token, and each closes an attack:
- Shares cannot be sent to the zero address or to the contract itself. A burn-shaped transfer that is not a burn confuses everything downstream, and a company cannot be its own shareholder.
- Every position is a whole share or nothing, on buying, selling and transferring alike. Dust supply would let one wei of dividend inflate the per-share accumulator past what a word can hold, and there is no owner to fix it afterwards.
- Self-transfer is a no-op rather than an accounting event.
check it yourself
Nothing here asks to be believed.
the code is the code
Hash the bytecode living at the address and compare it to the seal:
cast keccak $(cast code <address> \ --rpc-url https://rpc.mainnet.chain.robinhood.com)
The source is published at the address itself on the block explorer, which is where you read it. There is no repository to trust instead.
there is no owner
Look for a function that lets anyone move money, change a number or stop the company. There is not one. That is the whole security model and it is checkable in a minute.
the dice are the chain's
Play a hand on the front page, take the block number it prints, and ask the chain for that block. The hash it returns is the die the page used, and the roll is the contract's own line recomputed in your browser.
honest edges
- Twenty seconds to reveal. That window is the chain's, not a choice: it is roughly how long Robinhood Chain keeps a block hash reachable. The winner is the party most motivated to act and the interface reveals for them, but a player who walks away mid-hand forfeits.
- A spread while a hand is live. Entry is priced on the book and exit on the book net of open bets. The gap is the company's exposure, never more than five percent, and it exists only for the seconds a bet is unsettled. It always favours the shareholders who stayed.
- Leaving mid-stream costs the unvested part. Dividends pay down over an hour. Redeem before your share has streamed and the rest stays with the holders who remain, the same way leaving before a record date works.
- A stranger can crowd the table. Cheap tickets at long odds can put a few percent of the book under lien for the length of the settlement window, which marks down redemptions in that window. It costs them the edge every time and the window is seconds, but it is a real nuisance and the caps are what bound it.
- Exotic wallets may need to pull. A payout is pushed with a 50,000 gas stipend and waits under your name if the push does not land.
- Immutability cuts both ways. There is no owner to fix a mistake, which is why the surface is this small, the suite is this heavy, and the audits were adversarial.