Docs

How Spend2Stake works, what it charges, and how to check every claim on this page against the contracts rather than taking our word for it. This page describes the mechanism, which does not change. Anything that does change is read live from the contracts.

The short version#

Spend2Stake is an open marketplace running on Robinhood Chain. A business deploys its own contract and lists what it sells. Nobody approves it.

When you buy something, the payment splits in that same transaction: the business is paid, Spend2Stake takes commission, and a share the business chose at deployment stays in the contract as a reward pool. You receive an NFT receipt.

The receipt earns from the moment you buy. Every later sale at that business adds to the pool, and the pool divides across receipts in proportion to their weight: what you paid, times an early-buyer multiplier. Claim whenever you like.

Receipts cannot be sold or sent. To leave, you exit: the contract pays what the receipt has earned and burns it for good.

The reward share is written into a business's contract when it deploys and can never be changed by anyone, including us. Commission can be lowered at any time and can only be raised within a ceiling that business agreed to on the day it joined.
Payment is final and nothing is held in escrow. The business is paid in the same transaction as the purchase. Spend2Stake never holds your money, which also means it cannot return it. Read the risk notice before spending.

Glossary#

TermWhat it means
ReceiptAn ERC-721 NFT minted on purchase. Records the business, the price and the date. It stays in your wallet: it cannot be sold or sent.
Early multiplierSet when you buy. Starts at 10× and falls as more USDG is staked in that business, with no floor. It rises again when holders exit.
ExitPays a receipt's earnings and burns it permanently. The only way out.
PoolThe share of each sale set aside for holders. Between 1% and 90%, fixed at deployment.
Pool shareYour receipts' weight divided by the total weight at that business.
SpenScoreA public trust signal out of 100, built from verification, delivery record, official channel confirmation and user reports.
BoostPaid promotion. Boost points lift a listing for 48 hours, then expire.
USDGThe stablecoin everything settles in. Gas is paid in ETH.

Receipts#

Every purchase mints one ERC-721 token to the buyer. It is a standard NFT, locked to the buyer (ERC-5192): it shows in any wallet and on any explorer, and cannot be transferred or sold.

The buyer is a parameter rather than the caller, so a payment made on someone's behalf still mints the receipt to them. That is what allows card payments to be added later without changing the contract.

Collection

Collection is recorded, not settled, because the business was already paid. The buyer's device produces a signature which the business scans, so an order cannot be marked collected without the buyer present.

markRedeemed(bytes32 code, bytes signature)
redeemDigest(bytes32 code) → bytes32   // what the buyer signs

A signature works for exactly one order at one business and cannot be replayed.

Multiplier and exit#

Weight. Each receipt has a weight, fixed at purchase: the amount paid times the early multiplier. The multiplier is the square root of 100,000 divided by the USDG currently staked, capped at 10×. There is no floor, so a crowded business can pay less than 1× per USDG, and a new one pays up to 10×.

Exit. A holder cannot sell a receipt. The only way to leave is exit, which pays everything the receipt has earned and burns it. The staked amount falls, so the next buyer gets a higher multiplier. A burned receipt cannot be revived; it stays on the explorer as a record and in your profile under Burned receipts.

exit(uint256[] tokenIds)
totalStaked() → uint256
weightOf(uint256 tokenId) → uint256
exitedAt(uint256 tokenId) → uint64
locked(uint256 tokenId) → bool   // always true

The pool#

Rewards use an accumulator rather than a payment per holder per sale. A business keeps a running total of reward per unit of weight, and each receipt records where it joined. What you are owed is the difference.

pending = weightOf[tokenId] × (accPerWeight - checkpoint[tokenId]) / 1e18

One sale is one storage write regardless of whether ten people or ten thousand are holding, which is what makes the model work at any size.

If there is no weight yet, the pool share goes to the business rather than sitting in the contract unclaimable. Money is never stranded.

Claiming#

Claiming is pull-based. Nothing is pushed to you, so nothing depends on us running a job. Call it whenever the amount is worth the network fee.

pendingRewards(address holder) → uint256
receiptsOf(address holder) → uint256[]
claim(uint256[] tokenIds)

Rewards belong to the wallet that holds the receipt. Exit pays any unclaimed rewards in the same transaction.

This works without us. The two read functions cost nothing and need no wallet. If this website disappeared, you could call claim straight from a block explorer and be paid. See Verify it yourself.

Commission#

Marginal bands, like income tax. Each rate applies only to the portion of an order inside it, so a larger order never pays a smaller fee than a smaller one.

Portion of an orderRate
First 30 USDG10%
30 to 1008%
100 to 2007%
200 to 5006%
500 to 2,0005%
2,000 to 10,0004%
Above 10,0002%

Minimum 0.50 USDG per sale. No cap.

OrderCommissionEffective
101.0010.00%
1008.608.60%
50033.606.72%
2,000108.605.43%
10,000428.604.28%
100,0002,228.602.22%

How rates can change

  • Cuts are immediate and reach every listed business at once. No re-listing.
  • Rises are capped and delayed. Never above the contract ceiling, announced on-chain, and effective only after 30 days.
  • Every business keeps the ceiling it joined on, recorded on its own contract and unchangeable afterwards.

The split#

A 100 USDG purchase at a business with a 10% reward pool:

Goes toAmountWhen
The business81.40same transaction, to their own wallet address
The reward pool10.00stays in the contract for holders
Spend2Stake8.60same transaction

Nothing is held back and nothing can be reversed. The only balance a business contract ever carries is rewards owed to holders.

