
Cope Market
A social feed where every take is backed by a real USDC position.
Demo
About
Cope Market is a social feed where every opinion costs something. You post a thesis — an asset, a direction, and your reasoning — and back it with real USDC. Other people can copy your position with one tap, and if their copy closes in profit, you get paid automatically, on-chain, by the contract. The problem it solves is that financial opinions are free to give and impossible to score. Crypto Twitter is full of calls nobody tracks, from people with no position. Here a thesis without a position is visibly marked as such, every track record is derived from settled trades rather than self-reported, and the incentive to share a good call is paid by the protocol instead of by a sponsorship deal. Positions are synthetic and oracle-priced. A shared USDC pool is the counterparty to every trade — LPs deposit into an ERC-4626 vault, traders' losses and fees become LP yield, traders' wins come out of the pool. Each position is an ERC-721 you actually hold and can sell; the credit for the call stays with whoever opened it, so buying someone's position doesn't buy their leaderboard rank. The copy mechanic is where the money flow gets interesting. A copy records which position it followed and the author's fee rate at that moment, so changing the protocol's fee later never rewrites a deal someone already took. On a profitable close the contract pays the original author a share of the profit only — never the notional, and capped at the payout so it can't be funded out of anyone else's collateral. The author never signs that transaction and may not know it happened. There's no invoice and nothing to reconcile. It runs on Arc, where USDC is the collateral, the quote asset and the gas, so no leg of that settlement touches a second token. Everything described is deployed and verified on Arc testnet: three contracts, three subgraphs across two chains, an MCP server, and two always-on services. The numbers in our demo were read from the chain, not typed into a slide — the indexed open interest reconciles to openInterest() on the contract to the wei.
How it's made
Contracts (Solidity 0.8.36, Foundry). SyntheticVault mints ERC-721 positions and does all settlement; LiquidityVault is an ERC-4626 pool whose totalAssets nets out what it owes open positions, so an LP can't deposit just before traders lose and withdraw just before they win. Entry prices are skewed against the trader by the oracle's confidence interval — a long enters at mid + conf, a short at mid − conf — so the pool never takes the oracle's uncertainty onto its own balance sheet. 166 Foundry tests including fuzz and invariant runs. Arc / Circle. USDC being native is not a detail here. Collateral, the pool's balance sheet, the author fee, the payout and the gas are one asset, so the conditional settlement has no swap, no wrapped representation and no price risk between the leg that pays and the leg that settles. One thing that catches people: Arc's native currency is USDC at 18 decimals and the ERC-20 at 0x3600…0000 is the same balance at 6. Gas therefore moves your USDC balance, and we had to account for that when reconciling — our liquidation test came out 3,920 units short until we realised the gap was gas. The Graph. Three subgraphs. One indexes any ERC-4626 vault — nothing about Cope Market appears in its schema, its mappings, or even its ABI, which is hand-written from the standard rather than exported from our vault. We proved that by pointing the same unmodified code at two MetaMorpho vaults on Base from a config file: a 6-decimal-asset vault and an 18-decimal one, priced correctly by the same expression. Then an MCP server on top, seven tools that compute drawdown, windowed rankings and whether copying a given author has actually paid — deliberately no raw GraphQL passthrough, and a test that fails if a tool name ever looks like one. Privy. X login creates an embedded wallet, and Arc is registered as a custom chain via defineChain so that wallet signs Arc transactions directly — no extension, no seed phrase. The backend holds no key at all: it validates, quotes, simulates the call as you with eth_call, and hands back an unsigned transaction. A compromised API server can lie to a user but cannot move their money. Backend. Next.js with Postgres holding only social content — theses, follows, comments. Wipe it and every position, balance and copy relationship survives on-chain. Routes are declared once as zod schemas, folded into an OpenAPI 3.1 document, and compiled into a typed client that's vendored into the frontend with a CI check that fails on drift. Pyth's pull oracle does not work on Arc. We proved it with a cross-chain control: the identical Hermes blob is accepted on Base mainnet and rejected on Arc testnet with InvalidWormholeVaa. Root cause is that Arc's Wormhole receiver holds Wormhole's guardian set (19 guardians) instead of Pythnet's (5) — not our bug, and not fixable from our side. Because the vault only ever knew an IPriceOracle, swapping to a push oracle was a constructor argument plus a service, not a rewrite. So we wrote a price pusher that fetches from Hermes, rescales to 18 decimals in exact BigInt arithmetic, drops feeds whose timestamps haven't moved, and — crucially — judges its own success by reading the oracle back and comparing each feed's age to that asset's maxAgeSec, because a mined transaction is not a usable price.