Once you’ve written and tested your smart contract, the next step is to deploy it to a Soroban network. This guide covers the deployment process from building to production deployment.
Prerequisites
Before deploying, ensure you have:
A working Soroban contract
Soroban CLI installed
A funded account on the target network
Your contract compiled to WebAssembly
Building for Production
Configure release profile
Optimize your Cargo.toml for production builds: [ profile . release ]
opt-level = "z" # Optimize for size
overflow-checks = true # Keep overflow checks
debug = 0 # No debug info
strip = "symbols" # Strip symbols
debug-assertions = false
panic = "abort" # Smaller panic handler
codegen-units = 1 # Better optimization
lto = true # Link-time optimization
These settings significantly reduce your contract’s WebAssembly size, which lowers deployment costs.
Build the contract
Build your contract with the release profile: cargo build --target wasm32-unknown-unknown --release
The compiled WebAssembly file will be located at: target/wasm32-unknown-unknown/release/your_contract.wasm
Optimize the WASM (optional)
Further optimize the WebAssembly using soroban-cli: soroban contract optimize \
--wasm target/wasm32-unknown-unknown/release/your_contract.wasm
This creates an optimized WASM file that’s typically smaller.
Deployment Process
1. Install Soroban CLI
If you haven’t already:
cargo install soroban-cli
Verify installation:
Add the network you want to deploy to:
soroban network add testnet \
--rpc-url https://soroban-testnet.stellar.org:443 \
--network-passphrase "Test SDF Network ; September 2015"
Create or import an identity:
# Generate a new identity
soroban keys generate deployer --network testnet
# Or import an existing secret key
soroban keys add deployer --secret-key
Keep your secret keys secure. Never commit them to version control or share them publicly.
4. Fund Your Account
For testnet/futurenet, use the friendbot to fund your account:
soroban keys fund deployer --network testnet
For mainnet, you’ll need to fund your account with XLM through normal Stellar channels.
5. Deploy the Contract
Deploy your contract to the network:
soroban contract deploy \
--wasm target/wasm32-unknown-unknown/release/your_contract.wasm \
--source deployer \
--network testnet
This will output your contract’s address:
CA3D5KRYM6CB7OWQ6TWYRR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQGAXE
Save this contract address - you’ll need it to invoke your contract.
Deploying with Constructor
If your contract has a constructor, you need to deploy and initialize in two steps:
Deploy the contract
CONTRACT_ID = $( soroban contract deploy \
--wasm target/wasm32-unknown-unknown/release/your_contract.wasm \
--source deployer \
--network testnet )
Initialize the contract
soroban contract invoke \
--id $CONTRACT_ID \
--source deployer \
--network testnet \
-- \
__constructor \
--init_key 100 \
--init_value 1000
Or deploy with automatic constructor invocation:
soroban contract deploy \
--wasm target/wasm32-unknown-unknown/release/your_contract.wasm \
--source deployer \
--network testnet \
-- \
--init_key 100 \
--init_value 1000
Invoking Your Contract
Once deployed, invoke contract functions:
soroban contract invoke \
--id CA3D5KRYM6CB7OWQ6TWYRR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQGAXE \
--source deployer \
--network testnet \
-- \
add \
--a 5 \
--b 7
Contract Installation vs Deployment
Soroban has a two-step process that can save costs:
Install Contract Code
Upload the WASM code once:
CODE_HASH = $( soroban contract install \
--wasm target/wasm32-unknown-unknown/release/your_contract.wasm \
--source deployer \
--network testnet )
echo $CODE_HASH
Deploy Contract Instances
Create multiple instances from the same code:
# Deploy first instance
CONTRACT_1 = $( soroban contract deploy \
--wasm-hash $CODE_HASH \
--source deployer \
--network testnet )
# Deploy second instance (cheaper, reuses code)
CONTRACT_2 = $( soroban contract deploy \
--wasm-hash $CODE_HASH \
--source deployer \
--network testnet )
Installing contract code separately is more efficient when you need to deploy multiple instances of the same contract.
Programmatic Deployment
Deploy contracts programmatically using the SDK’s deployer:
use soroban_sdk :: {contract, contractimpl, Env , Address , BytesN };
#[contractimpl]
impl Contract {
pub fn deploy_child (
env : Env ,
wasm_hash : BytesN < 32 >,
salt : BytesN < 32 >,
) -> Address {
// Deploy a new contract instance
env . deployer ()
. with_current_contract ( salt )
. deploy ( wasm_hash )
}
}
Managing Contract Storage
Extend TTL
Contract storage has a time-to-live (TTL). Extend it to prevent expiration:
# Extend instance TTL
soroban contract extend \
--id $CONTRACT_ID \
--ledgers-to-extend 100000 \
--durability persistent \
--source deployer \
--network testnet
Restore Expired Data
Restore expired contract data:
soroban contract restore \
--id $CONTRACT_ID \
--source deployer \
--network testnet
Upgrading Contracts
Contracts can be made upgradeable by implementing update functionality:
use soroban_sdk :: {contract, contractimpl, Env , BytesN };
#[contractimpl]
impl Contract {
pub fn upgrade ( env : Env , new_wasm_hash : BytesN < 32 >) {
// Check authorization
// ...
// Update contract code
env . deployer () . update_current_contract_wasm ( new_wasm_hash );
}
}
Then upgrade by invoking the upgrade function:
# Install new version
NEW_HASH = $( soroban contract install \
--wasm target/wasm32-unknown-unknown/release/your_contract_v2.wasm \
--source deployer \
--network testnet )
# Invoke upgrade function
soroban contract invoke \
--id $CONTRACT_ID \
--source deployer \
--network testnet \
-- \
upgrade \
--new_wasm_hash $NEW_HASH
Make contracts upgradeable carefully. Include proper authorization checks to prevent unauthorized upgrades.
Deployment Checklist
Before deploying to production:
Monitoring Deployed Contracts
After deployment, monitor your contract:
# Get contract info
soroban contract info \
--id $CONTRACT_ID \
--network testnet
# View contract storage
soroban contract fetch \
--id $CONTRACT_ID \
--network testnet
Cost Considerations
Code Size : Smaller WASM files cost less to deploy
Storage : Persistent storage has ongoing costs
TTL : Longer TTLs cost more upfront
Invocations : Each function call consumes resources
Use the testutils budget tracking during testing to estimate resource costs before deploying.
Next Steps
Testing Write comprehensive tests before deployment
Events Monitor contracts with events