# Testnet and mainnet

> Probarion runs on NEAR testnet with test tokens today, and one small vault on mainnet. What differs between the two networks and how the site picks one.

Probarion runs on NEAR testnet today, with test tokens. On mainnet one small vault runs since 2026-11-11, with real USDC, and no mainnet factory is deployed.

Status: Live · Network: Testnet · Reviewed: 2026-11-12 · Built from: 4ab41ca1436589c22073fa842ee46f970415e3d5

Canonical page: https://probarion.xyz/docs/start/testnet-and-mainnet

Probarion runs on NEAR testnet today. The vault contract and the factory are Live there, with test tokens in place of USDC. The web console is deployed there too, as Preview: its vault, keys, faucet, USDC top-up on NEAR, mandates, Agent (MCP) tab, Freeze and approvals have been tried with a real wallet, and on 2026-11-12 so were Reject, revoking a mandate, removing an agent key and Withdraw ([the record](https://github.com/probarion/probarion/blob/main/docs/evidence/trial-vault/README.md#2026-11-12-reject-revoke-a-spare-agent-key-and-withdraw-all)). Email alerts have not been tried. Payables, the console's reference agent, is Live on testnet: it was tried with a real wallet too, and on 2026-11-12 it paid two invoices on its own with an attested model, with test tokens ([the record](https://github.com/probarion/probarion/blob/main/docs/evidence/demo-vault/README.md#2026-11-12-payables-pays-on-its-own-with-an-attested-model), [the second](https://github.com/probarion/probarion/blob/main/docs/evidence/demo-vault/README.md#2026-11-12-filmed-a-second-invoice-paid-on-its-own-freeze-and-unfreeze)). On mainnet one small vault runs since 2026-11-11, `v0.probarion.near`, with real USDC: it made one NEAR payment and one refusal, and no Base payout has run on mainnet. The mainnet factory is not deployed, so no other mainnet vault can be created yet.

One deployment of the site is built to serve both networks, and the address you open decides which one you get. That is Preview too: today only testnet is served, so every live address serves testnet.

## The two networks side by side

| What | Testnet (Live) | Mainnet (one small vault) |
| - | - | - |
| USDC | `usdc.probarion.testnet`, a test token | `17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1`, native USDC |
| USDC decimals | 6 | 6 |
| NEAR Intents | `intents-stub.probarion.testnet`, a stand-in | `intents.near` |
| Base USDC | `base-usdc.probarion.testnet`, a test token | `base-0x833589fcd6edb6e08f4c7c32d4f71b54bda02913.omft.near`, POA USDC on Base |
| Solana USDC | `sol-usdc.probarion.testnet`, a test token | `sol-5ce3bf3a31af18be40ba30f721101b4341690186.omft.near`, POA USDC on Solana, marked as a stretch goal in the code |
| Vault factory | `vaults.probarion.testnet`, deployed 2026-11-05 | `vaults.probarion.near`, not deployed |
| First vault | `v0.probarion.testnet`, deployed 2026-11-01 | `v0.probarion.near`, deployed 2026-11-11, with no factory |
| A new vault | `<name>.vaults.probarion.testnet`. The console asks for about 3.3 test NEAR, which stays in the vault for its storage and gas | Cannot be created yet: the factory is not deployed |
| Wallet | A testnet account, such as `name.testnet` | A mainnet account |
| Default RPC | `https://rpc.testnet.fastnear.com` | `https://rpc.mainnet.fastnear.com`, then `https://rpc.intea.rs` |
| Explorer | `testnet.nearblocks.io` | `nearblocks.io` |

The first vaults are recorded in `contracts/deployments/testnet.json` and `contracts/deployments/mainnet.json`. The tokens, the Intents account, the factory, the default RPCs and the explorers come from one map in the code, which the SDK, the CLI and the web console all read:

`packages/core/src/constants.ts`

```ts
export const NETWORKS = {
  mainnet: {
    rpcUrls: ["https://rpc.mainnet.fastnear.com", "https://rpc.intea.rs"], // intea answered on 2026-10-21 but ran nearcore 2.14.0-rc.2; S3 confirms. Configurable via NEAR_RPC_URLS
    usdc: "17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1", // native USDC, 6 decimals
    intents: "intents.near",
    allowedAssets: {
      base: "base-0x833589fcd6edb6e08f4c7c32d4f71b54bda02913.omft.near", // POA USDC on Base, 6 decimals
      solana: "sol-5ce3bf3a31af18be40ba30f721101b4341690186.omft.near", // POA USDC on Solana, 6 decimals (stretch)
    },
    factory: "vaults.probarion.near",
    explorerTx: "https://nearblocks.io/txns/",
  },
  testnet: {
    rpcUrls: ["https://rpc.testnet.fastnear.com"],
    usdc: "usdc.probarion.testnet", // test-ft deployment
    intents: "intents-stub.probarion.testnet", // intents-stub deployment (Intents has no testnet)
    allowedAssets: { base: "base-usdc.probarion.testnet", solana: "sol-usdc.probarion.testnet" }, // test-ft deployments acting as POA tokens
    factory: "vaults.probarion.testnet",
    explorerTx: "https://testnet.nearblocks.io/txns/",
  },
} as const;
```

## What is different on testnet

- **The tokens are test tokens.** Test USDC and the Base and Solana assets are deployments of `test-ft`, a test token contract. Only the token's owner account, `probarion.testnet`, can mint it. Any other caller gets `test-ft: only the owner can mint`.
- **Test USDC comes from the faucet.** On a testnet vault's Top-up tab (`/console/<vault>/topup`), the "Add test USDC" button mints 25 test USDC into the vault. Only the vault's owner can use it. No wallet signs: the Probarion team's key signs the mint, and that key can only mint the test token. It works once a UTC day per vault, and for up to 3 vaults per signed-in account a day. When the server has no faucet key, the tab shows this instead: "Need test USDC? Send @probarionhq a direct message on X with your vault's name."
- **NEAR Intents is a stand-in.** Intents has no testnet, so `intents-stub.probarion.testnet` takes the place of `intents.near`. For a payout to a Base or Solana payee, the stub lowers the vault's balance in its own records and logs the burn events, `mt_burn` and then `ft_burn` with the `WITHDRAW_TO:` memo the vault built from the mandate. No token is burned: the test tokens stay in the stub's account on the token contract, and nothing leaves NEAR.
- **There is no Base top-up.** In the console's words, "NEAR Intents and 1Click exist on mainnet only", so the Top-up tab cannot top up a Base balance on testnet. The mainnet version of that top-up has not been tried with a live quote yet.
- **The protocol versions can differ.** On 2026-11-01 testnet ran NEAR protocol 88 and mainnet ran 86. On 2026-11-11 both ran 88, as `contracts/deployments/testnet.json` records. A testnet pass does not prove mainnet behaviour for anything that changes between the two.
- **The first vault runs an older build.** `v0.probarion.testnet` runs a build older than the current source, from before a `set_ledger_key` fix on 2026-11-03. The vaults the testnet factory creates run the fixed build recorded in `contracts/code-hashes.json`. The first vault's test spends, from the smoke run of 2026-11-01, were also sent without a ledger, so the verifier fails [check d](https://probarion.xyz/docs/trust/verifier-checks.md#check-d) and [check h](https://probarion.xyz/docs/trust/verifier-checks.md#check-h) on it today. Check d ties each spend to one decision in the ledger, and check h matches each burned spend with its burn.

## How the site picks a network

From the address you opened, and from nothing else.

1. **You open an address** The site reads the host of the request: the first `X-Forwarded-Host` value, else `Host`. It never reads a query parameter, a cookie or the request body to pick a network.
2. **The address names the network** An address equal to a network's configured origin is that network. Every other address, including `probarion.vercel.app`, previews and `localhost`, is the default network, which is testnet.
3. **Everything follows that network** Sign-in, the vault pages, a vault's Alerts tab and `/usage` each work on that one network.

One exception: the landing's live check and its links to the smoke run always read NEAR testnet, whatever network the page is on.

The watcher and metrics runs are not tied to an address: each run covers every served network in turn and keeps each network's records apart.

What that means when you use the console:

- **A vault of the other network does not open here.** Signed in as a member of the vault, you see its page say "This vault is on NEAR" and the vault's network, with a link to that network's address when the site serves it, and the API answers [409 `wrong_network`](https://probarion.xyz/docs/build/errors.md#http-409-wrong_network) with one of the two sentences below. Anyone else gets the same answer as for a vault that does not exist, so a stranger is never told which network a vault is on.
- **A registered vault keeps its network.** Registering it again at the other network's address is refused. A member of the vault, whatever their role, gets 409 and the same sentence as a vault page (below), before anything reads the chain. If two registrations race, the database refuses the second with "This vault is already registered on the other network. A vault stays on the network it was registered on."
- **A session belongs to its address.** It names the network you signed in on. Signing in at one network's address does not sign you in at the other, and there you sign in with a wallet of that network. The message your wallet signs names `probarion.xyz` as its recipient on every address.
- **The console checks the chain before sign-in and Register.** Before either creates lasting state, it asks each RPC URL which chain it serves, and the owner's Settings button "Re-sync approvers from the chain" runs the same check. A URL that serves the other chain stops them: sign-in answers [503 `wrong_chain`](https://probarion.xyz/docs/build/errors.md#http-503-wrong_chain) and makes no session, and Register shows "This site is connected to the wrong NEAR network right now, so nothing was registered. Try again later."
- **The network switch stays hidden today.** The header shows its Testnet and Mainnet switch only when the other network is served, so today it does not show.

The `wrong_network` answer carries the first sentence when the site serves the vault's network, and the second while it has no address for it:

```text
This vault is on NEAR <network>. Open it at the <network> address.
This vault is on NEAR <network>, which this site does not serve yet.
```

## For developers: match the network

The SDK and the CLI take the network as a setting. The vault id and the RPC URLs you use must belong to that same network: a testnet vault ends in `.testnet`, a mainnet vault in `.near`.

- **SDK.** `new Probarion(...)` takes `network: "testnet"` or `network: "mainnet"`. Any other value throws a `ConfigError`. The RPC comes from the `rpcUrls` option, else `NEAR_RPC_URLS`, else the network's defaults in the table above.
- **CLI.** `--network` falls back to `NEAR_NETWORK`, then `testnet`. `--rpc` takes comma-separated URLs and falls back to `NEAR_RPC_URLS`, then the network's defaults.

Put both options on the command line and no environment variable can change the network or the RPC. `verify` still reads its archival RPC, for burn transactions older than about 2.5 days, from `NEAR_ARCHIVAL_RPC_URLS` unless you pass `--archival-rpc`. A testnet run:

```bash
node packages/cli/dist/bin.js --network testnet --rpc https://rpc.testnet.fastnear.com verify --vault v0.probarion.testnet
```

On this vault the run ends in `RESULT: FAIL` today, for the reason given above: its test spends of 2026-11-01 were sent without a ledger, so checks d and h fail. [Verify a vault](https://probarion.xyz/docs/trust/verify-a-vault.md) walks through this run and its output.

> **NEAR_RPC_URLS is not per network.**
>
> The SDK and the CLI read `NEAR_RPC_URLS` and `NEAR_ARCHIVAL_RPC_URLS` for whichever network you pass, and the CLI reads `PROBARION_FACTORY_ID` and `PROBARION_VAULT_ID` the same way. The repository's `.env.example` sets all of them to testnet values:
>
> ```text
> NEAR_NETWORK=testnet
> NEAR_RPC_URLS=https://rpc.testnet.fastnear.com
> NEAR_ARCHIVAL_RPC_URLS=https://archival-rpc.testnet.fastnear.com
> PROBARION_FACTORY_ID=vaults.probarion.testnet
> PROBARION_VAULT_ID=v0.probarion.testnet
> ```
>
> Nothing in the packages asks an RPC which chain it serves, and the CLI checks only that a factory or vault id is a well-formed account id. So a mainnet run with these values loaded talks to testnet, `vault create` prints a call to the testnet factory, and a command without `--vault` aims at `v0.probarion.testnet`. That follows from the code, and no test shows it yet. The `_MAINNET` and `_TESTNET` forms in the same file are the web console's settings: the SDK and the CLI never read them.
>
> For a mainnet run, pass `rpcUrls` or `--rpc`, or set `NEAR_RPC_URLS` to mainnet URLs. Also set `NEAR_ARCHIVAL_RPC_URLS` to a mainnet archival URL, or leave it unset so the network's FastNEAR archival node is used. `verify` also takes `--archival-rpc`. The SDK reads `NEAR_ARCHIVAL_RPC_URLS`, and a host can pass its own archival client instead, as the second constructor argument: `new Probarion(opts, { archivalRpc })`. Unset `PROBARION_FACTORY_ID` and `PROBARION_VAULT_ID` or set them to mainnet accounts, and pass `--vault`.

## The mainnet vault

On 2026-11-11 the owner ran the small demo path of the [mainnet runbook](https://github.com/probarion/probarion/blob/main/docs/runbooks/mainnet-v0.md), with real USDC and small amounts. The owner signed every transaction in their own terminal and wallet. `v0.probarion.near` is a standalone vault: its owner `probarion.near` created it, and it deployed the recorded build `3cQXYDvfGLRMveCVAHmh1exiuZKDXWqD8cUhqdEs9MF1` and called `new` itself, with no factory. It has no full-access key. Its one approver, `probarion-duong.near`, is the owner's own wallet, which is also the payee of its mandate.

- **One NEAR payment.** Under mandate 1, spend 1 paid 1 USDC on NEAR ([transaction](https://nearblocks.io/txns/22oqhgruo7JqdpPg5Cb2ts25mLK2fto8y1YAxNA56ieE)).
- **One refusal.** A spend against mandate 999, which does not exist, was refused on chain with `PROBARION:NoMandate` ([transaction](https://nearblocks.io/txns/2Dabq4uMh9VvttH3uj85samfYoX2wbQheADHS96AtwYh)).
- **No Base payout.** The runbook's Intents top-up, Base mandate and first Base payout did not run. Spike S1, a contract account withdrawing Base POA USDC to a Base address on mainnet, is unproven, so no Base payout has run on mainnet.
- **A pre-ledger decision.** The vault has no ledger. Its spend's decision hash is the sha256 of a decision file in the repository, not an entry of a signed ledger, and no TEE attestation covers it.

A live `verify` of the vault, with the repository's evidence and a mainnet RPC, passes checks a to h and skips check i, because the vault has no factory: see [its output of 2026-11-11](https://github.com/probarion/probarion/blob/main/docs/evidence/mainnet-v0/verify-2026-11-11.txt). Run it from a clone:

```bash
node packages/cli/dist/bin.js --network mainnet --rpc https://rpc.mainnet.fastnear.com verify --vault v0.probarion.near --evidence docs/evidence --proof docs/mainnet-proof.json
```

[`docs/evidence/mainnet-v0`](https://github.com/probarion/probarion/tree/main/docs/evidence/mainnet-v0) lists every transaction of the run. No console or proof page serves this vault: the site serves testnet only.

## When mainnet opens

All of this is Planned.

- **The rest of the v0 run.** The runbook's Base payout through NEAR Intents waits for spike S1. The owner runs every step on their own machine: the owner calls are signed in the owner's own wallet, and the spends with the vault's agent key file.
- **The mainnet factory.** Until `vaults.probarion.near` is deployed, the console cannot create a mainnet vault. Registering a vault that runs a recorded build, as `contracts/code-hashes.json` lists them, does not read the factory, but until a mainnet address is served the console cannot open or register a mainnet vault either.
- **The addresses.** The plan is that `probarion.xyz` serves mainnet and `testnet.probarion.xyz` serves testnet. Testnet sessions on the main address then end, and people sign in again at the testnet address. Neither change is live.
- **The docs.** Before the main address serves mainnet, the pages that say only testnet is live and the rules for agents are revised, and the site is built again: the Markdown twins and the llms files carry absolute links on the production address.
- **The record.** [`contracts/deployments/mainnet.json`](https://github.com/probarion/probarion/blob/main/contracts/deployments/mainnet.json) and [`docs/mainnet-proof.json`](https://github.com/probarion/probarion/blob/main/docs/mainnet-proof.json) record the v0 run of 2026-11-11. Their Base, Intents and factory fields stay empty until those steps run.

## Where to go next

- [What works today](https://probarion.xyz/docs/start/what-works-today.md) gives the status of every part.
- The [owner quickstart](https://probarion.xyz/docs/start/owner-quickstart.md) sets up a testnet vault in the console, with test USDC from the faucet.
- The [developer quickstart](https://probarion.xyz/docs/start/developer-quickstart.md) runs one payment cycle against a testnet vault with the SDK.
- [Verify a vault](https://probarion.xyz/docs/trust/verify-a-vault.md) runs the verifier on `v0.probarion.testnet` and shows why checks d and h fail there.
- [Vaults, roles and keys](https://probarion.xyz/docs/concepts/vaults-roles-and-keys.md) covers who signs what.
- The [security model](https://probarion.xyz/docs/trust/security-model.md) covers what is proven and what is not, and the [glossary](https://probarion.xyz/docs/resources/glossary.md) defines Probarion's terms.

## What this does not do

- **A testnet result is not a mainnet result.** The protocol versions can differ, and NEAR Intents is a stand-in. On mainnet only the small v0 run is recorded, with no Base payout.
- **Test tokens have no value.** A testnet result shows how the contract, the SDK and the console behave. It moves no real money, and the test USDC in a vault cannot pay a real invoice.
- **The site never moves a vault between networks.** Neither the address nor a setting changes the network a vault was registered on.
- **No mainnet address is served yet.** The addresses under [When mainnet opens](#when-mainnet-opens) are the plan, not a deployment.
- **The SDK and the CLI do not check the RPC's chain.** The console does, for sign-in and Register. In your own code, the network, the vault id, the factory and the RPC URLs must agree.
