Deployment
Testnet onlyHow the contracts are deployed, and the guard that refuses mainnet outright.
Testnet. The deploy script refuses chain 4663 outright, regardless of configuration or flags. Mainnet deployment is gated on Production gates, and gate 1 is open.
#Order
flowchart TB A["Registries<br/>SourceRegistry · AssetRiskRegistry"] --> B["Routers<br/>PriceRouter · ExecutionRouter"] B --> C["Adapters<br/>allowlisted individually"] C --> D[FeeController] D --> E[MirrorVaultFactory] E --> F["MirrorVault<br/>one per source version"]
Registries first, because the routers reference them; the factory last, because a vault's immutable references are set at construction and cannot be repointed afterwards.
#Keys
| Environment | Method |
|---|---|
| Local Anvil | --unlocked --sender <anvil account> — no key |
| Testnet | An encrypted keystore: forge script --account <name> |
| Mainnet | A hardware wallet (--ledger), and only once every gate is met |
Warning. Never put a real private key in an environment file or on a command line.
.envis gitignored and must never be committed; the repository ships.env.exampleonly.
#Admin
DEPLOY_ADMIN receives the admin and pauser roles, defaulting to the broadcasting address.
In production this must be a multisig or timelock. A single EOA holding PAUSER_ROLE across the protocol is a single point of failure, and is listed as one in the production gates.
#Verification before configuration
Every address written into configuration has to pass an onchain verification predicate first:
pnpm verify:chainThe check refuses any address that lacks a predicate. This is not ceremony: this chain hosts six verified contracts called Quoter, two of them wired to fork factories. A name proves nothing.
#A cheatcode that does not persist
vm.deal is a Foundry cheatcode. It works in tests and does not persist through forge script --broadcast — a seeding script that used it produced accounts with no gas, and only one of six vaults landed.
Funding for a broadcast run has to come from outside the script, for example via the node's own RPC:
cast rpc anvil_setBalance <address> 0x56BC75E2D63100000