peard
Running a cluster

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:

1
deposit_for_burn_with_hook on Solana

The CCTP burn.

2
mint_and_forward on Stellar

A Soroban call.

3
pathPaymentStrictSend between USDC and USTRY

A classic operation, because Soroban cannot reach the classic orderbook.

4
changeTrust

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.

KeyNetworkPurposeHeld on 2026-08-25
solana/pricedin-router-mainnet.jsonSolana mainnetburns USDC into CCTP, pays fees, reclaims burn rent0.0455 SOL, 1 USDC
stellar/pricedin-router.jsonStellar mainnetsubmits the mint, buys and holds USTRY50.26 XLM, 17.70 USTRY
stellar/pricedin-router-testnet.jsonStellar testnetthe same flow where failure is free10,000 XLM, 1 USDC
solana/pricedin-faucet-{1..5}.jsonSolana devnetfaucet-limited USDC, consolidated for bridge tests99 devnet USDC, 0.1 SOL each
solana/pricedin-devnet-admin.jsonSolana devnetGlobal.admin, 69TtCQGHCeDM2wxN8j5PFHEijq2xvGyy5utj9eKUNm3dno balance
solana/pricedin-devnet-oracle.jsonSolana devnetGlobal.oracle_authority, Enr469NV4RkwamVpcESWfh21Rvh5y4ZagNXD2syQyML2no balance
solana/pricedin-devnet-fulfillment.jsonSolana devnetGlobal.fulfillment_authority, 43K6McKYagKnpCnv12AuthgYZQaWjnUGLY1Pnq2qvgSzno balance
solana/id.jsonshared, devnetpre-existing machine key; deploy payer, devnet funder, and the upgrade authority on all three deployed programs11.2 devnet SOL
solana/pricedin-program-keys/backupsthe five program-id keypairsno 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.

adminPubkey

Can 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_authorityPubkey

Signs 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_authorityPubkey

Signs 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_receiverPubkey

Where 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_immutable flag is false, 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.