This guide documents the deployment flow implemented by scripts/deploy-contracts.sh for the workspace contracts under contracts/:
nova_tokenreward_poolvestingreferraladmin_roles
The script builds each package, optimizes the generated WASM, uploads it to the selected network, deploys a contract instance, invokes initialize, and records the contract ID in .env.<network>.
Install the required toolchain:
rustup target add wasm32-unknown-unknown
cargo install --locked stellar-cli --features optInstall wasm-opt:
# macOS
brew install binaryen
# Ubuntu / Debian
sudo apt install binaryenFund the deployer account before broadcasting transactions. Use Friendbot on testnet, or your standard treasury process on mainnet.
Export these variables before running the deployment script:
| Variable | Required | Description |
|---|---|---|
DEPLOYER_SECRET |
Yes | Secret key used for upload, deploy, and initialize transactions |
ADMIN_ADDRESS |
Yes | Address passed to each contract initializer |
NETWORK |
No | testnet by default, or mainnet |
TESTNET_RPC_URL |
No | Overrides the default testnet RPC endpoint |
MAINNET_RPC_URL |
No | Overrides the default mainnet RPC endpoint |
ADMIN_SIGNERS |
No | Space-separated signer list for admin_roles; defaults to ADMIN_ADDRESS |
ADMIN_THRESHOLD |
No | Threshold for admin_roles; defaults to 1 |
Example:
export DEPLOYER_SECRET=S...
export ADMIN_ADDRESS=G...
export NETWORK=testnet
export ADMIN_SIGNERS="$ADMIN_ADDRESS"
export ADMIN_THRESHOLD=1From the repository root:
bash scripts/deploy-contracts.shTo preview the generated commands without broadcasting:
bash scripts/deploy-contracts.sh --dry-runThe script deploys contracts in this order:
| Order | Package | Output env key | initialize arguments |
|---|---|---|---|
| 1 | nova_token |
NOVA_TOKEN_CONTRACT_ID |
admin |
| 2 | reward_pool |
REWARD_POOL_CONTRACT_ID |
admin |
| 3 | vesting |
CLAIM_DISTRIBUTION_CONTRACT_ID |
admin |
| 4 | referral |
STAKING_CONTRACT_ID |
admin |
| 5 | admin_roles |
ADMIN_ROLES_CONTRACT_ID |
admin, signers, threshold |
For each package, it performs this pipeline:
cargo build --manifest-path contracts/Cargo.toml --target wasm32-unknown-unknown --release -p <package>wasm-opt -Oz --strip-debugstellar contract uploadstellar contract deploystellar contract invoke -- initialize ...- Upsert the resulting contract ID into
.env.<NETWORK>
The script derives RPC settings from NETWORK:
| Network | Default RPC URL | Network passphrase |
|---|---|---|
testnet |
https://soroban-testnet.stellar.org |
Test SDF Network ; September 2015 |
mainnet |
https://soroban-rpc.stellar.org |
Public Global Stellar Network ; September 2015 |
Override these with TESTNET_RPC_URL or MAINNET_RPC_URL when required.
After a successful run, .env.testnet or .env.mainnet will contain entries like:
NOVA_TOKEN_CONTRACT_ID=C...
REWARD_POOL_CONTRACT_ID=C...
CLAIM_DISTRIBUTION_CONTRACT_ID=C...
STAKING_CONTRACT_ID=C...
ADMIN_ROLES_CONTRACT_ID=C...
Re-running the script updates existing values for the same keys.
After deployment:
- Inspect
.env.<NETWORK>and confirm all five contract IDs were written. - Invoke representative read methods on each deployed contract to confirm initialization succeeded.
- Store the uploaded WASM hashes alongside the contract IDs for future upgrades.
Useful checks include:
nova_token.balancereward_pool.get_balancevesting.pool_balancereferral.pool_balanceadmin_roles.get_admin
- This script only covers the workspace contracts listed in
contracts/Cargo.toml. - The separate
contracts/nova-rewardscrate is not part of that workspace and must be built and deployed independently. - If an
initializesignature changes, update the contract andscripts/deploy-contracts.shtogether.