Boost#

Paid promotion. Points lift a listing, and bigger packs cost less per point.

PointsPricePer pointDuration
200$19$0.09548 hours
500$44$0.08848 hours
1,000$79$0.07948 hours
5,000$299$0.06048 hours

Points expire on their own. The score is calculated from purchases still inside their window, so a boost fades rather than stopping dead, and nothing has to sweep it.

Anyone can boost any business, including a customer. Boosted listings are labelled, boosting does not affect SpenScore, and it implies no endorsement.

Repricing a pack never changes a boost already bought. Points keep the value they were purchased at.

No resale#

Receipts are soulbound. They cannot be sold, sent or listed on a marketplace, so there is no secondary market, no resale royalty and no fee on one. The only transfer that can happen is an agent reassignment of a stolen receipt, which waits 72 hours and is public.

This keeps the pool honest: a receipt's weight belongs to the person who paid for it, and leaving always costs the holder their place in the pool.

Custody#

Spend2Stake never holds user funds. The business contracts contain no withdraw, no sweep, no rescue, and no emergency function. Money leaves by exactly two routes:

RouteWho triggers itWhere it goes
Settlementautomatic, at purchasethe business's own wallet address
Claimthe receipt holderthat holder

Neither is a decision anyone makes. The business sets its own wallet address and we never choose where money goes.

One contract per business. This is deliberate containment. A fault reaches one business's reward pool, never the platform's whole balance.

Theft recovery#

A receipt reported stolen can be frozen immediately so it cannot be sold on, and after a 72-hour public delay it can be reassigned to its original holder.

freeze(uint256 tokenId, string reason)
queueReassign(uint256 tokenId, address to)   // emits, then waits 72h
executeReassign(uint256 tokenId)

This power moves tokens only. There is no path from it to moving USDG to the agent. Every use emits a public event, and the delay means a misuse can be seen and objected to before it completes.

The agent key is intended to be a multisig, not a single wallet.

Suspension#

A listing can be hidden and brought back with one call. Nothing is ever deleted.

Suspension stops new sales and removes the listing from the site. It does not affect holders. Receipts continue to earn and can still be claimed, because a dispute between us and a business is not the fault of people who bought from it.

Every suspension and restoration is written to a public audit log with a reason. So is a decision to review reports and leave a listing up.

Verify it yourself#

Nothing here needs to be taken on trust. Every claim above can be checked against the contracts, using a block explorer and no wallet connection.

1. Read a business without connecting anything

Open its contract on the explorer and use the Read tab. These cost nothing and need no wallet:

poolBps()            → the reward share, in basis points
totalStaked()        → USDG currently staked, which sets today's multiplier
feeCeilingBps()      → the most this business can ever be charged
platformFee(amount)  → commission on an order of that size
poolBalance()        → USDG currently owed to holders
activeCount()        → how many receipts are earning

2. Check what you are owed

receiptsOf(yourAddress)      → your token ids here
pendingRewards(yourAddress)  → what you can claim, in USDG wei

3. Claim without this website

On the Write tab, connect the wallet holding the receipts and call:

claim([1841, 1907, 2033])

You pay only the network fee. The USDG arrives in your wallet.

4. Confirm there is no way out for us

Open the contract source and search it. There is no withdraw, sweep, rescue, drain or emergency function. If one existed, this whole page would be worth nothing.

Live contracts#

The shared contracts every business is built on. A business's own contract is linked from its page on this site, or findable by searching its name on the explorer.

Factory 0x46244D07b60702C44cd941afc976cEdE438A745D
Fee schedule 0x4f3307a69444162d667B78aff2c579CA63840E3E
Implementation 0xA87d8A67F16d0523b4a5445b1f2ECfA96d6FB63C
Every business is a minimal proxy pointing at the implementation above, which is why a listing costs cents to deploy rather than a full contract deployment. It also means verifying the implementation once makes every business readable.

Robinhood Chain, chain id 4663. Explorer at robinhoodchain.blockscout.com.

Functions#

FunctionWho can call itWhat it does
purchaseanyonepays, mints a receipt, splits in one transaction
markRedeemedanyone with the buyer's signaturerecords a handover
exitthe receipt ownerpays earnings and burns the receipt
claimthe receipt ownerpays out accrued rewards
setPayoutAddressthe business ownerchanges where it is paid
freeze / unfreezethe agentlocks a stolen receipt
queueReassignthe agentstarts a 72 hour recovery
setSuspendedthe platformhides a listing, stops new sales
lowerBandsthe platformcuts commission, immediately
proposeRaisethe platformproposes a rise, 30 day delay
There is no function in this list that moves money to an address the caller chooses. Every payout goes to a party already recorded in the contract.

Events#

Everything that matters emits an event, so the whole history can be rebuilt from the chain without reading our database.

Purchased(code, buyer, tokenId, amount, claimBy)
Settled(code, toBusiness, toPool, toPlatform)
Redeemed(code, buyer)
Locked(tokenId)
Exited(holder, tokenId, paid, weight, payout)
Claimed(holder, amount, tokenIds)
Frozen(tokenId, reason)
ReassignQueued(tokenId, to, readyAt)
Reassigned(tokenId, from, to)
SuspendedSet(suspended, reason)
Boosted(business, payer, packId, points, price, expiresAt)
BandsLowered(rates, at)
RaiseProposed(rates, readyAt)

An indexer reading these can reconstruct every balance, every holder and every fee ever charged.

Live Terms of Service Privacy Policy How it works Questions Not offered where unlawful ⓘ Support