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.

Activate that receipt and it starts earning from the pool. Every later sale at that business adds to the pool, and it divides across activated receipts in proportion to how many each person holds. Claim whenever you like.

An unactivated receipt earns nothing, and its share goes to holders who did activate. That is the whole mechanism.

The reward share and the resale royalty are 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 product, the price and the date. Yours to hold, transfer or sell.
ActivationA one-off, permanent step that switches a receipt into an earning state. Until then it earns nothing.
PoolThe share of each sale set aside for holders. Between 1% and 90%, fixed at deployment.
Pool shareYour activated receipts divided by every activated receipt at that business.
SpenScoreA public trust signal out of 100, built from verification, delivery record, official channel confirmation and user reports.
BoostPaid promotion. 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: it shows in any wallet, on any explorer, and can be sold on any marketplace.

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.

Activation#

A receipt earns only once activated. Activation is a one-off with a small fee, and it is permanent.

Why it costs anything. Without a price, every receipt ever minted would be activated, the pool would divide across all of them, and nobody would earn enough to care. A price filters to holders who expect to earn more than they pay.

It is not retroactive. A receipt joins the pool at the moment it activates and earns from sales after that, never from sales before. Activating early is worth more than activating late.

activate(uint256[] tokenIds)
activated(uint256 tokenId) โ†’ bool
activeCount() โ†’ uint256

The pool#

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

pending = accPerReceipt - checkpoint[tokenId]

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 nobody has activated, 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 whoever holds the receipt. Sell it with unclaimed rewards inside and they go to the buyer. Claim first if you do not want that.

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 payout 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.

Royalties#

Receipts are freely transferable and can be sold anywhere. On a resale, the business takes the royalty it set at deployment, up to 10%, and Spend2Stake takes 1.5%.

ERC-2981 allows one recipient, so the royalty is paid to the business contract and split afterwards by sweepRoyalties(), which anyone can call. It only ever pays the business's own payout address and the platform, and it cannot touch rewards owed to holders.

Royalty enforcement is voluntary. Marketplaces choose whether to honour ERC-2981 and several have made it optional. A sale routed around it pays neither the business nor us.

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 payout address
Claimthe receipt holderthat holder

Neither is a decision anyone makes. The business sets its own payout 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
royaltyBps()         โ†’ the resale royalty
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
activatethe receipt ownerswitches receipts into earning
claimthe receipt ownerpays out accrued rewards
sweepRoyaltiesanyonesplits resale royalties to fixed addresses
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)
Activated(tokenId, holder, fee)
Claimed(holder, amount, tokenIds)
RoyaltiesSwept(toBusiness, toPlatform)
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