100% non-custodial
Nirium never holds a key that can withdraw your funds, in any node. Below: who signs in each one, on the network you have selected, and then Payouts, Audit Trail and the treasury in detail.
Who signs, node by node
The buyer's own wallet signs each payment and a facilitator settles it on Stellar. If you sell with x402Serve, the USDC goes from the buyer straight to your account: Nirium is not in the path. If you pay Nirium's own API, Nirium is the seller and receives that payment.
TestnetThe testnet agent holds its own test key to pay for demo calls.
Runs inside the buyer's client, before anything is signed. If the policy says no, or does not answer in time, nothing is signed. Its decision is tied to the hash of the exact payment being signed. Nirium never sees the buyer's key.
TestnetSame on both networks.
You send a SHA-256 hash, or a small record of up to 8 KB, and it is pinned to IPFS. You get back a CID, which is the hash of the content, so nobody, Nirium included, can change what it points to. An optional signature with your own Stellar key proves who declared it, and invalid signatures are rejected. It holds no funds. IPFS records can't be deleted: send hashes, not personal data.
TestnetFree and rate-limited during the beta.
Read-only. It summarizes what is already recorded (payments, receipts, payout runs). It cannot sign or move anything.
TestnetPublic summary, no key needed.
Nirium builds each batch as an unsigned transaction. The company signs it with its own wallet, and only then is it sent. Nirium never holds the funds being paid out.
TestnetTestnet only: on Trustless Work escrows, the agent can sign milestone approvals and releases with its own key, limited to allowlisted escrow contracts and authorized API keys.
The agent can only rebalance, never withdraw. Details for each network are in the sections below.
TestnetNiriumVault, source-verified: only your key withdraws.
Payouts: the company signs, the receiver is fixed by a person
Nirium builds each batch as an unsigned transaction. The company signs it with its own wallet, and Nirium only sends the transaction it already signed. On mainnet it is invite-only: an authorized API key, the Payouts Terms accepted on every run, and the company identifies itself.
With Trustless Work escrows, a person signs the deployment, and that fixes who each milestone pays. If the escrow names Nirium's agent as approver or release signer, the agent can sign approvals and releases with its own key. Only for contracts on an allowlist that is empty by default and set on our server, and only for authorized API keys.
Someone could approve or release milestones of allowlisted escrows early. They could not send the money anywhere new: the approve and release calls take a milestone number, never a receiver. This flow is not enabled on mainnet.
Audit Trail: what a receipt proves, and what it does not
That this exact content, or its hash, is stored under this CID, and nobody can change it without the CID changing. If it is signed, that the holder of that Stellar key declared it. Invalid signatures are rejected, never stored.
That the content is true or complete. The time on the receipt is when Nirium's server recorded it, not a time on the Stellar ledger: today the record lives on IPFS. An unsigned receipt says nothing about who sent it.
nirium.xyz/verify, or npx nirium-cli verify <cid>, recompute the hash and check the signature from the raw content, not from what the document says about itself. Add --evidence <file> to compare it with your own file. If there is nothing to check, the CLI says NOTHING VERIFIED instead of passing.
What goes to IPFS can't be deleted, by us or anyone. Send a hash of your evidence, not personal data.
Treasury on mainnet: a DeFindex vault you own
Nirium's agent holds DeFindex's RebalanceManager role, nothing else. Our code only sends Invest and Unwind. The contract's rebalance() also accepts two swap instructions, but none of the four takes a destination address: whatever they produce stays in the vault, so the role cannot send funds anywhere. Worst case if the agent's key leaked: someone could swap at a bad price inside the vault and lose value to slippage.
The role that can withdraw (Manager) sits with the vault owner's key, separate from the agent's key. The owner can also replace the agent's role at any time.
The vault contract is DeFindex (PaltaLabs), audited by OtterSec in March 2025. Nirium did not write it.
Today the only live vault is Nirium's own, with its own funds: it proves the mechanism, not client use. Access for clients is invite-only while legal review closes.
Nirium's own contract: two kinds of control
Your vault: your key
- Only your key withdraws, and only to your own address
- Only your key closes the vault (its balance must be 0)
- You can delegate to the agent up to a cumulative cap you set (max_execution_amount)
- You can revoke the agent at any time, even while the contract is paused
Emergency pause: Nirium
- Nirium's admin key can pause the whole contract (every vault) in an emergency
- While paused, nobody can withdraw, deposit or close a vault, including you. Pausing never moves funds
- The contract supports a 2-of-3 pause (admin plus one cosigner). It is not active yet: no cosigners are registered (checked on-chain, 8 Nov 2026), so today the admin pauses alone. Registering them is planned
- Cosigners are contract-wide and set by the admin, not by each vault owner
What Nirium CANNOT do
Not a legal disclaimer - what the contracts themselves allow.
What Nirium CAN do on NiriumVault (testnet): pause the whole contract with its admin key. Today that takes no second signature. It freezes withdrawals until it is unpaused, but it cannot move funds.
The real contract
NiriumVault is deployed on Stellar Testnet and is verifiable.
CDMFURE6MYROTA2A6DLD4TN2S4QTN64L2FZ2I2RY2AREONX6DUQOI2S2d317ac7bf81ba47dda9a6d61270525c35d3e182a75e27998cf1b1b4ba8f88e7dGitHub built this WASM from the public repo (commit 8489481) and attested it, and that exact file is what was deployed. Stellar Expert matched it to the source and shows the contract as "verified". The code has no upgrade, migrate or set_wasm function and never calls update_current_contract_wasm, so it cannot be changed after deployment. Check it yourself: stellar contract fetch --id CDMFURE6MYROTA2A6DLD4TN2S4QTN64L2FZ2I2RY2AREONX6DUQOI2S2 --network testnet, then compare its sha256 with the release file.
The release: WASM and build attestationPrevious NiriumVault deployments (testnet)
They stay on testnet and cannot be changed. nirium.xyz no longer uses them, so vault counts restart on the verified contract.
May 2026. Used by nirium.xyz until 9 Nov 2026; 180 vaults were created on it, including our own tests. Unverified, and older than the 25 Oct security fix (FZN-2026-NIR-02).
25 Oct 2026. Redeployed with the FZN-2026-NIR-02 fix, but never connected to the site; 0 vaults. Unverified.
Not built yet: withdrawals that need 2 of 3 people
Today a withdrawal needs one signature: the vault owner's. The 2-of-3 in the contract only covers the emergency pause, and no cosigners are registered yet. A company that wants, say, its CFO, CEO and accountant to approve every withdrawal can get that from Stellar itself, without changing the contract: the vault owner is a Stellar account with three signers and a threshold of two. Soroban checks that account's signers against its medium threshold, so a withdrawal with a single signature is rejected by the network. What is missing is on our side: nirium.xyz signs with one wallet and cannot collect a second signature yet. Planned, not built.
Stellar docs: authorization and multisigAudit
Third-party contract, audited by its authors' auditor
No external audit yet: it stays on testnet until one is done
Security Status
Non-custodial nodes (settlement, audit, reporting) run on mainnet without holding funds. Payouts also runs on mainnet, invite-only while legal review closes. Treasury rebalancing runs on mainnet over DeFindex vaults (third-party, already audited), invite-only. NiriumVault, Nirium's own vault contract, has not yet undergone a formal third-party audit and stays on testnet until one is completed.