Deploy Contracts
by @iskysun96
Safely deploys Move contracts to Aptos networks (devnet, testnet, mainnet) with pre-deployment verification. Triggers on: 'deploy contract', 'publish to test...
clawhub install deploy-contractsπ About This Skill
name: deploy-contracts description: "Safely deploys Move contracts to Aptos networks (devnet, testnet, mainnet) with pre-deployment verification. Triggers on: 'deploy contract', 'publish to testnet', 'deploy to mainnet', 'how to deploy', 'publish module', 'deployment checklist', 'deploy to devnet'." license: MIT metadata: author: aptos-labs version: "1.0" category: move tags: ["deployment", "devnet", "testnet", "mainnet", "publishing"] priority: high
Deploy Contracts Skill
Overview
This skill guides safe deployment of Move contracts to Aptos networks. Always deploy to testnet before mainnet.
Pre-Deployment Checklist
Before deploying, verify ALL items:
Security Audit β CRITICAL - See SECURITY.md
security-audit skill)Testing
aptos move test --coverageaptos move testCode Quality
aptos move compileConfiguration
my_addr = "_"Object Deployment (Modern Pattern)
CRITICAL: Use Correct Deployment Command
There are TWO ways to deploy contracts. For modern object-based contracts, use deploy-object:
β CORRECT: Object Deployment (Modern Pattern)
aptos move deploy-object \
--address-name my_addr \
--profile devnet \
--assume-yes
What this does:
1. Creates an object to host your contract code 2. Deploys the package to that object's address 3. Returns the object address (deterministic, based on deployer + package name) 4. Object address becomes your contract address
β WRONG: Using Regular Publish for Object Contracts
# β Don't use this for object-based contracts
aptos move publish \
--named-addresses my_addr=
When to use each:
deploy-object: Modern contracts using objects (RECOMMENDED)publish: Legacy account-based deployment (older pattern)How to tell if you need object deployment:
init_moduleobject::create_named_object()Alternative Object Deployment Commands
Option 1: deploy-object (Recommended - Simplest)
aptos move deploy-object --address-name my_addr --profile devnet
Option 2: create-object-and-publish-package (Advanced)
aptos move create-object-and-publish-package \
--address-name my_addr \
--named-addresses my_addr=default
Recommendation: Always use deploy-object unless you have a specific reason to use the alternative.
Deployment Workflow
Step 1: Test Locally
# Ensure all tests pass
aptos move testVerify 100% coverage
aptos move test --coverage
aptos move coverage summary
Expected output: "coverage: 100.0%"
Step 2: Compile
# Compile contract
aptos move compile --named-addresses my_addr=Verify compilation succeeds
echo $?
Expected: 0 (success)
Step 3: Deploy to Devnet (Optional)
Devnet is for quick testing and experimentation. Account is auto-funded on aptos init.
Check if a profile exists before initializing:
# Check if default profile exists (look for "default" in output)
aptos config show-profilesIf no profile exists, initialize one (auto-funds on devnet)
aptos init --network devnet --assume-yes
# Deploy as object (modern pattern)
aptos move deploy-object \
--address-name my_addr \
--profile default \
--assume-yesSave the object address from output for future upgrades
Output: "Code was successfully deployed to object address 0x..."
Verify deployment
aptos account list --account --profile default
Step 4: Deploy to Testnet (REQUIRED)
Testnet is for final testing before mainnet.
Check if a profile exists before initializing:
# Check if default profile exists
aptos config show-profilesIf no profile exists, initialize one
aptos init --network testnet --assume-yes
Fund your account via web faucet (required β testnet faucet needs Google login):
1. Get your account address: aptos config show-profiles
2. Go to: https://aptos.dev/network/faucet?address=
3. Login and request testnet APT
4. Return here and confirm you've funded the account
# Verify balance
aptos account balance --profile defaultDeploy to testnet as object (modern pattern)
aptos move deploy-object \
--address-name my_addr \
--profile default \
--assume-yesIMPORTANT: Save the object address from output
You'll need it for upgrades and function calls
Output: "Code was successfully deployed to object address 0x..."
Step 5: Test on Testnet
# Run entry functions to verify deployment
aptos move run \
--profile default \
--function-id :::: \
--args ...Test multiple scenarios
- Happy paths
- Error cases (should abort with correct error codes)
- Access control
- Edge cases
Verify using explorer
https://explorer.aptoslabs.com/?network=testnet
Step 6: Deploy to Mainnet (After Testnet Success)
Only deploy to mainnet after thorough testnet testing.
Check if a profile exists before initializing:
# Check if default profile exists
aptos config show-profilesIf no profile exists, initialize one
IMPORTANT: Warn user that this generates a private key β store it securely
aptos init --network mainnet --assume-yes
Fund your account: Transfer real APT to your account address from an exchange or wallet.
# Verify balance
aptos account balance --profile defaultDeploy to mainnet as object (modern pattern)
aptos move deploy-object \
--address-name my_addr \
--profile default \
--max-gas 20000 # Optional: set gas limitReview prompts carefully before confirming:
1. Gas confirmation: Review gas costs
2. Object address: Note the object address for future reference
OR use --assume-yes to auto-confirm (only if you're confident)
aptos move deploy-object \
--address-name my_addr \
--profile default \
--assume-yesSAVE THE OBJECT ADDRESS from output
You'll need it for upgrades and documentation
Confirm deployment
Review transaction in explorer:
https://explorer.aptoslabs.com/?network=mainnet
Step 7: Verify Deployment
# Check module is published
aptos account list --account --profile defaultLook for your module in the output
"0x...::my_module": { ... }
Run view function to verify
aptos move view \
--profile default \
--function-id :::: \
--args ...
Step 8: Document Deployment
Create deployment record:
# Deployment RecordDate: 2026-01-23 Network: Mainnet Module: my_module Address: 0x123abc... Transaction: 0x456def...
Verification
[x] Deployed successfully
[x] Module visible in explorer
[x] View functions working
[x] Entry functions tested Links
Explorer: https://explorer.aptoslabs.com/account/0x123abc...?network=mainnet
Transaction: https://explorer.aptoslabs.com/txn/0x456def...?network=mainnet Notes
All security checks passed
100% test coverage verified
Tested on testnet for 1 week before mainnet
Module Upgrades
Upgrading Existing Object Deployment
Object-deployed modules are upgradeable by default for the deployer.
# Upgrade existing object deployment
aptos move upgrade-object \
--address-name my_addr \
--object-address \
--profile mainnetUpgrade with auto-confirm
aptos move upgrade-object \
--address-name my_addr \
--object-address \
--profile mainnet \
--assume-yesVerify upgrade
aptos account list --account --profile mainnet
IMPORTANT: Save the object address from your initial deploy-object output - you need it for upgrades.
Upgrade Compatibility Rules:
Making Modules Immutable
To prevent future upgrades:
// In your module
fun init_module(account: &signer) {
// After deployment, burn upgrade capability
// (implementation depends on your setup)
}
Cost Estimation
Gas Costs
# Typical deployment costs:
- Small module: ~500-1000 gas units
- Medium module: ~1000-5000 gas units
- Large module: ~5000-20000 gas units
When you run deploy-object, the CLI shows gas estimate before confirming
Use --assume-yes only after you've verified costs on testnet first
Mainnet Costs
Gas costs are paid in APT:
Multi-Module Deployment
Deploying Multiple Modules
Option 1: Single package (Recommended)
project/
βββ Move.toml
βββ sources/
βββ module1.move
βββ module2.move
βββ module3.move
# Deploys all modules at once as a single object
aptos move deploy-object --address-name my_addr --profile testnet
Option 2: Separate packages with dependencies
# Deploy dependency package first
cd dependency-package
aptos move deploy-object --address-name dep_addr --profile testnet
Note the object address from output
Update main package Move.toml to reference dependency address
Then deploy main package
cd ../main-package
aptos move deploy-object --address-name main_addr --profile testnet
Troubleshooting Deployment
"Insufficient APT balance"
Devnet: Auto-funded on aptos init. If needed, run:
aptos account fund-with-faucet --account default --amount 100000000 --profile default
Testnet: Use the web faucet (requires Google login):
1. Get your account address: aptos config show-profiles
2. Go to: https://aptos.dev/network/faucet?address=
3. Login and request testnet APT
4. Verify balance: aptos account balance --profile default
Mainnet: Transfer real APT to your account from an exchange or wallet.
"Module already exists" (for object deployments)
# Use upgrade-object with the original object address
aptos move upgrade-object \
--address-name my_addr \
--object-address \
--profile testnet
"Compilation failed"
# Fix compilation errors first
aptos move compile
Fix all errors shown, then retry deployment
"Gas limit exceeded"
# Increase max gas
aptos move deploy-object \
--address-name my_addr \
--profile testnet \
--max-gas 50000
Deployment Checklist
Before Deployment:
During Deployment:
After Deployment:
CLI Argument Types
When calling entry or view functions via the CLI, use these type prefixes:
Primitive Types
--args u64:1000 # u8, u16, u32, u64, u128, u256
--args bool:true # boolean
--args address:0x1 # address
Complex Types
--args string:"Hello World" # UTF-8 string
--args hex:0x48656c6c6f # raw bytes
--args "u64:[1,2,3,4,5]" # vector
--args "string:[\"one\",\"two\",\"three\"]" # vector
Object Types
# For Object parameters, pass the object address
--args address:0x123abc...
ALWAYS Rules
security-audit skill)deploy-object (NOT resource_account::create_resource_account() which is legacy)NEVER Rules
~/.aptos/config.yaml or .env files (contain private keys)"0x..." placeholderscat ~/.aptos/config.yaml, echo $VITE_MODULE_PUBLISHER_ACCOUNT_PRIVATE_KEY, or similar commandsgit add . or git add -A without confirming .env is in .gitignoreReferences
Official Documentation:
Explorers:
Related Skills:
security-audit - Audit before deploymentgenerate-tests - Ensure tests existRemember: Security audit β 100% tests β Testnet β Thorough testing β Mainnet. Never skip testnet.
βοΈ Configuration
my_addr = "_"