15 min read11 sections
P2P swaps for USDC on Base
Swap TAZ, SOUL, KCAL or RA for USDC with another person, with no one in the middle.
Open P2PIn shortSwap a Phantasma token for USDC on Base directly with another person. Each side locks its own coins on its own chain, one secret opens both locks, and every lock goes back to its owner if the trade stops.
- Tokens
- TAZ, SOUL, KCAL, RA
- Paid in
- USDC on Base
- Fee
- at most 2% of the USDC
- Base wallet
- passkey wallet or browser wallet
P2P swaps trade a Phantasma token for USDC on Base between two people. Nobody in the middle holds the coins: the seller locks the token on Phantasma, the buyer locks USDC on Base, and one secret, made by the seller's page (by the buyer's on an instant offer), opens both locks. Saturn's keeper finishes the claims. If anyone stops midway, every lock goes back to its owner after its time limit.
How it works on the P2P page explains each step, the time limits and who can do what.
What you need
- To sell: the token, a little KCAL and SOUL for fees in your Phantasma wallet (the page says how much), and a Base address to be paid in USDC. A seller needs no ETH. Keep the trade page open until it has shared your secret.
- To buy: USDC and a little ETH, both on the Base network, and a Phantasma address for the token. ETH pays the network fee for each step on Base, usually under one cent; about 0.0005 ETH covers many trades. Before you take an offer or accept a take, the page checks that your Base address holds the USDC and enough ETH for the lock's fee, whichever wallet you use. Keep a little KCAL and 1 SOUL in the Phantasma wallet too, so you can claim the token yourself if the keeper cannot.
The exchange view
The Market tab shows one token at a time (TAZ, SOUL, KCAL or RA, picked at the top) with its reference price, the book, the depth chart, the trade chart and the completed trades, and beside them the order panel and the offer form. On a phone, Book, Depth and Chart share one place, and the three buttons above them pick one.
- The book lists live offers as price levels: offers to sell (asks) above, offers to buy (bids) below, the best of each next to the spread. Each row shows the price in USDC, the amount and the total. Click a level, or press Enter on it, and the order panel takes its price and the amount up to it. Nothing is taken until you confirm.
- The depth chart adds up the USD of the bids at or above each price and of the asks at or below it, around the reference price, with the band 5% either side that the published rule counts.
- The trade chart has one dot per completed trade, sized by the USDC traded: a filled dot where the taker bought, a ring where the taker sold. Pick a dot for its time, price, amount and fee, with links to both locks and both claims on the explorers. The arrow keys step from trade to trade.
- The reference price at the top is Saturn's published USD price of the token, with a tag that says where it comes from: USD via SOUL, or, for RA and TAZ, USD via P2P once completed P2P trades and live offers near the price pass the published rule. It is there for information. The offer form never fills in a price for you, and no check before a lock reads it. How Saturn prices RA and TAZ explains it.
Buy or sell up to a price
The order panel buys or sells an amount at your limit or better: Pay at most for a buy, Sell for at least for a sell. Buying, you can give the USDC to spend instead. It splits the order across the best live offers of other makers, at most 5 at a time and 8 takes in all, and shows before you confirm what fills, from how many offers, the average price and what cannot fill at your limit.
- Each take is a trade of its own. Its maker accepts it first (within 2 minutes), and you approve each lock yourself: a passkey wallet asks once per lock, a browser wallet twice for each USDC lock (approve, then lock). Buying, you approve each USDC lock within 10 minutes of that seller's lock on devnet, 25 on mainnet. Selling, you approve each token lock within 10 minutes of that buyer's accept.
- Keep the page open until every lock is approved. The tracker under the order panel lists the takes, each with its own Approve lock button. A missed lock counts as a no-show, and 3 in 24 hours pause your takes for 24 hours.
- Stop ends further takes. Takes already made are real trades and still need their locks. A take its maker never accepted locked nothing; Fill the rest tries other offers for what is left.
- Post the rest as an offer lists whatever did not fill at your limit, once the takes are placed.
- Fill now: when an offer you are about to post already crosses live offers (a sell at or under a bid, a buy at or over an ask), the offer form offers to take them instead, through the same order panel. Each still needs the other side to accept and your approval of each lock. Post my offer anyway lists your offer as typed.
Accept takes on their own
Each offer has a box, Accept takes on their own. When it is on, the page accepts a take for you once the chain shows the other side's funds: on an offer to sell, the buyer's USDC and a little ETH for the network fee on Base; on an offer to buy, the seller's token, with the KCAL or SOUL a seller keeps on top. It signs nothing: you still approve your own lock. Any other take waits for your Accept or Decline.
- It starts off when you lock with a passkey wallet (selling from a passkey wallet, or buying with USDC from the passkey wallet's Base address), and on with other wallets. You can turn it on or off for each offer under My trades.
- Off, you accept or decline each take yourself within 2 minutes. A take left unanswered is cancelled, and nothing is locked.
- The passkey wallet never signs without your passkey prompt, here or anywhere else on the site.
Offers that follow the reference price
An offer's price can be fixed, or it can follow the token's published reference price. In the offer form, pick Follow the reference price under Price, then set the Offset (from −20% to +20%), the price you never go past (Never below on an offer to sell, Never above on an offer to buy; required) and, if you like, the most it may fill in a day (At most per day; empty means the whole offer). The form shows the reference price with its label and what your price would be now.
- The board sets the offer's price every minute from the reference price's average over the last hour, plus your offset, and never past your limit price. It only moves your offer's price: it never trades.
- It pauses the offer, so nobody can take it, while the reference price cannot be used: too few figures in the last hour, none in the last 3 minutes, or more than 10% between the hour's highest and lowest. It pauses it too while, at that price, its smallest or largest trade would fall outside what one USDC lock may hold. My trades then shows the offer as paused.
- At your limit price, one take may cost at most 1,000 USDC on mainnet (10,000 test mUSDC on devnet), so the largest trade of such an offer has to fit that.
- Each take is fixed at the price its taker saw. If the price moved in between, the take is refused and the taker sees the new price; trades already running keep theirs.
- Before your page accepts a take, on its own or by your click, it checks the trade's price against your limit price again (for a fixed price, against the prices you set). A take past your limit is never accepted.
- Change price under My trades switches an offer between a fixed price and following, or changes how it follows, at most once every 10 seconds.
While the reference price is USD via SOUL, thin pools can move it. Your limit price is what protects you: set it to the worst price you would still trade at.
Alerts
Your offers stay listed only while the P2P page is open (on a phone, while it is on screen). When someone takes one, you have 2 minutes to accept the take, then about 10 minutes to approve your lock once it is due (a USDC lock on mainnet: 25). The bell at the top of the P2P page, and the top of My trades, opens the alerts, so you hear about it in time.
- In this tab, always on: a notice on the page, a count in the tab's title, two short beeps (sound starts after your first click or key press on the page) and, if you allow it, a browser notification while the tab is in the background.
- Push to this device: a notification even when the tab is closed, where the browser supports it. Push alerts don't work in Safari on iPhone and iPad, because the site cannot be installed as an app there; use Telegram.
- Telegram: Connect Telegram opens Saturn's alert bot; press Start in the chat and the alerts arrive there. Send /stop in the chat, or press Turn off on the page, to end them.
- Every channel has Send test and Turn off. Alerts come when someone takes one of your offers and when a lock of yours is due. Each carries the trade's number and a link, never a key or a secret.
- Alerts only tell you. Your passkey still asks for every lock, and a trade can be acted on only in the browser where its offer or take was made: open the link there.
Instant offers
On an instant offer you, the buyer, lock first. Your page makes the trade's secret (it calls it your code) and locks your USDC; the seller's bot checks that lock on Base, then locks the token for you on Phantasma; your page checks the seller's lock, then releases your code. Saturn's keeper claims the token for you on Phantasma first, and only after that the USDC for the seller. The contracts are the same as for every other trade: only the order of the two locks changes.
- Devnet only for now, and only while Saturn has them turned on there. Mainnet has no instant offers, and the site does not offer them there. Opening them on mainnet is the owner's decision, taken from the risks below.
- Only a seller's bot can post one, with an API key the owner has marked for instant offers and gives to makers with a record. The P2P page buys from instant offers; it does not post them.
- They carry an Instant badge in the book and in All offers. Once the seller's bot accepts your take, lock your USDC within about 8 minutes (one passkey prompt, or approve and lock with a browser wallet; the page stops 90 seconds before the trade's 10-minute limit, so the lock can still be mined in time), or the missed lock counts as your no-show. A browser wallet's second prompt, the lock itself, has to be confirmed within about a minute and a half of the first (on devnet).
- The seller's bot then has 5 minutes on devnet (10 on mainnet) to lock the token. If it does not, your USDC comes back after your lock's time limit: about 32 minutes after you locked on devnet (2 hours 20 minutes on mainnet).
- While it is open, your page releases your code on its own once the seller's lock holds the right token and amount for your address, came in time and leaves time to claim. Releasing it signs nothing.
- If the token is still unclaimed a minute after your code went out, the page offers to claim it yourself (Claim TAZ myself, on a TAZ trade): one wallet prompt, with 3 KCAL and 1 SOUL in your Phantasma wallet. Once your lock's time limit has passed on a trade that did not finish, Refund my USDC brings the USDC back.
Risks that remain. Risks 1, 2, 4 and 5 cost time, never funds. Risk 3 can cost the buyer the trade's USDC. The owner decides on instant offers for mainnet from this list.
- Hash squatting. Both locks are filed under the trade's hash, a fingerprint of your code that does not give the code away. Your lock makes that hash public before the seller locks, and Phantasma accepts each hash only once, ever. Anyone can lock 1 KCAL under it first, for well under a cent; the seller's lock then fails, and your USDC waits until its time limit. Mitigations: the board spots the squat at once, moves the trade to refunding and tells you; the time limit is kept short; and the seller's bot may lock without waiting for the block to settle, at its own risk. Your code is never released for a lock that does not fit, so a squatter cannot learn it.
- Makers who do not lock, or who squat their own trades, hold your USDC until its time limit. Makers who miss their locks are paused (3 no-shows in 24 hours); two squats on one maker's instant trades within 24 hours pause its instant offers until 24 hours after the latest; and only keys the owner marked for instant offers can post them. Anyone can squat a trade, its taker too, so a buyer can set off that pause on purpose: the owner lifts a pause that was not the maker's doing.
- A failed Phantasma claim can still make your code public, and that can cost the buyer the trade's USDC if every Phantasma claim fails until the time limit (the end of the seller's lock): the seller can claim your USDC with the public code, and gets its tokens back when its own lock ends. Mitigations: your page releases your code only while at least 6 minutes on devnet (20 on mainnet) remain on the seller's lock, checked through a trusted node, and the board refuses it any later; Saturn's keeper retries the claim every round until a minute before that time limit, and alerts its operator at the first failure; and your page offers to claim the token yourself as soon as it is still unclaimed a minute after your code went out.
- Admin changes between the two locks. A paused Phantasma escrow, or a token whose shared lock cap is full, makes the seller's lock fail, and your USDC waits until its time limit. The owner's operating rule: never pause the escrow or stop a token while instant trades sit between their two locks.
- You must stay online, or have released your code, from the seller's lock until 6 minutes before its time limit on devnet (20 on mainnet): after that, neither your page nor the board releases it. The site releases your code on its own while the tab is open. If it is not released in time, both sides get their coins back after the time limits, and the missed release counts as your no-show.
Risk 3 is the one that can cost money. Before an instant buy, keep 3 KCAL and 1 SOUL in your Phantasma wallet, keep the trade page open until the token is claimed, and claim it yourself as soon as the page offers it.
Buying with your passkey wallet
Every passkey wallet has a Base address of its own (see The passkey wallet). On the P2P page you can pick it as your Base wallet, next to MetaMask and other browser wallets. Locking USDC with it takes one passkey prompt and one transaction: it signs the USDC permit and the lock together, so there is no separate approve step.
- To fund it, send USDC and a little ETH to it on the Base network. From an exchange, withdraw to this address and choose the Base network. Coins sent on another network (Ethereum, Arbitrum…) do not show here.
- On devnet the address is on Base Sepolia, a test network: get free Base Sepolia ETH from a faucet, then press Get 1,000 test mUSDC. Never send real ETH there.
Being paid to your passkey wallet
When you sell, the page never fills in your passkey wallet's Base address on its own; Use my passkey wallet's Base address puts it in. USDC paid there stays in your passkey wallet. You can spend it on this market, or send it to any Base address with Move USDC out on the Wallet page; both need a little ETH on Base for the network fee. Want the USDC on an exchange? Paste your exchange's Base deposit address instead.
What the passkey wallet signs on Base
Your passkey wallet signs nothing on Base except P2P market steps (locking USDC for a trade, claiming, refunding, withdrawing a payout that had to wait, and on the test network the test mUSDC faucet) and Move USDC out (a transfer of its own USDC to another Base address) on the Wallet page. It refuses separate approvals and permits, any other transfer, other contracts and other chains, and network fees above a fixed ceiling.
These limits do not mean your USDC can go only to your trade partner or to an address you typed. Code running on this site, with one passkey approval, could still send your USDC elsewhere, just as it could already open the wallet itself. And a Base key you export works in any wallet.