This guide covers deploying Ethos-Protocol to Stellar mainnet with security best practices, configuration, and rollback procedures.
- Rust 1.70+
- Soroban CLI (latest)
- Stellar CLI
- A funded Stellar mainnet account for deployment
- Access to secure key management infrastructure
Never use seed phrases in deployment scripts. Use Stellar CLI key management:
# Generate a deployment key (mainnet)
stellar keys generate deployer-mainnet --network mainnet
# Verify the key exists
stellar keys listStore the public key securely. The private key is managed by Stellar CLI in ~/.stellar/keys/.
Create .env.mainnet:
# Network
STELLAR_NETWORK=mainnet
STELLAR_MAINNET_RPC_URL=https://mainnet.sorobanrpc.com
# Deployment
DEPLOYER_IDENTITY=deployer-mainnet
CONTRACT_ADMIN=<admin-public-key>
# Monitoring
LOG_LEVEL=info
SENTRY_DSN=<optional-error-tracking>- Verify contract builds without warnings:
cargo build --package ttl-vault --lib --release - All tests pass:
cargo test --package ttl-vault - Security audit passes:
cargo audit - Code review completed
- Deployment key funded with XLM for fees (~10 XLM recommended)
- Admin key is secure and backed up
- Beneficiary address format validated
./scripts/build.shThis produces optimized WASM binaries in target/wasm32-unknown-unknown/release/.
export STELLAR_MAINNET_RPC_URL=https://mainnet.sorobanrpc.com
./scripts/deploy_mainnet.shThe script will:
- Display target network and identity
- Require confirmation (type
mainnet) - Deploy the contract
- Output the contract ID
Save the contract ID — you'll need it for initialization and frontend configuration.
After deployment, initialize with admin and token:
stellar contract invoke \
--network mainnet \
--id <CONTRACT_ID> \
--source-account deployer-mainnet \
-- initialize \
--token <STELLAR_ASSET_ADDRESS> \
--admin <ADMIN_PUBLIC_KEY>For native XLM, use the standard Stellar asset contract address.
Mainnet WASM artifacts must be byte-for-byte reproducible from source so that external auditors can independently verify deployed bytecode matches the audited commit.
scripts/build.sh pins the exact rustc version (currently 1.96.1,
matching the CI toolchain in .github/workflows/ci.yml) and warns if the
active toolchain doesn't match. Install the pinned version with:
rustup install 1.96.1
rustup override set 1.96.1scripts/build.sh sets the following before compiling:
SOURCE_DATE_EPOCH=0— normalizes any timestamp embedded by build scriptsCARGO_INCREMENTAL=0— disables incremental compilation artifacts that can vary between runsRUSTFLAGS="--remap-path-prefix=$(pwd)=."— strips the absolute checkout path from embedded debug info, so identical source produces identical output regardless of where it's checked out
After building, scripts/build.sh writes SHA-256 hashes of every produced
.wasm file to target/wasm-hashes.txt.
rm -rf target && ./scripts/build.sh
cp target/wasm-hashes.txt /tmp/hashes-a.txt
rm -rf target && ./scripts/build.sh
diff /tmp/hashes-a.txt target/wasm-hashes.txtNo output from diff means the build is reproducible.
.github/workflows/reproducible-build.yml runs on every push and PR to
main: it builds twice from the same checkout (using separate
CARGO_HOME directories to avoid cache leakage between the two builds),
diffs the resulting WASM hashes, and fails the job if they differ. A
failing reproducible-build job should block merge until the
non-determinism is root-caused — do not silence it by disabling the check.
- Deployment key stored in Stellar CLI keystore (not in files)
- Admin key backed up in secure location (hardware wallet or vault)
- No seed phrases in environment variables or logs
- Key rotation plan documented
- Access to deployment credentials restricted to authorized personnel
- RPC endpoint rate limits configured (if using private RPC)
- Monitoring alerts set up for contract errors
- Transaction fee monitoring enabled
- Unusual activity alerts configured
- All deployments logged with timestamp, deployer, and contract ID
- Contract initialization events logged
- Admin actions logged to external system (e.g., Sentry, CloudWatch)
- Logs retained for 90+ days
- Contract responds to
get_admin()call - Contract responds to
get_contract_token()call - Test vault creation with small amount
- Verify beneficiary payout mechanism works
- Monitor for errors in first 24 hours
If a critical bug is discovered before users interact with the contract:
- Pause Operations: Notify all users to stop using the contract
- Deploy Patch: Fix the bug and deploy a new contract
- Migrate State: If needed, migrate vault data to new contract (requires custom migration logic)
- Update Frontend: Point frontend to new contract ID
- Communicate: Post-mortem and transparency report
If users have already created vaults:
- Assess Impact: Determine which vaults are affected
- Notify Users: Communicate the issue and mitigation plan
- Deploy Patch: Deploy a new contract with the fix
- Provide Migration Path: Offer users ability to migrate vaults to new contract
- Maintain Old Contract: Keep old contract running for users who choose not to migrate
- Immediate Action: Disable affected functionality if possible
- Notify Users: Send urgent security notice
- Deploy Patch: Deploy fixed contract immediately
- Audit: Conduct security audit of the fix
- Post-Incident Review: Document lessons learned
The deployment key doesn't have enough XLM. Fund it:
# Get the public key
stellar keys show deployer-mainnet
# Fund via Stellar testnet faucet (for testnet) or transfer from another accountVerify the token address is correct:
stellar contract read \
--network mainnet \
--id <CONTRACT_ID> \
--key <ADMIN_KEY>Check RPC endpoint availability:
curl https://mainnet.sorobanrpc.com/healthIf the endpoint is down, switch to an alternative RPC provider.
The contract may already be initialized. Verify:
stellar contract invoke \
--network mainnet \
--id <CONTRACT_ID> \
-- get_adminIf it returns an admin, the contract is already initialized.
- Contract responds to read-only calls
- No error spikes in logs
- RPC endpoint latency normal
- Review vault creation metrics
- Check for failed transactions
- Verify beneficiary payouts are processing
- Security audit of recent changes
- Performance review
- Backup verification
For deployment issues:
- Check this guide's troubleshooting section
- Review contract logs and RPC responses
- Consult SECURITY.md for security concerns
- Open an issue on GitHub with deployment logs (sanitized)