📄 🦆 📐 📄

ducs docs

~ * ~ Every door in the company ~ * ~
*** THE MANUAL FOR A COMPANY WITH NO EMPLOYEES *** EVERY FUNCTION *** EVERY CONSTANT *** EVERY NUMBER IT KEEPS *** AND HOW TO CHECK ALL OF IT YOURSELF ***

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% chance1.09x
49% chance2.00x
25% chance3.92x
10% chance9.80x
1% chance98.00x

what the company remembers

Six numbers, and an identity that has to hold after every single call.

bookthe company's own money. Player stakes are not part of it.
reservedthe 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.
stakedstakes held for open bets. Player money, not company money.
retainedprofit earned and not yet streamed to shareholders.
divPooldividends already streamed and not yet claimed.
capitalmoney 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 price0.0001 ETH
EDGE_BPS, the house edge200 (2.00%)
MIN_BET, smallest stake0.01 ETH
MAX_RISK_BPS, one bet100 (1% of book)
MAX_TOTAL_RISK_BPS, the table500 (5% of book)
WIN_MIN_BPS / WIN_MAX_BPS100 / 9000
SETTLE_DELAY, blocks to the die10 (about 1s)
SETTLE_WINDOW, blocks to reveal200 (about 20s)
BOUNTY, the settlement fee0.0001 ETH
VEST, the dividend stream1 hour
SUPPLY_FLOOR, smallest position1 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.