CDM is the deploy, registry, and dependency tool for PVM smart contracts on Polkadot. It builds contracts in dependency order, deploys them to Asset Hub, publishes metadata to Bulletin, registers package names in the on-chain registry, and installs typed ABIs for downstream projects.
Browse published contracts at contracts.dot.li.
curl -fsSL https://raw.githubusercontent.com/paritytech/contract-dependency-manager/main/install.sh | bashThis installs the cdm binary, the Rust nightly toolchain with rust-src, and cargo-pvm-contract.
# Scaffold a new workspace
cdm template shared-counter
# Generate a deploy account and map it for pallet-revive
cdm init -n paseo
cdm account map -n paseo
# Build, deploy, publish metadata, and register all workspace contracts
cdm deploy -n paseoBefore deploying a template, change every #[pvm::contract(cdm = "@example/...")] namespace to one you own, such as @myteam/counter. Package names are global per registry target.
Use CDM for contract lifecycle and dependency resolution:
- Build PVM contracts.
- Deploy contracts to Asset Hub.
- Publish ABI/readme metadata to Bulletin.
- Register
@org/name -> address + metadatain the ContractRegistry. - Install published contracts into
cdm.json,.cdm/contracts.d.ts, and generated Solidity import files.
Use product-sdk in apps and frontends:
- Do not import
@dotdm/cdmin frontend/runtime app code. - Use
@parity/product-sdk-contractsandContractManagerto resolve contracts fromcdm.json. - Use
@parity/product-sdk-signerfor Product Account / Triangle host signing. - Use
@parity/product-sdk-chain-clientfor host chain connections. - Use
@parity/product-sdk-txwhen batching.prepare()calls with other Asset Hub transactions.
cdm install generates type augmentation for @parity/product-sdk-contracts, so ContractManager.getContract("@org/name") is typed after .cdm/contracts.d.ts is included by TypeScript. Solidity projects also get address-backed interfaces under .cdm/solidity/.
Annotate each contract with a CDM package name:
#[pvm::contract(cdm = "@yourorg/mycontract")]
mod mycontract {
#[pvm::constructor]
pub fn new() -> Result<(), Error> { Ok(()) }
#[pvm::method]
pub fn do_something() -> u32 { 42 }
}To call another CDM contract from Rust:
cdm::import!("@someorg/other-contract");
let other = other_contract::cdm_reference();
if let Err(_) = other.do_something() {
common::revert(b"OtherCallFailed");
}For external packages, run cdm i -n paseo @someorg/other-contract first. The import macro reads cdm.json, resolves the installed ABI in ~/.cdm, and generates the same typed reference shape as a same-workspace Cargo dependency.
Solidity contracts use NatSpec for their own CDM package name:
/// @custom:cdm @yourorg/mycontract
contract MyContract {}To call an installed CDM contract from Solidity, import the generated interface:
import ".cdm/solidity/someorg/other-contract.sol";
contract Caller {
function callOther() external returns (uint256) {
return SomeorgOtherContract.ref().doSomething();
}
}The generated file contains an interface plus a small library with ADDRESS, ref(), and cdm(). Running cdm i updates that generated file from the registry, so contract source does not need an address edit.
Install published contract ABIs:
cdm i -n paseo @yourorg/counter @yourorg/counter-writerThis updates cdm.json, stores ABIs under ~/.cdm, writes .cdm/contracts.d.ts, and generates Solidity imports under .cdm/solidity/. Keep .cdm/**/* in tsconfig.json so product-sdk contract handles are typed.
Install the product-sdk app/runtime packages:
pnpm add @parity/product-sdk-chain-client@^0.4.1 \
@parity/product-sdk-contracts@^0.5.0 \
@parity/product-sdk-descriptors@^0.4.0 \
@parity/product-sdk-signer@^0.2.4 \
@parity/product-sdk-tx@^0.2.3 \
polkadot-api@^2.1.2In frontend code, use product-sdk:
import { getChainAPI } from "@parity/product-sdk-chain-client";
import {
ContractManager,
ensureContractAccountMapped,
type CdmJson,
} from "@parity/product-sdk-contracts";
import { paseo_asset_hub } from "@parity/product-sdk-descriptors/paseo-asset-hub";
import { SignerManager } from "@parity/product-sdk-signer";
import cdmJson from "./cdm.json";
const DOT_NS_IDENTIFIER = "my-app.dot";
const signerManager = new SignerManager({ dappName: "my-app" });
await signerManager.connect();
const productAccount = await signerManager.getProductAccount(DOT_NS_IDENTIFIER);
if (!productAccount.ok) throw productAccount.error;
const chain = await getChainAPI("paseo");
const contracts = ContractManager.fromClient(
cdmJson as CdmJson,
chain.raw.assetHub,
paseo_asset_hub,
);
await ensureContractAccountMapped(
contracts.getRuntime(),
productAccount.value.address,
productAccount.value.getSigner(),
);
contracts.setDefaults({
origin: productAccount.value.address,
signer: productAccount.value.getSigner(),
});
const counter = contracts.getContract("@yourorg/counter");
const { value } = await counter.getCount.query();
await counter.increment.tx();Every contract method exposes:
.query(...args, opts?)for read-only dry-runs..tx(...args, opts?)for signed contract calls..prepare(...args, opts?)for batch-ready calls.
Batch contract calls with other Asset Hub transactions:
import { batchSubmitAndWatch } from "@parity/product-sdk-tx";
const a = counter.increment.prepare();
const counterWriter = contracts.getContract("@yourorg/counter-writer");
const b = counterWriter.writeIncrement.prepare();
await batchSubmitAndWatch([a, b], chain.raw.assetHub, productAccount.value.getSigner());The shared-counter template demonstrates a three-contract dependency graph:
counterstores a shared count value.counter-writercallscounter.increment()through a CDM reference.counter-readerqueriescounter.get_count()through a CDM reference.
cdm template shared-counter
cdm deploy -n paseo
cdm i -n paseo @yourorg/counter @yourorg/counter-writer @yourorg/counter-readerCDM includes first-pass Solidity scaffolds for the two supported Solidity toolchains:
cdm template hardhat-counter
cdm template foundry-counterhardhat-counter uses @parity/hardhat-polkadot and compiles with pnpm build.
foundry-counter uses the Polkadot Foundry fork and compiles with forge build --resolc.
These templates are compile-ready starter projects and can be built, deployed, published, registered, installed, and consumed through CDM.
Build all contracts with the selected ContractRegistry address baked in.
cdm build
cdm build --contracts counter counter_writer
cdm build -n preview-net
cdm build --root /path/to/workspaceBuild, deploy, publish metadata, and register all workspace contracts.
cdm deploy -n paseo
cdm deploy -n preview-net
cdm deploy -n paseo --suri //Bob
cdm deploy --registry-address 0x... --assethub-url wss://... --bulletin-url wss://...Supported deploy presets are paseo, preview-net, and local. The paseo preset points at Paseo v2.
Install published contracts for Rust imports, Solidity imports, and product-sdk TypeScript usage.
cdm i -n paseo @polkadot/contexts @polkadot/profiles
cdm i -n preview-net @yourorg/package
cdm i -n paseo @yourorg/package:3cdm install queries the registry, fetches metadata from the configured Bulletin IPFS gateway, updates cdm.json, installs ABIs under ~/.cdm, regenerates .cdm/contracts.d.ts, and writes Solidity interfaces under .cdm/solidity/.
Scaffold an example project into ./<template-name> by default. Pass a target directory to override it; use . to scaffold into the current directory.
cdm template shared-counter # writes ./shared-counter
cdm template instagram # writes ./instagram
cdm template hardhat-counter # writes ./hardhat-counter
cdm template foundry-counter # writes ./foundry-counter
cdm template instagram . # writes current directory
cdm template instagram ./apps/ig # creates ./apps/ig recursively
cd instagram && cdm template . # infers the instagram template from cwdThe Instagram template is the current browser app example. It uses product-sdk host flows, Product Account signing, Bulletin uploads, and ContractManager resolution from cdm.json.
git clone https://github.com/paritytech/contract-dependency-manager.git
cd contract-dependency-manager
make setup
# Run the CLI in dev mode
bun run src/apps/cli/src/cli.ts --help
# Run the frontend; rebuilds local workspace deps first
make frontend
# Run tests
make test
# Build native binary
make compile
# Cross-compile for all platforms
make compile-allsrc/
apps/
cli/ CLI tool (Commander.js, Bun runtime)
frontend/ Contract Hub web dashboard (React, Vite)
lib/
contracts/ @dotdm/contracts: detection, deploy, publish, registry, install helpers
env/ @dotdm/env: chain connections, signers, presets
utils/ @dotdm/utils: shared constants and utilities
scripts/ build/deploy helper scripts
cdm/ Rust macro + TypeScript compatibility package
contract/ ContractRegistry (Rust/PolkaVM)
templates/ Project scaffolding templates
Apache-2.0