
Short version. A rig is an NFT. It earns ETH only while online. It is online only while it burns $RIG. The ETH is Pons creator fees pulled from an escrow contract. Nothing is emitted. Everything below is a description of contract behaviour, not a projection.
A rig is one ERC-721 token in RigsNFT. The collection is capped at 2,000 by a constant, MAX_SUPPLY, with no function to raise it. Mint price 0.01 ETH · PROPOSED, maximum 10 per wallet · PROPOSED. There is no whitelist and no team reserve. Every rig starts at hashpower 1 and offline.
MAX_PER_WALLET is a soft limit. It counts mints per address at mint time, and nothing stops one person from minting from several addresses or buying rigs on the secondary market. It spreads the first distribution; it does not cap ownership.
Mint ETH goes to the protocol wallet. It funds the launch of the first basket tokens and infrastructure. It is not revenue for rigs and it never enters the pool.
The NFT carries ERC-2981 royalty metadata of 5% · PROPOSED with the pool as recipient. Whether a marketplace honours it is up to the marketplace.
refuel(rigId, amount) transfers amount of $RIG from the caller to 0x000000000000000000000000000000000000dEaD and extends the rig's onlineUntil by amount × 1 day / FUEL_PER_DAY. If the rig is already offline the extension starts from now, not from the old expiry, so idle time is never credited.
function refuel(uint256 rigId, uint256 amount) external {
rigToken.transferFrom(msg.sender, 0xdEaD, amount);
uint64 base = max(rig.onlineUntil, block.timestamp);
uint64 ext = uint64(amount * 1 days / FUEL_PER_DAY);
if (base + ext > block.timestamp + MAX_ONLINE_AHEAD) revert FuelExceedsCap(maxRefuel(rigId));
rig.onlineUntil = base + ext;
}Refuels below MIN_FUEL, one hour of fuel, revert with BelowMinimumFuel. The extension is rounded down to whole seconds and exactly that many seconds are charged; the remainder stays in your wallet. Fuel that would push a rig past now + 30 days is refused with FuelExceedsCap. It reverts. It never burns $RIG for time the rig cannot hold. maxRefuel(rigId) returns the exact amount that fills the rig to the cap, and the dashboard sizes refuels from it. The burn is checked by balance delta at 0xdEaD, so a fee-on-transfer token is refused.
Rate 10,000 $RIG per 24 h · PROPOSED, cap 30 days ahead · PROPOSED. Anyone may refuel any rig; the burn is charged to the caller. The burned total is the balance of the dead address, readable by anyone.
A rig whose onlineUntil is in the past has zero hashpower in the next settle. Not reduced. Zero.
Hashpower is the weight of a rig in a settle. It starts at 1 and can be raised to 10 by calling upgrade(rigId), which burns upgradeCost(level + 1) of $RIG. Upgrades are permanent, stored on the rig, and travel with the NFT. There is no downgrade path and no decay.
| level | burn to reach | status |
|---|---|---|
| 2 | 50,000 $RIG | PROPOSED |
| 3 | 100,000 $RIG | PROPOSED |
| 4 | 175,000 $RIG | PROPOSED |
| 5 | 275,000 $RIG | PROPOSED |
| 6 | 400,000 $RIG | PROPOSED |
| 7 | 600,000 $RIG | PROPOSED |
| 8 | 900,000 $RIG | PROPOSED |
| 9 | 1,500,000 $RIG | PROPOSED |
| 10 | 2,500,000 $RIG | PROPOSED |
claim(rigId) and claimAll are restricted to the rig's owner or an approved operator; the ETH goes to the owner. Both refuel(rigId, amount) and upgrade(rigId) are callable by anyone for any rig. The caller pays the burn; the rig gets the benefit. That is how you gift fuel or a level to someone else's machine, and there is no way to take it back. Upgrading does not put a rig online. A level 10 rig with no fuel earns exactly what a level 1 rig with no fuel earns. The metadata emits ERC-4906 MetadataUpdate so marketplaces refresh the render.
Pons V2 charges a fee on every trade of a token it launched and credits the creator's share to a pull-based escrow, V2FeeEscrow. The recipient calls claim() to withdraw ETH and claimToken(token) to withdraw ERC-20 fees. RigsPool is the creatorFeeRecipient of every token in the basket, so those fees accumulate under the pool's address in the escrow.
interface IPonsV2FeeEscrow {
function claim() external returns (uint256 amount);
function claimToken(address token) external returns (uint256 amount);
function balanceOf(address recipient) external view returns (uint256);
}harvest() is permissionless. It calls escrow.claim() and, where a route is allowlisted, converts ERC-20 fee tokens to ETH with a slippage bound v1 may hold tokens and distribute ETH only · PROPOSED. The keeper runs it once per epoch; anyone else may run it sooner.
The basket has three sources: tokens the protocol launches with the pool as recipient, $RIG itself, and any third-party Pons V2 token whose deployer calls transferCreatorFeeRecipient to the pool. A token is listed on /basket only after that read returns the pool address.
settle() runs at most once per epoch of 24 h · PROPOSED. It pulls the fees from the escrow itself, then splits them across every rig by weight, where weight is hashpower times the seconds the rig was online during the epoch. The share is written to the rig's earned balance; claim(rigId) pays it out. pendingRevenue() shows what the next settle will distribute.
// each rig packs onlineFrom, onlineUntil, banked (hashpower-seconds already accrued this epoch)
weight(id) = banked + hashpower * max(0, min(onlineUntil, now) - max(onlineFrom, lastSettle))
function settle() external {
require(block.timestamp >= lastSettle + EPOCH);
pull ETH (and basket fee tokens) from the Pons escrow // settle harvests itself
uint256 revenue = pendingRevenue();
uint256 total = 0; // pass 1: sum weights
for (id = 1..totalSupply) total += weight(id);
if (total == 0) { lastSettle = block.timestamp; return; } // carried to next epoch
for (id = 1..totalSupply) { // pass 2: pay to the wei, reset banked
uint256 share = revenue * weight(id) / total;
rig[id].earnedWei += share; totalOwed += share; rig[id].banked = 0;
}
lastSettle = block.timestamp;
}claim(rigId) pays earned(rigId) to the owner and zeroes it. The pool tracks totalOwed, the sum of every rig's earned plus every parked payout. Invariants you can read: pool balance ≥ totalOwed + undistributed, and totalHarvested ≥ totalDistributed + undistributed. rescuable() is the remainder and is normally zero.
Time-weighted. A rig earns for the seconds it was online in the epoch, times its hashpower. A rig fuelled for exactly 24 h earns the full epoch. A rig that goes online at hour 12 earns half. Nothing depends on the settle instant alone.
onlineHashpower is maintained incrementally: refuel and upgrade adjust it, and expiries are removed lazily at settle by a full pass over minted rigs: 6.8M gas measured with all 2,000 rigs online, about 0.0002 ETH per day at 0.03 gwei. If total weight is zero at settle, the revenue is carried to the next epoch. It is never sent anywhere else.
Refuel and upgrade bank the interval so far and restart it, so an upgrade mid-epoch applies its new level only from that second on. Rigs still online after a settle continue from lastSettle automatically.
RigsNFT calls pool.settleFor(rigId) inside its transfer hook. Pending ETH is paid to the outgoing owner and its earned balance is zeroed before ownership changes. The buyer receives the rig with its hashpower and remaining online time, and with zero pending balance.
This removes the usual trick of buying a token with unclaimed yield. What is listed is a machine, not a receivable.
Parked payouts. If a recipient rejects ETH, on a claim or on a transfer, the amount is written to parked[recipient], still counted in totalOwed, and withdrawable with withdrawParked(). Transfers and claims never block on a broken receiver, and no payout is ever lost to one.
Four contracts matter. Two are ours, two belong to Pons. Ours are shown as the zero address until deployed. The addresses are also published on X before the mint opens, and nowhere else.
The pool has no owner path to ETH at all: there is no rescue function. The owner can set the basket token list the settle pulls from, set the $RIG token once, and sweep ERC-20 fee tokens as described below. The escrow and rigToken addresses are immutable. The renderer base URI can be switched once and then frozen.
Stated v1 trust assumption. Fee tokens other than ETH are held by the pool, visible via heldToken(token), and swept by the owner with sweepToken (ERC-20 only, never ETH, emits TokenSwept) to be converted off chain. Every sweep is posted with its tx. This is the one place where you trust an operator, and it is printed here for that reason.
Burn address: 0x000000000000000000000000000000000000dEaD. Escrow: 0xd3AFEB2a57f70eF218Aa82451c51B2fb0416Ac9e.