CosmWasm Contract Structure
SkillDev toolsAxone contract structure and Abstract SDK patterns. Use when scaffolding or refactoring contracts, deciding layer boundaries, wiring AppContract entrypoints, or adding module metadata and replies.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the CosmWasm Contract Structure skill
What this skill tells your AI
The instructions your AI receives, as published by axone-protocol/contracts in .agents/skills/cosmwasm-contract/SKILL.md and read by ahel’s review.
Companion Skills
Use rust-contract-domain-modeling for invariant-heavy domain design, api-design for message surfaces, api-doc-comments for schema-facing documentation, rust-testing for tests, and rust-quality-gates for validation gates.
Repository Structure
The repository has:
- a workspace-level
Makefile.tomlfor shared tasks - a contract-level
Makefile.tomlin each contract for local helpers - one directory per contract under
contracts/
Minimal Contract Skeleton
Start from this minimal shape:
contracts/<contract-name>/
├── Cargo.toml
├── Makefile.toml
├── README.md
├── metadata.json
├── src/
│ ├── lib.rs
│ ├── contract.rs
│ ├── msg.rs
│ ├── state.rs
│ ├── error.rs
│ ├── handlers/
│ │ ├── mod.rs
│ │ ├── instantiate.rs
│ │ ├── execute.rs
│ │ ├── query.rs
│ │ └── migrate.rs
│ └── bin/
│ ├── schema.rs
│ ├── publish.rs
│ └── install.rs
└── tests/
└── integration.rs
Add extra layers only when they clarify boundaries.
Optional Layers Already Used In This Repo
Current repository layers include:
domain/for explicit business concepts and invariantsservices/for orchestration and environment-aware compositiongateway/for external module interaction and protocol I/Oqueries/for query string / payload buildersreplies/for reply handlers
axone-gov is the reference example for the richer layered shape.
Layer Boundaries
msg.rsdefines the public contract surface.contract.rswires theAppContractentrypoints and module metadata.handlers/should stay thin: decode messages, call domain/services, build responses.domain/should own invariants and canonical representations.services/should coordinate enriched flows or external calls without becoming a second handler layer.gateway/should isolate external query / module plumbing.state.rsshould persist and reconstruct values, not silently redefine business rules.
lib.rs Pattern
Keep module identity constants explicit:
pub const AXONE_NAMESPACE: &str = "axone";
pub const CONTRACT_NAME: &str = "my-contract";
pub const CONTRACT_ID: &str = const_format::concatcp!(AXONE_NAMESPACE, ":", CONTRACT_NAME);
pub const APP_VERSION: &str = env!("CARGO_PKG_VERSION");
contract.rs Pattern
The baseline AppContract wiring looks like this:
use abstract_app::AppContract;
pub type MyContract = AppContract<
MyContractError,
MyContractInstantiateMsg,
MyContractExecuteMsg,
MyContractQueryMsg,
MyContractMigrateMsg,
>;
const APP: MyContract = MyContract::new(CONTRACT_ID, APP_VERSION, None)
.with_instantiate(handlers::instantiate_handler)
.with_execute(handlers::execute_handler)
.with_query(handlers::query_handler)
.with_migrate(handlers::migrate_handler)
.with_dependencies(&[]);
#[cfg(feature = "export")]
abstract_app::export_endpoints!(APP, MyContract);
abstract_app::cw_orch_interface!(APP, MyContract, MyContractInterface);
Repository-specific refinements:
- Use
Some(APP_METADATA_URL)when the contract publishes metadata from a tagged GitHub URL. - Add
.with_replies(...)when the contract has reply-driven flows. - Keep
.with_dependencies(&[])explicit unless real module dependencies exist. - Add the non-wasm
DependencyCreationimpl when the interface needs the standard installation path used in this repo.
Message Wiring
Use abstract_app::app_msg_types!(...) in msg.rs when following the repository's Abstract app pattern.
Keep message docs and response typing aligned with:
api-designapi-doc-comments
Error Design
Error enums should include the standard conversion layers used by the contract and then domain-specific errors.
Do not hide domain invariants in generic StdError messages if a dedicated error variant would make the failure explicit.
Replies and Metadata
Two patterns matter in this repository:
metadata.jsonis part of the contract deliverable and should stay aligned with the module identity.- reply handlers are normal when contract setup involves follow-up callbacks or submessage completion.
Treat both as first-class contract structure, not optional afterthoughts.
Construction Rules
- Put invariant checks close to domain object creation.
- Keep handler branches short; move validation-heavy logic out of handlers.
- Prefer explicit constructors such as
new,try_new, orfrom_state. - Reuse canonical domain types rather than passing partially validated strings across layers.
Signals
- GitHub stars
- 123
- Forks
- 19
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
cosmwasm-contract- Source
- github.com/axone-protocol/contracts