QoreChain Native Development
QoreChain supports QoreChain Native smart contracts. QoreChain Native is QoreChain's name for its CosmWasm runtime: developers write secure, sandboxed programs in Rust against the standard CosmWasm libraries (cosmwasm-std) and compile them to WebAssembly. QoreChain Native contracts run alongside EVM and SVM programs within the QoreChain triple-VM architecture.
The commands below use the qorechain-vladi mainnet (live since 7 June 2026), which runs node release v3.2.6 since 4 November 2026 (governance proposal 15, height 4,020,000; v3.2.5 since 29 October 2026, v3.2.4 since 23 October 2026). Substitute --chain-id qorechain-diana for the testnet, which runs v3.2.7 (since 6 November 2026; v3.2.4 since 19 October 2026).
As of this writing (checked 27 October 2026), code_upload_access and instantiate_default_permission are both set to Nobody on mainnet, meaning MsgStoreCode and MsgInstantiateContract are not open to arbitrary accounts, following an industry-wide security advisory for CosmWasm, the runtime that QoreChain Native is built on. On the qorechain-diana testnet the settings differ: code_upload_access is still Nobody (code is stored only through governance), but instantiate_default_permission is Everybody, set by testnet governance on 27 October 2026, so any account can instantiate a stored code whose own permission allows it. Check the live parameters first, since this is exactly the kind of setting governance can change (mainnet currently has no stored contract code at all):
qorechaind query wasm params
# or: curl -s https://api.qore.host/cosmwasm/wasm/v1/codes/params (substitute api-testnet.qore.host for testnet)
The chain's circuit breaker also switches message types off network-wide (qorechaind query circuit disabled-list). On mainnet MsgStoreCode, MsgInstantiateContract and MsgInstantiateContract2 are on the list, so raising the permission alone is not enough until those entries are lifted. On the testnet only MsgStoreCode is on the list: instantiation is open, upload is not.
Testnet: reviewed contracts stored by governance. Because ordinary accounts cannot upload code on the testnet, governance stored five reviewed contracts that anyone can instantiate (instantiate_permission Everybody): cw20-base (token), cw721-base (NFT collection), cw4-group, cw3-fixed-multisig and a small counter contract. At the time of writing they are code ids 859 to 863, in that order, listed by GET /cosmwasm/wasm/v1/code with the governance module account as creator and identified by their data_hash; read the ids from the live list rather than hardcoding them. They exist on the testnet only. Mainnet has no stored code.
This restriction doesn't affect already-instantiated contracts — execute and query against an existing contract work normally regardless of this setting.
tx pqc cosignMainnet and testnet require a hybrid post-quantum signature on every Cosmos-lane transaction, so the tx commands on this page do not broadcast as written. They build the transaction with --generate-only > tx.json; then sign and broadcast it with qorechaind tx pqc cosign tx.json --from mykey --pqc-key mypqc --chain-id <chain-id> (the release binary from the download manifest has the signer; a build from the public source does not). The network fee floor is 0.1 uqor per unit of gas, which is what --gas-prices 0.1uqor expresses; the hybrid signature adds roughly 47,000 gas that a simulation does not include, hence the 1.5 adjustment. (From v3.2.7, on the testnet since 6 November 2026, the post-quantum verification charge is a flat 2,000 gas; mainnet is still on v3.2.6.) See Post-Quantum Signing.
Prerequisites
| Dependency | Version | Purpose |
|---|---|---|
| Rust | Latest stable | Contract compilation |
| wasm32-unknown-unknown | target | WebAssembly compilation target |
| cargo-generate | Latest | Project scaffolding |
| cosmwasm-std | 1.5+ | CosmWasm standard library |
Install the Wasm target:
rustup target add wasm32-unknown-unknown
Contract Lifecycle
QoreChain Native contracts follow a five-step lifecycle: Build, Store, Instantiate, Execute, and Query.
-
Build — Compile your contract to optimized WebAssembly:
cd my-contract# Standard buildcargo build --release --target wasm32-unknown-unknown# Optimized build (recommended for deployment)docker run --rm -v "$(pwd)":/code \cosmwasm/rust-optimizer:0.15.0The optimized
.wasmfile will be in theartifacts/directory. -
Store — Upload the compiled contract to the chain:
qorechaind tx wasm store contract.wasm \--from mykey \--gas auto --gas-adjustment 1.5 --gas-prices 0.1uqor \--generate-only > tx.jsonAfter the transaction confirms (sign and broadcast
tx.jsonwithtx pqc cosignas described above), query the stored code ID:qorechaind query wasm list-code -
Instantiate — Create a new contract instance from a stored code ID:
qorechaind tx wasm instantiate <code-id> \'{"count": 0, "owner": "qor1..."}' \--label "my-counter-contract" \--from mykey \--no-admin \--gas auto --gas-adjustment 1.5 --gas-prices 0.1uqor \--generate-only > tx.jsonFlag Description <code-id>Numeric ID returned from the store transaction --labelHuman-readable label for this instance --no-adminNo admin address (contract is immutable) --admin <address>Set an admin who can migrate the contract Retrieve the contract address:
qorechaind query wasm list-contract-by-code <code-id> -
Execute — Call a contract's execute entry point to change state:
qorechaind tx wasm execute <contract-addr> \'{"increment": {}}' \--from mykey \--gas auto --gas-adjustment 1.5 --gas-prices 0.1uqor \--generate-only > tx.jsonExecute with funds attached:
qorechaind tx wasm execute <contract-addr> \'{"deposit": {}}' \--amount 1000000uqor \--from mykey \--gas auto --gas-adjustment 1.5 --gas-prices 0.1uqor \--generate-only > tx.json -
Query — Read contract state without submitting a transaction:
qorechaind query wasm contract-state smart <contract-addr> \'{"get_count": {}}'Query responses are returned as JSON.
Useful Queries
# List all stored code
qorechaind query wasm list-code
# List all instances of a specific code ID
qorechaind query wasm list-contract-by-code <code-id>
# Get contract info (code ID, admin, label)
qorechaind query wasm contract <contract-addr>
# Get raw contract state by key
qorechaind query wasm contract-state raw <contract-addr> <key-hex>
# Get full contract state (all keys)
qorechaind query wasm contract-state all <contract-addr>
# Get contract history (instantiate/migrate events)
qorechaind query wasm contract-history <contract-addr>
Contract Structure
A typical QoreChain Native contract has three entry points:
use cosmwasm_std::{
entry_point, Binary, Deps, DepsMut, Env, MessageInfo,
Response, StdResult,
};
#[entry_point]
pub fn instantiate(
deps: DepsMut,
_env: Env,
info: MessageInfo,
msg: InstantiateMsg,
) -> StdResult<Response> {
// Initialize contract state
Ok(Response::new().add_attribute("method", "instantiate"))
}
#[entry_point]
pub fn execute(
deps: DepsMut,
env: Env,
info: MessageInfo,
msg: ExecuteMsg,
) -> StdResult<Response> {
// Handle state-changing operations
Ok(Response::new().add_attribute("method", "execute"))
}
#[entry_point]
pub fn query(
deps: Deps,
_env: Env,
msg: QueryMsg,
) -> StdResult<Binary> {
// Handle read-only queries
Ok(Binary::default())
}
Cross-VM Calls
Cross-VM calls are sent as MsgCrossVMCall transactions through the x/crossvm module; see Cross-VM Interoperability for the message lifecycle. QoreChain Native contracts do not have a dedicated contract-side binding for initiating a cross-VM call (there is no custom QoreChainMsg message for contracts to emit), so a contract cannot call an EVM or SVM contract from inside its execute entry point. Since v3.2.3 a call into the caller's own lane is refused and a queued call that fails leaves no side effects behind.
MsgCrossVMCall is on mainnet's circuit-breaker list (qorechaind query circuit disabled-list), and the SVM lane is disabled on both networks, so the cross-VM path is not usable for ordinary transactions today.
Module Integration
QoreChain Native contracts can interact with Cosmos SDK modules through standard message passing:
// Send native tokens via the bank module
let send_msg = BankMsg::Send {
to_address: "qor1recipient...".to_string(),
amount: vec![Coin {
denom: "uqor".to_string(),
amount: Uint128::new(1_000_000),
}],
};
// Delegate to a validator via the staking module
let delegate_msg = StakingMsg::Delegate {
validator: "qorvaloper1...".to_string(),
amount: Coin {
denom: "uqor".to_string(),
amount: Uint128::new(1_000_000),
},
};
Contract Migration
If the contract was instantiated with an --admin address, the admin can migrate it to a new code ID:
qorechaind tx wasm migrate <contract-addr> <new-code-id> \
'{"migrate_msg": {}}' \
--from admin-key \
--gas auto --gas-adjustment 1.5 --gas-prices 0.1uqor \
--generate-only > tx.json
This calls the migrate entry point on the new code with the existing contract state.
Next Steps
- Cross-VM Interoperability — Call EVM and SVM contracts from QoreChain Native
- SVM Development — Deploy BPF programs on QoreChain
- EVM Precompiles — Reference for the Solidity precompiles (none is active on mainnet; three are active on the testnet)