Step-by-step guide for deploying TrustLink to Stellar mainnet. Complete the mainnet-checklist.md before starting.
Run through these checks immediately before executing the deployment. Each must pass or be formally waived.
# 1. All tests green
cargo test
# 2. Build the optimized WASM
make optimize
# 3. Record the WASM size — must be < 100 KB
ls -lh target/wasm32-unknown-unknown/release/trustlink.optimized.wasm
# 4. Record the SHA-256 hash for post-deploy verification
sha256sum target/wasm32-unknown-unknown/release/trustlink.optimized.wasm| Check | Expected |
|---|---|
cargo test exit code |
0 |
| WASM artifact exists | trustlink.optimized.wasm present |
| WASM size | < 100 KB |
| SHA-256 recorded | noted for step 4 |
| Admin key on hardware wallet | confirmed |
| Testnet smoke-test passed | confirmed |
| Security audit sign-off | confirmed |
Set environment variables once; all commands below reference them.
export ADMIN_SECRET=SXXX... # hardware wallet or secure store — never commit
export ADMIN_PUBLIC=GXXX... # corresponding public keystellar contract upload \
--source "$ADMIN_SECRET" \
--network mainnet \
--wasm target/wasm32-unknown-unknown/release/trustlink.optimized.wasmExpected output:
<WASM_HASH> # 64-character hex string — save this
Verify the hash matches the SHA-256 recorded in the pre-deployment checklist.
stellar contract deploy \
--wasm-hash <WASM_HASH> \
--source "$ADMIN_SECRET" \
--network mainnetExpected output:
<CONTRACT_ID> # C... address — save this
export CONTRACT_ID=<CONTRACT_ID>stellar contract invoke \
--id "$CONTRACT_ID" \
--source "$ADMIN_SECRET" \
--network mainnet \
-- initialize \
--admin "$ADMIN_PUBLIC" \
--ttl_days nullExpected output: null (no return value on success).
Repeat for each trusted issuer:
stellar contract invoke \
--id "$CONTRACT_ID" \
--source "$ADMIN_SECRET" \
--network mainnet \
-- register_issuer \
--admin "$ADMIN_PUBLIC" \
--issuer <ISSUER_PUBLIC_KEY>Expected output: null.
Run these checks immediately after deployment to confirm the contract is live and correctly initialized.
stellar contract invoke \
--id "$CONTRACT_ID" \
--network mainnet \
-- get_adminExpected: "<ADMIN_PUBLIC>" — must match $ADMIN_PUBLIC.
stellar contract invoke \
--id "$CONTRACT_ID" \
--network mainnet \
-- health_checkExpected:
{ "initialized": true, "admin_set": true, "issuer_count": <N>, "total_attestations": 0 }stellar contract invoke \
--id "$CONTRACT_ID" \
--network mainnet \
-- is_issuer \
--issuer <ISSUER_PUBLIC_KEY>Expected: true for each issuer registered in step 4.
Use the verification script (creates and revokes a test attestation, then cleans up):
./scripts/verify_deployment.sh \
--contract "$CONTRACT_ID" \
--source "$ADMIN_SECRET" \
--network mainnetExpected exit code: 0.
| Field | Value |
|---|---|
| Contract ID | |
| WASM hash | |
| Deploy transaction | |
| Init transaction | |
| Deployed by | |
| Date (UTC) |
Commit these values to DEPLOYMENT.md.
TrustLink does not support deleting a deployed contract — Soroban storage is immutable. "Rollback" means one of two things depending on the situation:
Use this when a new version was deployed but the previous version was stable.
# 1. Re-upload the previous optimized WASM
stellar contract upload \
--source "$ADMIN_SECRET" \
--network mainnet \
--wasm <PATH_TO_PREVIOUS_WASM>
# Outputs: <PREVIOUS_WASM_HASH>
# 2. Invoke upgrade on the live contract
stellar contract invoke \
--id "$CONTRACT_ID" \
--source "$ADMIN_SECRET" \
--network mainnet \
-- upgrade \
--admin "$ADMIN_PUBLIC" \
--new_wasm_hash <PREVIOUS_WASM_HASH>
# 3. Verify admin and state are intact
stellar contract invoke \
--id "$CONTRACT_ID" \
--network mainnet \
-- get_adminAll storage (issuers, attestations) is preserved — only the executable is replaced.
If the contract cannot be upgraded (e.g. the upgrade function itself is
broken), pause activity and deploy a fresh instance:
- Communicate the incident to all issuers and integrators immediately.
- Deploy a new contract instance following section 2.
- Re-register all issuers on the new instance.
- Update all integrators with the new
CONTRACT_ID. - Mark the old contract as deprecated in
DEPLOYMENT.md.
| Situation | Action |
|---|---|
| Bug in new version, previous version stable | Option A — upgrade back |
| Critical security vulnerability, contract must stop | Option B — pause and redeploy |
| Data corruption or storage inconsistency | Option B — redeploy; assess migration |
The admin key holder is responsible for executing the rollback. A second authorized team member must confirm the decision before execution on mainnet.
Related: mainnet-checklist.md · DEPLOYMENT.md · docs/security.md · docs/monitoring.md