The teaching page
HOW IT WORKS
The whole loop in order, with the arithmetic written out. Mint burns tokens, rarity sets a base power, staking is what makes a lil trader earn, burning more tokens raises that lil trader's share of the ETH pool forever. If you only read one page, read this one.
Step 1
WHAT A LIL TRADER IS
A Lil Trader is a pixel NFT on Robinhood Chain. There are of them and no more, ever. That cap is set in the constructor and cannot be raised.
Each lil trader carries two things that matter beyond the art:
- A rarity tier, fixed at deploy, which gives it a base power of 1, 2, 4 or 8.
- A bonus power, which starts at zero, goes up every time somebody burns $LILT into that specific token id, and resets to zero when the token changes owner.
Power is the only thing that decides how the ETH pool divides. A lil trader with power 8 earns exactly eight times what a lil trader with power 1 earns over the same period, as long as both are staked.
There is no reveal. The art and the rarity are public from the first mint, because the rarity table is written to the contract once at deploy, before the mint opens.
Two sinks point at one token and one pool pays out in ETH. That is the entire design. Nothing mints new $LILT, and no part of this contract set can create yield out of nothing.
on this page
Step 2
MINTING
The price is fixed in dollars and paid in $LILT. The tokens are burned, not collected. The contract never holds them.
the price is a dollar figure, not a token figure
One lil trader costs of $LILT. The contract stores that as a constant in dollars. It does not store a token amount, because the number of tokens that adds up to a dollar and a half moves whenever the token moves.
To turn dollars into tokens the contract needs to know what one $LILT is worth. A keeper address pushes that number on chain with setTokenUsd, and the contract stamps the time it arrived. The mint then works out:
cost = qty * PRICE_USD * 1e18 / tokenUsd()
Both PRICE_USD and tokenUsd() are 18 decimal dollar figures, which is why the extra 1e18 is there: it keeps the multiplication ahead of the division so nothing is truncated early.
worked example
Example numbers. The $0.005 token price below is made up to keep the arithmetic readable. The real one comes from the on chain feed and changes.
why a mint can revert
Three separate things stop a mint, and all three are deliberate.
The feed is stale or was never set. tokenUsd() reverts if the last push is older than 15 minutes or if there has never been one. A stale price cannot be used to mint at the wrong number of tokens. The mint fails closed rather than guessing.
Your maxCost was too tight. You call mint(qty, maxCost). maxCost is the largest number of $LILT wei you are willing to burn for that transaction. The site quotes you the cost and you add headroom. If the price moves between the quote and the block your transaction lands in, and the real cost lands above maxCost, the whole transaction reverts and your tokens stay where they are. You pay gas, nothing else.
The mint is not open, or the caps are hit. The mint only opens when the vault address is set, and that call locks forever. On top of that there is a hard supply cap and a per wallet cap.
| $LILT moves | Real cost at inclusion | Outcome |
|---|---|---|
| Up, to $0.006 | 250 tokens | Mints. You burn 250, not 315. You are only ever charged the real cost. |
| Flat, at $0.005 | 300 tokens | Mints at 300. |
| Down, to $0.0048 | 312.5 tokens | Mints. Still under your ceiling. |
| Down, to $0.004 | 375 tokens | Reverts. Above your ceiling, so nothing is burned and no lil trader is minted. |
Read it this way: with maxCost set, a mint can only cost you less than you expected or fail outright. It can never quietly cost more. | ||
the payment is burned
The mint calls transferFrom on $LILT and sends your tokens to 0x000000000000000000000000000000000000dEaD in the same transaction. They go from your wallet to the dead address. They do not pass through the NFT contract's balance at any point.
That is worth being precise about, because it is the difference between a project that could rug the mint proceeds and one that structurally cannot. There is no token balance sitting in the NFT contract, so there is no sweep function, no withdraw function, and nothing for an owner key to take. The burn is the payment.
Since the mint uses transferFrom, you approve the NFT contract on $LILT first. That is one extra signature the first time you mint and none after: the approval is one-time and does not depend on the price. The contract can only pull tokens inside a mint you sign, capped by that mint's maxCost, straight to the burn address. One thing to check before you click: the tokens must sit in the connected wallet. An approval from one account cannot spend tokens held by another.
| Supply | |
| Price | of $LILT, burned |
| Max per wallet | |
| Paid in | $LILT, a plain ERC-20 |
| Goes to | 0x...dEaD |
| Price feed | keeper push, max age 15 minutes |
| Token ids | 1 upward, sequential |
| Reveal | none, art is public from mint 1 |
Step 3
POWER
Power is your slice of the pool. It has two parts: one you get at mint and one you buy by burning.
power(id) = baseWeight(id) + bonusPower(id)
baseWeight = 1 | 2 | 4 | 8 (rarity, fixed at mint)
bonusPower = floor(tokensBurned(id) / POWER_UNIT) (uncapped, survives unstake, resets on sale)
base power comes from rarity
Rarity is decided before the mint opens by a ranked statistical rarity cut across all lil traders, written to the contract once, and locked. The split is exact, not approximate:
Those four numbers add to the full supply, and the base powers add up to a known total. If every single lil trader were staked and nobody had ever powered one up, the total power in the vault would be:
In that hypothetical, a legendary would hold 8 of 5,700, which is about 0.14% of every payout, and a common would hold 1 of 5,700, about 0.018%. Real shares will be larger than that, because in practice not every lil trader is staked. They will also move, because every power up changes the denominator for everyone.
bonus power comes from burning
POWER_UNIT is the number of $LILT that buys one point of power. It is fixed at deploy and it is the same in both contracts. The value for this deployment is $LILT.
The maths is a floor division, which has one consequence worth stating plainly. Your gain is amount / POWER_UNIT rounded down. If the gain would round down to zero the call reverts, so you cannot burn a small amount and silently get nothing. But a remainder above one full unit is still burned and does not carry over to a later top up. Burn exact multiples.
The example below uses 1,000 $LILT as the unit only because it makes the arithmetic readable. The real unit is the figure above.
Two more properties of bonus power that people get wrong:
- It dies with the sale. Sell or transfer the lil trader and its bonus power resets to zero: the buyer starts at the rarity base weight and burns their own $LILT if they want more. You do not get your burned tokens back either way.
- Anyone can power up anyone's lil trader. The burn always comes out of the caller's wallet, and the power always lands on the token id they name. Gifting power to someone else's lil trader is allowed because it can only ever help the recipient.
Step 4
STAKING
A lil trader sitting in your wallet earns nothing. Earning is gated on staking, and there is a reason for that beyond wanting you to click a button.
what staking does
You call stake with a list of token ids. For each one the vault pulls the NFT in, reads power(id) at that moment, records it, and adds it to the running total power. It also stamps your starting point in the reward accumulator, so you begin earning from now and not from anything that arrived before you.
While a lil trader is staked it is owned by the vault contract. It is not in your wallet. You cannot transfer it, you cannot list it, and it will not show up as yours on a marketplace. The only way it moves is you calling unstake. Nobody else can move it, including whoever holds the owner key.
The vault still knows it is yours. It records the staker for every id and only that address can unstake it or claim against it.
why earning is staking gated
Reward accounting has to know two things at every moment: the total power in the system, and each token's share of it. If lil traders could earn while moving freely between wallets, every transfer would have to settle rewards mid flight, and every settlement is somewhere a bug can live.
Because staked lil traders live inside the vault, a staked lil trader cannot be transferred at all except through unstake, which settles properly on the way out. That means the plain NFT transfer path needs no reward settlement whatsoever. It stays a plain transfer. That single design choice is what keeps the money path small enough to check by hand.
Note on ETH that arrives with nothing staked. It cannot be divided by a total power of zero, so the vault holds it aside. It is not lost and it is not sent back, it waits. It folds into the pool only once a staked position has been standing for a day, and then it is split by power across everyone staked at that moment. The delay is there on purpose: without it, one wallet could stake a single common lil trader, take the whole pile, and unstake in the same transaction. If nobody ever stakes again, that ETH sits in the vault. There is no admin function to retrieve it.
Step 5
THE POOL
The vault holds ETH and divides it by power. It does not create ETH. Everything paid out arrived from somewhere first.
where the ETH comes from
- The desk. The team trades on this chain and sends what that trading earns to the vault as plain ETH, every hour. An hour that earned nothing sends nothing.
- Pons launch fees. Every token the team has launched on Pons earns creator fees, and any of them can be routed into the vault with the same plain send. Each launch is one more line paying in.
- Royalties. The marketplace creator fee is 5% and its only recipient is the vault. The NFT contract also declares an EIP-2981 royalty (700 basis points) whose on-chain receiver is the vault itself, so venues that read the standard pay the pool directly. The dev keeps none of it.
- Anything else. Any other ETH the project decides to point at the vault, sent in as plain ETH.
Be clear eyed about all four. The first two are operations the team runs, not code: the contracts do not trade and nothing on chain can force the next hourly send. What you can verify is the result, ETH arriving at the vault address, which is public. The royalty is code on our side only: EIP-2981 publishes a number, it does not enforce payment, so a marketplace that chooses to ignore royalties pays nothing and no contract on this chain can make it. Royalty income is real but it is not guaranteed, and it scales with secondary volume, which nobody can promise.
Operational note for anyone routing revenue in: the vault's receive function does no work, so a plain send lands at any gas and a marketplace paying a royalty with a 2,300 gas stipend lands too. The ETH sits in the balance until the next call to the vault folds it into the pool, which any wallet can trigger with sync. The fund function does the fold in the same transaction and needs normal gas.
how a deposit divides
When ETH lands, the vault does not loop over every staker. It adds one number to a running accumulator: the deposit divided by the total staked power, held at 1e18 precision. Each token's claim is then its own power multiplied by how much that accumulator has moved since the token started earning. That is why the gas cost of a deposit does not grow with the number of stakers.
In plain terms: every unit of power gets an equal slice of every deposit, and your lil trader's slice is its power times that per unit amount.
worked example, two holders
Example numbers. Three staked lil traders, one deposit of 1.2 ETH. Alice holds one legendary that has never been powered up. Bob holds two commons, one of which he has burned 2,000 $LILT into at an example unit of 1,000.
| Holder | Lil Trader | Base | Bonus | Power | Share | From 1.2 ETH |
|---|---|---|---|---|---|---|
| Alice | #14 legendary | 8 | 0 | 8 | 8 / 12 = 66.7% | 0.8 ETH |
| Bob | #902 common, powered up | 1 | 2 | 3 | 3 / 12 = 25.0% | 0.3 ETH |
| Bob | #1455 common | 1 | 0 | 1 | 1 / 12 = 8.3% | 0.1 ETH |
| Total staked power | 12 | 100% | 1.2 ETH | |||
Bob ends the round with 0.4 ETH across two lil traders and Alice with 0.8 ETH from one. Bob's powered up common earns three times what his untouched one does, which is exactly the ratio of their powers.
Notice what the denominator is doing. Alice's 66.7% is not a property of her legendary. It is 8 divided by whatever total power happens to be staked at the time. If somebody stakes another legendary, the total becomes 20 and her share of the next deposit drops to 40% without her doing anything at all. Power is a share of a pool, not a rate of return.
Step 6
POWERING UP WHILE STAKED
You can raise a lil trader's power without unstaking it. The contract has to settle the old rewards first, and this is the part of the design most worth understanding.
Calling powerUp with a token id and an amount burns that amount of $LILT from your wallet to the dead address and raises the token's bonus power by amount / POWER_UNIT. If the lil trader is not staked, that is the whole story: the bonus is recorded against the id and it will count the next time the lil trader is staked.
If the lil trader is staked, the contract does three things in this order, and the order is the whole point:
SETTLE
Work out everything this token has earned so far at its current power and bank it as credit. Reset its starting point to now.
BURN
Move the $LILT from the caller to the dead address and add the gain to the token's bonus power.
RAISE
Increase the token's live power and the vault's total power by the same amount, so both sides of the ledger move together.
why settling first matters
A token's pending reward is its power multiplied by the gap between the accumulator now and the accumulator when it last settled. Raise the power without closing that gap first, and the higher power gets applied to the entire history, including rewards that accrued while the token was weaker. The token would claim ETH it never earned, and because the vault only holds what actually arrived, that ETH would come out of the other stakers.
Worked from the table above. Bob powers up #902 by 5 points right after that 1.2 ETH deposit, then a second deposit of 1.7 ETH arrives with the same three lil traders staked.
Now the same token without the settle step. The accumulator has moved 0.2 in total across the two deposits, so the contract would compute 8 x 0.2 = 1.6 ETH for a token that earned 1.1. That is 0.5 ETH conjured out of the other stakers' balances. Settling first is what makes the difference, and it is a required property of the contract, not an optimisation.
what a power up does to everyone else
It dilutes them, and it is honest to say so. In round one Alice's legendary took 8 of 12. In round two it takes 8 of 17, so 0.8 ETH out of 1.7 instead of 0.8 out of 1.2. She earned the same ETH from a bigger deposit. Her share went from 66.7% to 47.1% because Bob bought power, not because anything happened to her lil trader.
| Lil Trader | Round 1 power | Round 1 ETH | Round 2 power | Round 2 ETH | Total |
|---|---|---|---|---|---|
| #14 legendary | 8 | 0.8 | 8 | 0.8 | 1.6 ETH |
| #902 powered up | 3 | 0.3 | 8 | 0.8 | 1.1 ETH |
| #1455 common | 1 | 0.1 | 1 | 0.1 | 0.2 ETH |
| Deposit | 12 | 1.2 | 17 | 1.7 | 2.9 ETH |
Every ETH that went in came out, split by the power that was actually staked at the time. That is the invariant to check any of these numbers against.
Step 7
CLAIMING
Calling claim settles every lil trader you have staked, adds the result to your credit balance, sets that balance to zero, and then sends you the ETH. The zeroing happens before the send, which is the standard ordering for not being drained by a contract that calls back into the vault mid payment.
There is no schedule, no lock and no expiry. Pending ETH keeps accruing until you claim it. Claiming early does not reduce what you earn later, and waiting does not earn you extra.
The only real consideration is gas. A claim is a transaction, so claiming a very small balance can cost more than it pays. The stake page shows your pending figure so you can decide.
what a claim does not do
- It does not unstake anything. Your lil traders stay in the vault and keep earning.
- It does not touch power. Base and bonus are unchanged.
- It does not burn anything. Claiming costs gas and nothing else.
Unstaking also settles, so you never have to claim first to avoid losing pending ETH. Whichever you call, the credit is worked out before anything else moves.
Step 8
UNSTAKING
You call unstake with a list of token ids. For each one the vault settles what it has earned into your credit, removes its power from the total, and transfers the NFT back to you. It is in your wallet again and you can do anything you like with it.
From that moment it earns nothing. An unstaked lil trader is art. There is no partial rate, no cooldown and no penalty, it simply stops counting.
bonus power survives unstake, not a sale
This is the part people ask about most, so to be explicit: unstaking does not destroy bonus power. The bonus is stored against the token id, not against the stake. Unstake a lil trader that you burned 20,000 $LILT into, leave it in your wallet for six months, stake it again, and it comes back with exactly the same bonus power it had. Nothing decays.
A sale is the opposite: the moment the lil trader changes owner, the contract resets its bonus to zero and the buyer starts at base weight. The tokens you burned are gone either way. They were burned, not deposited, so there was never anything to withdraw.