Skip to main content

Deploy WASM Contract

Deploy your ink! smart contract to Mandala Testnet using Polkadot.js Apps interface and learn how to interact with deployed contracts.

Overview​

This guide covers the complete deployment process for ink! contracts on Mandala Testnet, from uploading contract code to instantiating and interacting with your deployed contract.

Prerequisites​

Before deploying, ensure you have:

Contract Deployment Process​

Understanding the Two-Step Process​

ink! contract deployment involves two steps:

  1. Upload Code - Store the WASM code on-chain (code hash)
  2. Instantiate Contract - Create a contract instance with specific parameters

This separation allows multiple contract instances to share the same code, reducing storage costs.

Step 1: Upload Contract Code​

Accessing the Contracts Interface​

  1. Navigate to Polkadot.js Apps:

    https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frpc1.paseo.mandalachain.io#/contracts
  2. Go to Developer → Contracts

  3. Verify you're connected to Mandala (check network name in top-left)

    developer-contracts.png

Upload Process​

  1. Click "Upload a new contract"

    upload-a-new-contract.png

  2. Select your contract files:

    • Contract Bundle: Choose flipper.contract (recommended)
    • Or separately: Upload flipper.wasm and flipper.json
  3. Review contract details:

    • Contract name: "flipper"
  1. Configure upload parameters:
    • Account: Select your funded account
    • Storage Deposit: Auto-calculated (usually ~1.57 nano KPGT)
  1. Click "Next"

    contract-bundle.png

    deploy-code.png

    sign-and-submit-deploy.png

    uplod-contract-transaction-password.png

Step 2: Instantiate Contract​

Starting Instantiation​

  1. Click "Add an existing contract" or "Instantiate" next to your uploaded code

    add-an-existing-contract.png

    add-an-exiting-contract-save.png

    flipper-contract.png

Interacting with Deployed Contract​

Contract Interface​

Once deployed, your contract interface shows:

Contract Information:

  • Contract address
  • Code hash
  • Current balance
  • Deployment block

Available Messages:

  • flip() - Toggle the boolean value

    flip-exce.png

    flipper-message-to-send-contract.png

    flipper-contract-sign-and-submit.png

    flipper-transaction-password.png

    flipper-contract-done.png

  • get() - Read current value

    get-value.png

    get-read.png

    contract-read.png

Reading Contract State​

Call the get() function:

  1. Expand your contract in the contracts list
  2. Click "Call" next to get()
  3. Set call parameters:
    • Account: Any account (reading is free)
  4. Click "Read"

Result: Shows current boolean value (true/false)

get-value.png

get-read.png

contract-read.png

Sending Transactions​

Call the flip() function:

  1. Click "Exec" next to flip()

    flipper-contract.png

  2. Configure transaction:

    • Account: Your funded account
  3. Click "Execute"

    flipper-message-to-send-contract.png

  4. Sign the transaction

    flipper-contract-sign-and-submit.png

    flipper-transaction-password.png

    flipper-contract-done.png

Transaction result:

  • Success/failure status
  • Gas used
  • Events emitted

Monitoring Events​

View emitted events:

  1. Go to Network → Explorer
  2. Find your transaction in recent blocks
  3. Expand transaction details
  4. Check Events tab

Advanced Deployment Options​

Using Command Line​

Deploy via cargo-contract CLI:

# Upload code only
cargo contract upload --suri //Alice --url wss://rpc1.paseo.mandalachain.io

# Instantiate with specific constructor
cargo contract instantiate \
--constructor new \
--args true \
--suri //Alice \
--url wss://rpc1.paseo.mandalachain.io


# Deploy (upload + instantiate in one command)
cargo contract instantiate \
--constructor new \
--args false \
--suri //Alice \
--url wss://rpc1.paseo.mandalachain.io \
--skip-confirm

Batch Deployment​

Deploy multiple instances efficiently:

# Upload once
cargo contract upload --suri //Alice

# Instantiate multiple times with different parameters
for i in {1..5}; do
cargo contract instantiate \
--constructor new \
--args $([ $((i % 2)) -eq 0 ] && echo "true" || echo "false") \
--suri //Alice \
--skip-confirm
done

Contract Management​

Contract Information​

Retrieving contract details:

  1. Copy contract address from Polkadot.js Apps

  2. Use Developer → Chain state

  3. Query: contracts.contractInfoOf(address)

    developer-chain-state.png

    chain-state-contractinfoof.png

Returned information:

{
"trieId": "0x...",
"depositAccount": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"depositValue": "1000000000000",
"codeHash": "0x1234...",
"storageDeposit": "5000000000000"
}

contract-returned-information.png

Contract Storage​

View contract storage:

contract-chain-nonce.png

chain-starte-nonce.png

# Query specific storage keys
contracts.contractStorageOf(address, key)

# For Flipper, the boolean value storage key
# Key calculation depends on storage layout

Contract Balance Management​

pallet-version-chain-state.png

pallet-version-returned-information.png

Check contract balance:

// Via chain state
system.account(contractAddress)

// Result shows contract's token balance

Transfer tokens to contract:

// Use balances.transfer extrinsic
balances.transfer(contractAddress, amount)

Troubleshooting Deployment​

Common Deployment Errors​

"OutOfGas" Error:

Solution: Increase gas limit
- Try doubling the gas limit
- Check contract complexity
- Verify constructor logic

"StorageDepositLimitExhausted":

Solution: Increase storage deposit
- Add more KPGT to your account
- Check storage requirements
- Optimize contract storage

"CodeRejected":

Solution: Verify contract compilation
- Rebuild with cargo contract build --release
- Check WASM validation
- Verify metadata consistency

Gas Optimization​

Estimate gas usage:

  1. Use "Dry Run" option before actual execution
  2. Monitor gas consumption in successful transactions
  3. Adjust limits based on actual usage

Gas usage patterns:

  • Constructor: Usually 50M-200M gas
  • Simple messages: 10M-50M gas
  • Complex operations: 100M+ gas

Contract Verification and Security​

Code Verification​

Verify deployed bytecode:

# Get deployed code
cargo contract info --contract-address CONTRACT_ADDRESS

# Compare with local build
diff <(xxd target/ink/flipper.wasm) <(xxd deployed.wasm)

Contract Upgrades​

Upgrading Contract Code​

ink! contracts are immutable, but you can implement upgrade patterns:

Option 1: Deploy new version

  1. Deploy updated contract code
  2. Migrate state manually
  3. Update frontend to use new address

Option 2: Proxy pattern

// Implement proxy contract that delegates to implementation
#[ink(storage)]
pub struct Proxy {
implementation: AccountId,
admin: AccountId,
}

#[ink(message)]
pub fn upgrade(&mut self, new_implementation: AccountId) -> Result<()> {
// Only admin can upgrade
// Update implementation address
}

Next Steps​

With your contract deployed on Mandala:

  1. Build your first EVM contract - Compare with Solidity development

Additional Resources:

Congratulations! You've successfully deployed your first ink! smart contract to Mandala Testnet. Your contract is now live and ready for interaction!