Smart Contract Deployment to Cosmos (CosmWasm)

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
Smart Contract Deployment to Cosmos (CosmWasm)
Medium
from 4 hours to 2 business days
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1215
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1043
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    823

Deploying Smart Contracts in Cosmos (CosmWasm)

CosmWasm is not EVM. If you come from a Solidity background, the first thing that's confusing: contracts are written in Rust, compiled to WebAssembly, and interact through message-passing rather than direct function calls. The architectural model is closer to actor model than to object method calls. This is important to understand before writing the first line of code.

Development Environment and Toolchain

To work with CosmWasm, you need Rust with the wasm32-unknown-unknown target:

rustup target add wasm32-unknown-unknown
cargo install cosmwasm-check   # validation of compiled wasm
cargo install cargo-generate   # project templates

Standard project template via cw-template:

cargo generate --git https://github.com/CosmWasm/cw-template.git --name my-contract

CosmWasm Contract Structure

A contract consists of three mandatory entry points:

// src/contract.rs
#[cfg_attr(not(feature = "library"), entry_point)]
pub fn instantiate(
    deps: DepsMut,
    env: Env,
    info: MessageInfo,
    msg: InstantiateMsg,
) -> Result<Response, ContractError> { ... }

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn execute(
    deps: DepsMut,
    env: Env,
    info: MessageInfo,
    msg: ExecuteMsg,
) -> Result<Response, ContractError> { ... }

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn query(
    deps: Deps,
    env: Env,
    msg: QueryMsg,
) -> StdResult<Binary> { ... }

The key difference from Solidity: DepsMut (for writing) and Deps (read-only) are explicitly separated. It's physically impossible to accidentally write to storage from a query function — the compiler won't allow it.

State management via cw-storage-plus:

use cw_storage_plus::{Item, Map};

pub const CONFIG: Item<Config> = Item::new("config");
pub const BALANCES: Map<&Addr, Uint128> = Map::new("balances");

Map with an address as key is the standard pattern for storing balances. There's no mapping(address => uint256) from Solidity, but the semantics are the same.

Compilation and Optimization

Raw cargo build --target wasm32-unknown-unknown --release produces a binary with debug symbols and unoptimized size. For production, we use the official optimizer:

docker run --rm -v "$(pwd)":/code \
  --mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \
  --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \
  cosmwasm/rust-optimizer:0.15.0

Result is artifacts/my_contract.wasm. Size should be < 800KB (hard limit for most networks). Verification:

cosmwasm-check artifacts/my_contract.wasm

Deployment to Cosmos-Compatible Network

I'll show using Neutron (one of the main CosmWasm networks for DeFi). Using neutrond CLI or CosmJS:

Via CLI:

# Store — upload bytecode to the network
neutrond tx wasm store artifacts/my_contract.wasm \
  --from <wallet> \
  --gas auto --gas-adjustment 1.3 \
  --fees 5000untrn \
  --chain-id neutron-1 \
  --node https://rpc-lb.neutron.org:443

# Get code_id from transaction events
# Instantiate — create contract instance
neutrond tx wasm instantiate <CODE_ID> \
  '{"admin": "neutron1...", "param": "value"}' \
  --label "my-contract-v1" \
  --admin <wallet_address> \
  --from <wallet> \
  --gas auto --gas-adjustment 1.3 \
  --fees 5000untrn \
  --chain-id neutron-1

Via CosmJS (for automation):

import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate";
import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing";

const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, {
  prefix: "neutron",
});
const client = await SigningCosmWasmClient.connectWithSigner(
  "https://rpc-lb.neutron.org:443",
  wallet
);

// Upload
const uploadResult = await client.upload(senderAddress, wasmBinary, "auto");
const codeId = uploadResult.codeId;

// Instantiate
const { contractAddress } = await client.instantiate(
  senderAddress,
  codeId,
  { admin: senderAddress },
  "my-contract-v1",
  "auto"
);

Migratable Contracts

CosmWasm has a built-in migration mechanism — similar to upgradeable proxies in EVM, but simpler. You need to add an entry point:

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn migrate(
    deps: DepsMut,
    env: Env,
    msg: MigrateMsg,
) -> Result<Response, ContractError> {
    // Migration logic for state if needed
    Ok(Response::default())
}

When deploying an instance with an --admin address, that address can call MigrateContract with a new code_id. Without --admin — the contract is immutable. For production protocols, the admin should be a multisig (via cosmwasm-multisig or DAO DAO).

Time Estimates

A contract with ready logic, written by an experienced Rust developer: deployment and verification 4–8 hours. If development is needed from scratch or porting from Solidity — 1–2 days depending on complexity.