Overview
PACE is two games sharing one wallet. The first pays you for moving, anywhere, every day. The second hides fragments of real tokenized stock at the physical doors of the companies that issue them, and pays you for walking to one and tapping it.
Four parts make it work: a spawn table (where, which token, how much), a claim server that verifies you are physically present and signs a voucher, a vault contract on BNB Chain that holds the tokens and only releases them against a valid voucher, and a keeper that tops the vault back up. Nothing is minted. Every fragment on the map was bought and deposited before it spawned.
The two loops
Most move-to-earn products pick one and die of it. Emission-based games print a token until it collapses. Location games have nothing to offer you on a day when there is no drop nearby.
- The movement loop works on any street on earth. Your equipped sneaker has a speed band; minutes inside that band are eligible. Energy caps eligible minutes per day, which bounds the protocol's daily liability and forces a return visit.
- The drop loop is the high-variance layer. Drops are finite, pre-funded and rarity-tiered. You can ignore it entirely and still earn.
Energy is spent by both. That is the join: one budget, two ways to spend it, and the player decides.
Drops
A drop is a spawn point: a token, an amount, a rarity, coordinates and a place name. Each token has one drop rule that applies everywhere on earth.
Rarity is set by door count, not by taste. A brand with forty thousand storefronts is Common and pays about two dollars a catch; a brand with one headquarters is Legendary and pays a whole share. That is what keeps the map dense in a suburb and still worth a plane ticket once a month.
| Token | Fragment | Rarity | Worth today |
|---|
Drops refill every day at midnight UTC. A drop can be caught at most 24 times per day, a wallet can catch at most 6 drops per day, and the same drop once per day. Legendary drops are monthly events announced 24 hours ahead, with a tighter 25 m radius and a short code physically stuck at the location — no code, no prize, which is what makes spoofing useless there.
Claim flow
Six steps, four of them invisible.
- You connect a wallet and enable location. The app watches your GPS position.
- Within 40 m of a drop, with accuracy under 65 m, the catch button unlocks.
- The app posts your address, the drop id and your fix to
POST /api/claim. - The server re-checks distance and accuracy, reads the GPS log behind the fix, compares it against your previous accepted fixes, applies the daily caps, then builds a voucher.
- The server signs it with the claim key (EIP-712) and returns it.
- Your wallet calls
claim(voucher, signature). The contract verifies the signature, burns the nonce and transfers the fragment.
Voucher {
address to; // your wallet
address token; // e.g. AAPLx 0x9d27…890a
uint256 amount; // 0.008 AAPLx = 8000000000000000 (18 decimals)
bytes32 spawnId; // keccak256("paris-0")
uint256 nonce; // unique, burned on use
uint256 deadline; // unix seconds, +15 minutes
}
The chain never trusts the app. It trusts one key, and that key only signs after the physical checks pass. If it leaks, the owner rotates it with setSigner and pauses the vault.
Vault contract
PaceVault.sol is deliberately small. It holds BEP-20 stock tokens and exposes one user function.
function claim(Voucher calldata v, bytes calldata sig) external // reverts if: paused, past deadline, nonce used, signer mismatch // effects: marks nonce used, transfers v.amount of v.token to v.to, emits Claimed
Owner functions: setSigner, setPaused, withdraw, transferOwnership. Anyone can relay a voucher, but tokens always go to the address inside it. Signatures use EIP-712 with domain PACE / 1 / chainId 56 / vault, so a voucher for one vault is worthless on another and a mainnet voucher is worthless on testnet.
Anti-cheat
GPS can be faked and wallets are free, so per-wallet limits alone are worthless. Every counter is keyed on something a fresh wallet does not reset.
- Radius and accuracy. 40 m radius, accuracy under 65 m. Indoor and coarse IP fixes are rejected.
- Proof of presence. The app sends the GPS log behind the fix, not just the fix: at least 4 readings over 20 seconds. A real chipset wobbles by centimetres and its accuracy drifts every second. A mock provider returns the same coordinates and the same ±5 m forever, and that is exactly what we look for.
- Travel. Every accepted fix is kept per wallet and per device. A new catch has to be reachable from the last one at walking speed under 300 km, or by plane plus 90 minutes beyond it. Two cities inside one hour is refused whatever the distance — the trail follows the phone, so a fresh wallet clears nothing.
- Cross-checks GPS cannot fake. Your connection is geolocated at the edge; a fix more than 500 km from the network you are actually on is refused. So is a device clock more than 3 hours off the timezone of the place you claim to stand in.
- Motion. We read the accelerometer while you stand there. Hands shake; emulators do not. A perfect zero is refused.
- Rate limits. 120 minutes between catches per wallet, 10 minutes per drop, 24 catches per day from the same 11 m square, and a global bucket so nobody drains the vault faster than the keeper refills it.
Gear
Four archetypes, matched to real speed bands. Your first pair is free and never expires.
| Type | Speed band | Energy |
|---|---|---|
| Walker | 1–6 km/h | ≈ 4 |
| Jogger | 4–10 km/h | ≈ 5 |
| Runner | 8–20 km/h | ≈ 6 |
| Trainer | 1–20 km/h | ≈ 4–6 |
Four attributes: Efficiency raises what a movement minute earns. Luck raises mystery-box odds. Comfort reduces HP decay. Resilience reduces repair cost. Higher-tier gear also widens your catch radius, which is the only place the two loops touch mechanically.
Tokens
xStocks are BEP-20 tokens issued by Backed Finance. Each one is collateralised 1:1 by the underlying share, held with a regulated custodian, and redeemable through Backed's own issuance channel. One contract per underlying, 18 decimals, the same address across every chain they deploy to. On BNB Chain they are ordinary BEP-20s and move like any other.
42 are wired into PACE. Every address in the tables above was read back off BNB Chain — symbol() and decimals() both answered — before it was allowed into the registry, because a drop pointed at a dead contract would strand a fragment forever.
They are not offered to US persons. What you may hold where you live is yours to know.
The chain
BNB Smart Chain, chain id 56, gas paid in BNB. Blocks land in well under a second and a token transfer costs a fraction of a cent, which is the entire reason the drop loop is viable: a two-dollar fragment cannot survive a one-dollar gas bill.
| Field | Value |
|---|---|
| Chain id | 56 (0x38) |
| Currency | BNB, 18 decimals |
| RPC | https://bsc-dataseed.binance.org |
| Explorer | https://bscscan.com |
| Testnet | chain 97, https://data-seed-prebsc-1-s1.binance.org:8545 |
| Venue | PancakeSwap |
The app adds the network to your wallet automatically. The chain figures in the header of this page are read live from a public BNB Chain node in your browser — if they are moving, the connection is real.
API
GET /api/spawns?lat=&lng=&limit= drops sorted by distance
POST /api/claim { address, spawnId, lat, lng, accuracy }
-> { ok, mode, voucher, signature, contract, chainId }
GET /api/claims public feed, addresses shortened
GET /api/vault balances, payable drops, keeper runs, limits
POST /api/session { address, minutes, band } movement-loop settlement
Errors come back as { ok: false, error: "human sentence" } with a 4xx status. The claim endpoint is the only one that signs anything.
Run it yourself
npm install npm run compile # solc-js -> src/vault.artifact.json npm run test:vault # 13 assertions on an in-process EVM DEPLOYER_KEY=0x… CLAIM_SIGNER_ADDRESS=0x… npm run deploy:testnet # BNB Smart Chain testnet, chain 97 — fund the vault, then set # NEXT_PUBLIC_VAULT_ADDRESS + CLAIM_SIGNER_KEY on the server
The claim server stays in demo mode until CLAIM_SIGNER_KEY and NEXT_PUBLIC_VAULT_ADDRESS both exist. In demo mode every check still runs for real and the catch is logged — no voucher is signed and nothing moves on chain. Never put the signer key in the browser.