Anatomy of a Contract
The contract! Macro
Thecontract! macro generates the necessary boilerplate for your contract:
- Generates wit-bindgen glue code
- Creates the
Guesttrait you implement - Sets up WASM component exports
- The name must match your WIT package
- Must appear after
use stdlib::*; - Name must match the contract name in your WIT file
Context Types
Every function in a Sigil contract receives a context as its first parameter. There are three context types:ViewContext - Read-Only Queries
ctx.storage()- Access low-level storagectx.model()- Get generated storage model (read-only)
ProcContext - State-Modifying Transactions
ctx.signer()- Transaction signerctx.contract_signer()- Contract’s own address (for receiving tokens)ctx.storage()- Access storagectx.model()- Get generated storage model (read-write)ctx.generate_id()- Generate unique IDsctx.view_context()- Get read-only view
FallContext - Fallback Handler
ctx.signer()- ReturnsOption<Signer>(may be None for view calls)ctx.proc_context()- ReturnsOption<ProcContext>(Some if called with signer)ctx.view_context()- Always available
WIT Files
WIT (WebAssembly Interface Type) files define your contract’s public interface.Relationship to Rust Code
- WIT files are hand-written by you
- They define the public API of your contract
- Every exported function in WIT must be implemented in Rust
- The
contract!macro generates Rust types from your WIT
Example WIT File
Built-in WIT Interfaces
Thekontor:built-in package provides:
context- Storage and execution context (ViewContext, ProcContext, FallContext)numbers- Arbitrary precision Integer and Decimal typeserror- Error type with variants (Message, Overflow, DivByZero, SyntaxError)crypto- Hash functionsforeign- Cross-contract calls
core/indexer/src/runtime/wit/deps/built-in.wit for complete reference.
Module Organization
Workspace Structure
Contracts are organized in a Cargo workspace:One Contract Per Crate
Each contract is a separate Rust crate with:Cargo.toml- Dependencies and build configsrc/lib.rs- Contract implementationwit/contract.wit- Interface definitionwit/deps/- Symlink to built-in types
Build Configuration
Cargo.toml:Hooks
Sigil defines specific function names that serve as hooks:init Hook
- Contract is first deployed (publish transaction)
- Automatically by the runtime
- Setting initial storage values
- Contract initialization logic
- Data migrations for upgrades
fallback Hook
- A function is called that doesn’t exist
- Primarily for proxy contracts
- Implementing proxy patterns
- Version upgrades
- Generic delegation
Quick Reference
Context Types
ProcContext- Enables state-modifying operations, such as balance transfers
- Provides write access to storage and signer access via
ctx.signer() - Used in functions like
mintortransferto update blockchain state
- Supports read-only queries for inspecting contract state
- Restricts access to read-only storage operations, no signer or mutations allowed
- Used in functions like
balancefor retrieving data without modifying the blockchain
- Manages unmatched calls via the
fallbackhook, enabling proxy patterns - Converts to
ViewContextorOption<ProcContext>for storage reads - Exclusive to the
fallbackfunction for dynamic routing
Context Traits (for helper functions)
WriteContext- For mutation logic (e.g., internal updates)
- Implemented only by
ProcContext
- For read-only logic (e.g., internal queries)
- Implemented by both
ViewContextandProcContext, enabling shared read operations
Storage
StorageRoot- Marks the root struct or enum for contract storage
- Key-value store for collections (e.g., account balances)
- Supports
get,set, andkeysmethods
ctx.model()- Returns the typed storage model- Field accessors (e.g.,
ctx.model().ledger()) - Provide structured access - Get/set methods - No ctx parameter needed (e.g.,
ledger.get(&key),ledger.set(key, value))
Signer Access
ctx.signer()- Retrieves the transaction signer (ProcContext only)ctx.contract_signer()- Returns the contract’s own address (for receiving tokens)
Cross-Contract Calls
Static imports:Utilities
crypto::generate_id() -> String- Generates unique IDs for entities (e.g., account IDs)
- Applies sha256 hash and returns hex encoded string and raw bytes
- Applies sha256 hash to string concatenated with salt
Error Type
Macros
contract!(name = “name”)- Defines contract name and generates boilerplate code from WIT file
- Statically imports another contract’s WIT for cross-contract calls
- Defines dynamic interface for runtime contract calls with dynamic addresses