Nine2Five — how it works

An office on Robinhood Chain. Hold $925, take one of 200 desks, and your agent works the shift whether or not you are watching. It is paid in real assets — USDG and tokenised stock — out of a pool that is topped up by hand.

The protocol mints nothing. Every $925 that passes through it is destroyed.


1. The one-paragraph version

Holding 1,000,000 $925 qualifies an address for a desk. A desk has a graphics card, which decides how fast it mines, and a level, which decides which assets it may be paid in. Each epoch — one day — the whole floor shares a pool of real assets, split by mining power. Desks wear out and have to be refurbished. Upgrading, fitting a card and refurbishing all cost $925, and all of it is burned.


2. The two levers, and why they are separate

LeverDecidesCosts
Cardhow much you are paid240 $925 (~$20)
Levelwhat you are paid *in*120 $925 (~$10) per step

This split is the core design decision and it is worth stating why.

Mining power is zero-sum. Your share is your power divided by the floor's power. When everybody

upgrades, every share returns to where it started — so a lever that only sells power is a treadmill that extracts tokens and gives nothing back.

Breadth is not zero-sum. A level-4 desk being paid in NVDAx takes nothing from the desk beside

it. Levelling up buys a *different* reward, not a bigger slice of the same one.

So a level-1 desk with the top card out-earns a level-5 desk with the stock card. That is not a bug; it is the whole point. test_level_buys_breadth_not_power pins it.


3. The numbers

Cards

CardPowerWear / epochCostUpkeep
Ledger 41,0002.0%issued with the desk117 $925 every 33 days (~$9.95)
Quant 8X1,4502.4%240 $925 (~$20)170 $925 every 27 days (~$14.42)
Arbiter 16 Pro2,1003.1%240 $925 (~$20)246 $925 every 21 days (~$20.88)

Both paid cards cost the same deliberately: what separates them is upkeep, not price.

Levels

LevelDeskUnlocksCumulative menu
1Hot deskUSDG, ETH2 assets
2Single screen+ SPYx3
3Dual screen+ AAPLx, MSFTx5
4Trading desk+ NVDAx, TSLAx7
5Corner office+ the rest of the catalogueall

Each tier is cumulative. Which ticker sits in which tier is set on StockDrop and can be changed later — unlike everything in Nine2Five, which has no admin key at all.

Constants

EPOCH             1 day
SEATS             200
HOLD              1,000,000 $925     0.1% of a 1,000,000,000 supply
CONDITION_FLOOR   35%
REFURB_RATE       0.18 $925 per point of power restored

4. The maths

Mining power

condition(t) = max(0.35, 1 − wear_card × (t − refurbishedAt) / EPOCH)
power        = cardPower(card) × condition

Condition falls continuously from the moment a desk is refurbished, and stops at 35%. A desk left at the floor still mines — at just over a third of what it could.

What a refurbishment costs

refurbishCost = cardPower × REFURB_RATE × (1 − condition)

Priced per point of power restored, so there is no clever moment to do it: the cost per point never changes. What changes is whether it is worth it, which depends entirely on the floor.

A tidy consequence: the recurring upkeep of a desk per day is

cardPower × REFURB_RATE × wear

The (1 − condition) and the cycle length cancel out. That is where the upkeep column above comes from.

Your share of a drop

share_i  = cardPower_i × condition_i / Σ cardPower_j
payout_i = pot × share_i

Note the denominator: rated power, with no condition in it. This is not a typo and it is not the

obvious formula.

The obvious formula — dividing by condition-weighted power so shares always sum to 100% — turns wear into a transfer from worn desks to fresh ones. Here, wear is a cost the desk pays and nobody else collects: when desks are worn, the shares sum to *less* than the pot and the remainder is simply not committed. It stays in the pool and lengthens the runway.

tools/check-drops.mjs pins this: a fresh desk is paid exactly the same whether its neighbour is

worn or not.


5. The reward pool

The protocol pays in assets it does not create. The pool lives in StockDrop, is funded in USDG by hand, and is drawn down by the publisher once per epoch.

Funding

$200 a week, from two sources. The dev, and the creator fee that $925 earns on Pons. Neither is

enforced on chain; both are manual transfers.

Player fees do not fund the pool. Every $925 spent on a desk is burned outright, so the money that leaves a player's wallet leaves the supply — it does not come back as a reward.

Why it does not run out

StockDrop releases at most 5% of a bucket's free balance per day. Funded once, that decays;

topped up at a steady rate X, it settles where inflow equals outflow:

0.05 × P = X   →   P = 20X

A pool holds twenty days of its own income. At $28.57/day in, it settles around $571 and pays

$28.57/day forever.

WeekPoolPaid that week
1$163.76$36.24 (18%)
2$278.12$85.64 (43%)
4$413.75$144.23 (72%)
8$512.15$186.74 (93%)

Two months to within 10% of the ceiling. Week one pays a third of what month three pays, and that is the mechanism working, not a shortfall. Seed the pool with $571 up front if you want it full on day one.

What to convert the USDG into

Not everything, and not on arrival. conversionPlan() in tools/publish-drops.mjs reads the levels actually sitting at the desks and prints the split every run. A desk contributes its rated power evenly across every asset its level opens, which is the *expected* demand rather than one epoch's draw — stable enough to buy against.

A floor of level-1 desks asks for nothing but tier 1. Higher tiers only start drawing budget once somebody has levelled into them, so no money is parked in a token nobody can receive.


6. Worked example — a floor of 20

7 × L1 Ledger, 3 × L1 Quant, 4 × L2 Ledger, 2 × L3 Quant, 2 × L4 Quant, 1 × L4 Arbiter, 1 × L5 Arbiter. Total rated power 25,350. Pool at steady state, paying $28.57/day.

