A Cargo subcommand and toolchain for building Rust smart contracts targeting PolkaVM (used by Polkadot's pallet-revive).
It scaffolds Rust contract projects, provides proc macros and a builder DSL for dispatch/ABI encoding, and compiles to .polkavm bytecode. A Solidity .sol interface file can optionally be provided to auto-generate method stubs and selectors, but is not required -- the macro can infer ABI information directly from Rust function signatures.
- Project scaffolding -- generate a complete Rust contract project from scratch, or from a
.solinterface to get typed method stubs with selectors and ABI encoding wired up automatically - Two API styles -- choose between proc macros (
#[contract],#[method]) for concise code or a builder-pattern DSL (ContractBuilder::new().method(...)) for explicit control - ABI generation -- the build system compiles your contract on the host to extract type information, then emits a
.abi.jsonalongside the.polkavmbinary - Lightweight ABI encoding --
pvm-contract-typesprovidesno_std-compatibleSolEncode/SolDecodetraits as an alternative toalloy-core, keeping binary sizes small - Allocator options -- contracts can run in stack-only mode (no allocator), or with a bump allocator (
pvm-bump-allocator) orpicoallocfor dynamic types likeStringandVec<T>
cargo install cargo-pvm-contractRequires Rust nightly with rust-src for contract compilation (the scaffolded project handles this via rust-toolchain.toml):
rustup toolchain install nightly --component rust-src --profile minimalOptionally install solc 0.8.26+ if you want to scaffold from .sol files:
# macOS
brew install solidity
# Linux
SOLC_VERSION=0.8.26
curl -L https://github.com/ethereum/solidity/releases/download/v${SOLC_VERSION}/solc-static-linux -o solc
chmod +x solc && sudo mv solc /usr/local/bin/solccargo pvm-contractThis launches an interactive prompt that walks you through:
- Init type -- start from scratch or from a bundled example (Fibonacci, MyToken, Multi)
- API style -- Macro (proc-macro attributes) or DSL (builder pattern)
- Allocator -- Bump allocator (for dynamic types) or no allocator (stack-only, smaller binary)
- Solidity interface -- optionally point to a
.solfile to auto-generate method stubs
The generated project builds with a plain cargo build. The PolkaVM bytecode and ABI JSON are written to:
target/<binary-name>.<profile>.polkavm
target/<binary-name>.<profile>.abi.json
Annotate a module with #[contract] and mark functions with #[method], #[constructor], or #[fallback]. The macro generates the PolkaVM entry points, calldata dispatch, and ABI encoding:
#[pvm_contract_macros::contract("MyToken.sol", allocator = "bump")]
mod my_token {
#[pvm_contract_macros::constructor]
pub fn new() -> Result<(), Error> { Ok(()) }
#[pvm_contract_macros::method]
pub fn total_supply() -> U256 { U256::ZERO }
#[pvm_contract_macros::method]
pub fn transfer(to: Address, amount: U256) -> bool { todo!() }
}Wire up dispatch explicitly using ContractBuilder. No proc macros needed -- all logic is visible in your source:
use pvm_contract_builder_dsl::{ContractBuilder, solidity_selector};
const TOTAL_SUPPLY: [u8; 4] = solidity_selector("totalSupply()");
const TRANSFER: [u8; 4] = solidity_selector("transfer(address,uint256)");
pub extern "C" fn call() {
ContractBuilder::new()
.method(TOTAL_SUPPLY, total_supply_handler)
.method(TRANSFER, transfer_handler)
.dispatch::<HostFnImpl, 256>()
}| Crate | Description |
|---|---|
cargo-pvm-contract |
CLI -- scaffolds contract projects from .sol files |
cargo-pvm-contract-builder |
Build helper -- build.rs integration that links PolkaVM bytecode and generates ABI JSON |
pvm-contract-macros |
Proc macros -- #[contract], #[method], #[constructor], #[fallback], #[derive(SolType)] |
pvm-contract-types |
ABI encoding/decoding traits (SolEncode, SolDecode) -- no_std compatible |
pvm-contract-builder-dsl |
Builder-pattern DSL for contracts without proc macros |
pvm-bump-allocator |
Simple bump allocator for short-lived contract executions |
pvm-contract-benchmarks |
Binary size comparison tool for CI regression detection |
The examples/example-mytoken project contains several MyToken variants as separate binaries:
| Binary | Style | Allocator |
|---|---|---|
example-mytoken-macro-pico-alloc |
Proc macro | picoalloc |
example-mytoken-macro-bump-alloc |
Proc macro | pvm-bump-allocator |
example-mytoken-macro-no-alloc |
Proc macro | None (stack-only) |
example-mytoken-macro-no-sol |
Proc macro | None (no .sol file) |
example-mytoken-dsl-no-alloc |
Builder DSL | None (stack-only) |
example-mytoken-alloy-alloc |
alloy-core | pvm-bump-allocator |
Build all variants:
cd examples/example-mytoken
env -u CARGO -u RUSTUP_TOOLCHAIN cargo build --releaseMIT