Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Deployment and operations

A practical guide for deploying a Tholos instance and operating it afterward. For what each function does, see CONTRACT.md. For design rationale, see ARCHITECTURE.md.

Before you deploy

This is testnet-only until audited. See SECURITY.md. Don’t point a Tholos instance at real value on mainnet without an independent security review first.

Decide these parameters up front; none of them (except the resolver committee) can be changed after initialize:

ParameterGuidance
tokenAny SEP-41 token your users already hold. No swap step exists, so picking a token nobody has is a dead deployment.
bond_amountHigh enough to make spam assertions and bad-faith disputes costly, low enough that legitimate use isn’t priced out. There’s no data-driven formula for this yet; start conservative and watch real usage.
challenge_window_secsLong enough that people who’d actually catch a bad assertion have a realistic chance to see it and act. Short windows finalize faster but catch less.
resolversOdd-length, non-zero. Pick people who’ll actually be reachable to vote within a reasonable time of a dispute; a slow resolver committee stalls every disputed assertion until it acts.

Deploying

# Build the optimized wasm
cd contracts/tholos && stellar contract build

# Deploy
CONTRACT=$(stellar contract deploy --wasm target/wasm32v1-none/release/tholos.wasm \
  --source deployer --network testnet)

# Initialize
stellar contract invoke --id "$CONTRACT" --source deployer --network testnet -- initialize \
  --admin "$ADMIN_ADDRESS" \
  --token "$TOKEN_CONTRACT_ID" \
  --bond_amount 1000000 \
  --challenge_window_secs 3600 \
  --resolvers "[\"$R1\",\"$R2\",\"$R3\"]"

scripts/testnet-smoke.sh automates this full sequence plus assert/dispute/resolve against real testnet infrastructure; run it to sanity-check a fresh deploy before handing the contract id to anyone.

Admin runbook

Pausing during an incident

If something looks wrong (a bug is found, a resolver key looks compromised, vote behavior looks off), pause first and investigate second:

stellar contract invoke --id "$CONTRACT" --source admin --network testnet -- set_paused --paused true

This stops new assert_outcome, dispute, and resolve calls immediately. Assertions already Pending can still finalize normally, so you aren’t freezing funds that were never at risk. Unpause the same way with --paused false once the issue is resolved.

Rotating the resolver committee

Works whether paused or not, so a compromised committee can be replaced without waiting to unpause:

stellar contract invoke --id "$CONTRACT" --source admin --network testnet -- update_resolvers \
  --new_resolvers "[\"$NEW_R1\",\"$NEW_R2\",\"$NEW_R3\"]"

The new committee must be odd-length. Resolvers removed mid-dispute simply lose the ability to cast further votes on assertions already in flight; resolvers added mid-dispute can vote on assertions that were disputed before they joined. See CONTRACT.md for the full detail.

Checking state

Read-only, no auth required:

stellar contract invoke --id "$CONTRACT" --source admin --network testnet -- get_assertion_state --id 0

Mainnet readiness checklist

Not a green light to deploy to mainnet on its own: a checklist of what’s true today, so you can judge what’s still missing for your use case:

  • Core propose/dispute/resolve flow implemented and unit tested
  • Reentrancy hardened, with a regression test proving it
  • Admin pause and resolver rotation available for incident response
  • Exercised end-to-end against real Stellar testnet infrastructure
  • Independent security audit
  • Real-world dispute volume tested (all testing so far is synthetic)
  • Bond sizing validated against real spam/griefing attempts, not just reasoned about
  • Fee/reward mechanism for uncontested finalizes (currently none; see CONTRACT.md)