DeskSharePer dayPer month
Ledger 43.945%$1.13$33.81
Quant 8X5.720%$1.63$49.03
Arbiter 16 Pro8.284%$2.37$71.01

Note that level does not appear. The L1 Quant and the L4 Quant earn exactly the same amount — they differ only in which tickers that amount can arrive as.

Net of upkeep

CardIncomeUpkeepNet
Ledger 4$1.13$0.31$0.82
Quant 8X$1.63$0.53$1.10
Arbiter 16 Pro$2.37$1.00$1.37

Payback on a card

CardExtra per day vs LedgerPays back in
Quant 8X$0.5140 days
Arbiter 16 Pro$1.2416.5 days

7. A known problem with the card table

At the same price, the Arbiter beats the Quant on every axis: higher income, higher net, faster payback. The Quant's only advantage is a smaller absolute upkeep bill, which matters only to someone who cannot carry $1 a day.

So as the table stands, the middle card is dead and the choice it was meant to create does not happen. Two ways to fix it, neither applied yet:

1. Price them apart — Arbiter at 480 $925 instead of 240. 2. Make the Arbiter run hotter — wear at 3.94% an epoch instead of 3.1% puts its net exactly level with the Quant's, which makes the decision about appetite for upkeep rather than arithmetic.

Both are one-line changes in Nine2Five.sol, and both must happen before deploy.


8. Supply

$925 is a fixed-supply token launched on Pons. Nine2Five cannot mint, has no mint function, and holds no balance of it.

What the protocol does to supply:

It never touches the contract's balance, so there is nothing to withdraw and no function to withdraw with.

No transfer, no deposit, no lock. A holder keeps every token and can sell at any moment; they lose the seat, not the money.

A full floor of 200 desks represents 200,000,000 $925 held in private wallets — 20% of supply, none of it in a contract.


9. The contracts

Nine2Five.sol

Decides who has a desk, how fast it runs, and what it may be paid in. Burns fees. Pays nothing.

No owner, no admin key, no upgrade path, no withdraw. Everything in it is fixed at deploy except the desks themselves.

FunctionWhoDoes
claimSeatanyone holdingtakes a free desk
upgradeseated+1 level, burns 120 $925
fitCardseatedswaps the card, burns 240 $925, carries condition across
refurbishseatedcondition back to 100%, burns the cost
setLookseatedcharacter, skin, nickname
leaveSeatseatedgives the desk up
evictanyonefrees a desk whose holder has sold below the threshold
floor / agentviewthe whole office, for drawing it and for splitting a drop

StockDrop.sol

Holds the pool and pays it out against cumulative merkle roots.

Has roles: an owner (manages the catalogue and can withdraw unallocated balance after 48 hours), a publisher (commits roots), and a guardian (can veto a root within 30 minutes).

tierOf records which desk level each asset is reserved for. Nothing in claim reads it — and

that is deliberate. A drop is earned across an epoch at the level the desk held *then*, so a check at claim time would get both ends wrong: an address that levels up afterwards would collect an asset it never earned, and one that leaves its seat falls to level 0 and would lose a drop it did earn. The rule belongs in the publisher, and tierOf is what lets anyone audit a published tree against it. test_claim_does_not_read_the_tier exists to stop someone "fixing" this.


10. Running it

Deploy

TOKEN_925=0x…  OWNER_ADDRESS=0x…  PUBLISHER_ADDRESS=0x…  GUARDIAN_ADDRESS=0x…
forge script script/Deploy.s.sol --rpc-url rh --broadcast

Optional: SEATS (200), HOLD_AMOUNT (1,000,000e18).

The office needs no funding. StockDrop does: send it USDG, and the stock tokens for whichever tiers the floor has reached.

Publish a drop

OFFICE=0x… DROPS=0x… node tools/publish-drops.mjs              # dry run
OFFICE=0x… DROPS=0x… PUBLISHER_KEY=0x… node tools/publish-drops.mjs --publish

Writes public/drops.json (the proofs the page fetches) and tools/.drops/ledger.json.

The ledger must survive between runs. Roots are cumulative; if it is lost, the next tree promises

less than the last one did, publish() refuses the lower total, and anyone mid-claim is stranded.

.github/workflows/drops.yml runs this daily and commits the ledger back for exactly that reason —

do not swap it for a cache that can be evicted.

Watching a desk from a terminal

A holder does not have to open the app to see their agent. The panel gives them one line to paste:

curl -fsSL https://nine2five-sigma.vercel.app/watch.mjs -o watch.mjs && node watch.mjs n25_<key>

It prints the desk, its energy, mining power, share of the floor, what it earns a day, what is waiting to be pulled, and the state of the floor — refreshing on a timer until stopped.

The key is the holder's public address, base64url'd so it is short enough to paste. It is not a

secret and it cannot sign: watch.mjs makes eth_call reads and nothing else, has no wallet code in it at all, and never prompts for anything. Nothing in Nine2Five will ever ask a holder to paste a private key, and the script says so in its own header.

The script has no dependencies. It speaks JSON-RPC over fetch and decodes the handful of return values by hand, so it runs on a bare Node install with nothing to audit but the one file. Function selectors are hard-coded because that is cheaper than shipping a keccak implementation to compute four constants.

tools/check-drops.mjs checks the key against both implementations — the encoder in the page and

the decoder in the script never import each other, which is exactly where a format quietly drifts.

Checks

npm run check        # 11 browser and logic checks
npm run check:drops  # the publisher's money maths, no browser
cd contracts && forge test

11. Still open