Key management
Sixteen keypairs, what each one is for, and the custody position stated plainly.
Sixteen keypairs exist for this project, created on 24 and 25 August 2026: one
Solana mainnet router key, two Stellar router keys, five devnet faucet keys,
three devnet role keys for peard, and five program-id keypairs. All live
outside the repository, under ~/.config/solana/ and ~/.config/stellar/, at
mode 0600. None is committed, and none should ever be. id.json is a
seventeenth file and is explicitly not ours.
This page exists because two of them now hold real money, and a key holding money should have a written answer to "what is this for" that predates the moment somebody needs it.
The intent, in one paragraph
These keys operate a cross-chain execution router and nothing else. They exist to move USDC from Solana to Stellar over Circle's CCTP, buy a tokenised US Treasury bond on Stellar's classic orderbook, hold that position, and reverse the trip on exit.
They sign exactly four kinds of transaction:
The CCTP burn.
A Soroban call.
A classic operation, because Soroban cannot reach the classic orderbook.
The operations that make the previous one possible.
They will additionally sign reclaim_event_account on Solana to recover
per-burn rent after its five-day window.
They are not used to deploy programs, not used to hold protocol funds, not used as an admin or upgrade authority anywhere, and not shared with any service. The devnet and testnet keys carry no value and exist so that the expensive failure modes can be exercised where a mistake costs nothing.
The custody position, stated plainly
The Stellar mainnet key is custodial, and that is forced by the chain
rather than chosen. A Soroban contract cannot reach Stellar's classic
orderbook, so the leg that buys the bond must be signed by an ordinary G
account with a private key. Whoever holds that key holds the position.
Today that is a single key on a single machine, which is appropriate for a $19 proof and is not appropriate for anyone else's money. Before this custodies a third party's funds it needs, at minimum: multisig or threshold signing on the Stellar side, the key off this machine and into an HSM or equivalent, and a documented recovery path. None of those exist yet and nothing about the current setup should be read as implying they do.
The inventory
Balances are a snapshot taken on 2026-08-25 and move.
| Key | Network | Purpose | Held on 2026-08-25 |
|---|---|---|---|
solana/pricedin-router-mainnet.json | Solana mainnet | burns USDC into CCTP, pays fees, reclaims burn rent | 0.0455 SOL, 1 USDC |
stellar/pricedin-router.json | Stellar mainnet | submits the mint, buys and holds USTRY | 50.26 XLM, 17.70 USTRY |
stellar/pricedin-router-testnet.json | Stellar testnet | the same flow where failure is free | 10,000 XLM, 1 USDC |
solana/pricedin-faucet-{1..5}.json | Solana devnet | faucet-limited USDC, consolidated for bridge tests | 99 devnet USDC, 0.1 SOL each |
solana/pricedin-devnet-admin.json | Solana devnet | Global.admin, 69TtCQGHCeDM2wxN8j5PFHEijq2xvGyy5utj9eKUNm3d | no balance |
solana/pricedin-devnet-oracle.json | Solana devnet | Global.oracle_authority, Enr469NV4RkwamVpcESWfh21Rvh5y4ZagNXD2syQyML2 | no balance |
solana/pricedin-devnet-fulfillment.json | Solana devnet | Global.fulfillment_authority, 43K6McKYagKnpCnv12AuthgYZQaWjnUGLY1Pnq2qvgSz | no balance |
solana/id.json | shared, devnet | pre-existing machine key; deploy payer, devnet funder, and the upgrade authority on all three deployed programs | 11.2 devnet SOL |
solana/pricedin-program-keys/ | backups | the five program-id keypairs | no balance, high value |
Three notes on that table.
id.json is not ours. It is the shared default key on this machine and
other work uses it, so it is always passed explicitly with -k and its global
config is never modified.
pricedin-program-keys/ holds no balance and is the most valuable thing
listed. It carries the program-id keypairs for all five programs, including
peard_tote, which has never been deployed and cannot reach its declared
address without them. They existed only inside target/ until they
were copied out on 2026-08-24, and anchor clean would have destroyed them.
The upgrade authority is not in that directory. Read off devnet on
2026-08-25, peard, peard_amm and peard_perps all name
9D2d7j5yC2phSzSV5FXDiHH2CrTHQb3W3fyQ6ctXP4m3 as their upgrade authority, which
is id.json, the shared machine key this page has just said is not ours. The
peard role authorities were rotated onto dedicated keys on 2026-08-25 and
the upgrade authority was not. peard_perps's own Global.admin is also still
id.json. Both are open.
The protocol authorities are a separate question
The router keys above have nothing to do with the on-chain roles. Those live in
peard's Global and are rotated with scripts/rotate-authorities.ts.
adminPubkeyCan change the rules: protocol fee, convert bounty, dollar mint, backing
program, and the other three authorities. Rotated last and only with
--i-understand-this-is-final, because it is what authorises the rotation.
oracle_authorityPubkeySigns push_price. On a cluster running perps this is the key that signs the
index deciding who is liquidatable, which is why peard_perps pins its registry
program at init with no setter.
fulfillment_authorityPubkeySigns settle_fulfillment, and only that. It cannot move money any other way:
the reserve was already set aside by the holder's own request, and
expire_fulfillment needs no signer at all.
fee_receiverPubkeyWhere withdraw_protocol_fees sends. The instruction itself is
permissionless, because the destination is fixed and there is no discretion
to guard.
On a fresh deploy seed.ts points the first three at the deployer, which is
also the program upgrade authority. One leak is all four. Rotate before
anything real happens. On devnet the first three were rotated onto dedicated
keys on 2026-08-25; fee_receiver and the upgrade authority were not, and both
are still 9D2d7j5yC2phSzSV5FXDiHH2CrTHQb3W3fyQ6ctXP4m3.
What would make me stop using the router keys
- Circle can denylist a Solana address from CCTP at the protocol level, and
can freeze a Stellar USDC trustline, since their USDC is
auth_revocable: true. - Etherfuse's USTRY is not revocable today, but its
auth_immutableflag isfalse, so that can change. - The USTRY orderbook is 99.85% one market maker, with $2,781 of realised volume in thirty days, which means the exit these keys depend on is one account's decision.
Any of those changing is a reason to wind the position down rather than to route around it.
peard