The home for all OpenZeppelin Canton docs, specs, and Reference
Implementations (RIs): the CIP-0112 / Token Standard V2 settlement specs, the
RI implementation code (the experimental settlement scaffold, a mock Token
Standard V2 interface layer mirroring the splice-api-token-*-v2 packages, a
deep settlement exemplar, and the compliance/identity experiments), the four RI
architecture reports, the audit-readiness package + threat model, scope locks,
research, and review provenance.
Repo split. The decoupled, ergonomic general Daml contracts library (
oz-access-control/oz-ownable/oz-pausable) is owned byOpenZeppelin/canton-contracts. That repo is the source of truth for the reusable primitives and contains no RI/specs code. This repo holds the RI implementation that consumes the library and builds against a vendored snapshot of those primitives (evolve the primitives incanton-contracts, then refresh the snapshot here). The RI architecture reports indocs/ri-reports/are living documents that link directly into the RI code (refresh withscripts/refresh-ri-anchors.sh). Originally seeded from thecanton-contractsCIP-0112 settlement work branch.
Status: experimental. The M1 target is the CIP-0112 settlement primitive (not the superseded CIP-56 token foundation), alongside the reusable access-control primitives (see Access Control Library below). No stable M1 public API, CIP-0112 conformance, audit readiness, production readiness, or release readiness is claimed.
M1 target scope:
- CIP-0112 / Token Standard V2 interface-aligned settlement primitive.
- CIP-86 compatibility surface scoped to interoperate with the settlement work.
- CIP-103 dApp and wallet-provider support components scoped to the settlement surface.
- CIP-104 rewards support components scoped to the settlement surface.
- Documentation, tests, security notes, and compatibility evidence.
Repository-local report surfaces:
docs/architecture/holds the CIP-0112 / Token Standard V2 architecture, promotion-boundary, import-gate, DPM, license, and source-of- record notes. The adopted D1–D4 design decisions are recorded indocs/architecture/cip0112-m1-ri-spec.md.docs/ri-reports/holds the portfolio report and all four RI architecture reports.
CIP-86 / CIP-103 / CIP-104 are addressed as settlement-interop criteria, not
standalone CIP-56-token deliverables. CIP-56 is background and migration evidence
only. The experimental CIP-112
settlement scaffold lives under experiments/cip112-settlement and remains
outside the committed public-library surface until the promotion boundary ADR's
Splice DAR/import, license/NOTICE, package-ID/checksum, DPM wiring, and public
API gates land:
docs/architecture/cip0112-public-api-promotion-boundary.mddocs/architecture/cip0112-m1-ri-spec.mddocs/experiments/cip112-settlement.md
Out of scope for this repo:
- DEX, lending, payments, or auction business logic.
- Production private integrations.
- Production KYC, sanctions, custody, validator, bridge, or relayer services.
- Full off-chain relayer infrastructure.
- Year 2 components before approval.
The M0 proof baseline accepts Daml SDK / Canton 3.4.11 through DPM only for the hello-world compile/deploy proof. M1 public API and Splice DAR import pins remain open until the CIP-112 promotion boundary gates are accepted.
For the M0 proof baseline:
- Install or expose DPM.
- Run
dpm install 3.4.11. - Run the accepted build command:
OZ_DAML_TOOLCHAIN=dpm dpm buildThe production package is the repo root DPM package. It intentionally has no
daml-script dependency. Disposable script/test code lives in the separate
proof/ DPM package, which depends on the production DAR and owns
daml-script.
Current M0 production DAR:
- Path:
.daml/dist/oz-canton-specs-0.0.0.dar - SHA-256:
ae5419a2b4a6748af3f4ec77736b46d3b9ca40c82f7df8aa1229dff5f71f48d8 - Main package ID:
c14e2d83f3454f4c70fe9ef4c78818afce121129e195573914d0fa2d32a93ea0
Current M0 proof DAR:
- Path:
proof/.daml/dist/oz-canton-specs-hello-world-proof-0.0.0.dar - SHA-256:
b76122f152fcd8df4a87c4a5de3cf989af3a5402b406ee89cd8638558a7bcaf2 - Main package ID:
81ccf8122e709a188c0ec2d9759b8f0c9c8601d483967be8114fca9492c8cf84
The root and scaffold scripts use OZ_DAML_TOOLCHAIN=auto by default. Auto
selection requires DPM and does not fall back to Daml Assistant. The scripts
make ~/.dpm/bin/dpm visible for non-interactive shells when present and
default DPM/DAML cache writes to the repo-local ignored .cache/ directory.
The scaffold check uses scripts/dpm-env.sh inside this repo so standalone
manual validation does not depend on the coordinating workspace root. Set
OZ_DAML_TOOLCHAIN=dpm when manually validating the accepted M0 proof baseline.
Daml Assistant use requires a superseding ADR or explicit exception.
The repo-local scripts/dpm-env.sh is intentionally kept byte-for-byte in sync
with the coordinating root helper until an accepted vendoring step replaces the
duplication. Root ./scripts/check-all.sh fails if the two helper copies drift.
Manual validation machines should install or expose DPM and Java 21 before
running scripts/manual-workflow-test.sh or scripts/check-scaffold.sh.
From the workspace root, run:
./scripts/check-all.sh
./scripts/test-all.sh
./scripts/manual-workflow-tests.shBecause daml.yaml is committed, missing DPM tooling is a hard failure. Daml
Assistant is not an accepted M0 proof path.
The M0 LocalNet proof uses the root Canton sandbox config and Daml Script over
the Ledger API gRPC endpoint from the separate proof/ package. DAR upload
uses dpm script --upload-dar true; the sandbox participant vets the uploaded
packages for this single-participant proof. Party allocation uses
allocatePartyByHint inside HelloWorld.Proof:helloWorldProof.
From the workspace root:
./scripts/localnet-up.sh
./scripts/localnet-hello-world-proof.sh
./scripts/localnet-down.shlocalnet-up.sh requires tmux, starts Canton in a detached session, and waits
for the Ledger API port to be reachable before returning. The proof script
performs the same DPM bootstrap as the build/test scripts, so the default
up/proof/down sequence works in non-interactive validation shells when DPM is
installed on PATH or at ~/.dpm/bin/dpm.
daml/HelloWorld/HelloWorld.daml is a minimal Daml source file for the M0
compile proof. It records its signatory, observer, controller, privacy, archive,
failure, and migration assumptions in the source comments.
proof/daml/HelloWorld/Proof.daml is a disposable M0 LocalNet proof script. It
is not public API and keeps the Daml Script dependency out of the production
package.
The first reusable primitives land here as three independent packages, each
its own DAR with no dependency on the others — so a consumer imports only what it
needs (e.g. just oz-pausable). This is the Daml-idiomatic form of OpenZeppelin's
decoupled-module promise: independence is at the package boundary, since Daml
has no inheritance and the unit of reuse is the DAR. The full rationale, the
options weighed, and the Daml-specific genericity trade are documented in the
canton-token-template docs/ARCHITECTURE.md.
| Package | Module | Mirrors | Notes |
|---|---|---|---|
oz-access-control |
OpenZeppelin.AccessControl |
AccessControl.sol |
RoleGrant / RoleAdmin + pure requireRole / hasRole. Roles are Text ids (the bytes32 analogue) because Daml templates are monomorphic; a consumer layers a closed role sum on top via a roleId : MyRole -> Text wrapper. |
oz-ownable |
OpenZeppelin.Ownable |
Ownable2Step.sol |
Ownership + OwnershipOffer. Transfer is a two-step handshake by necessity — a new owner is a signatory and cannot be bound unilaterally. |
oz-pausable |
OpenZeppelin.Pausable |
Pausable.sol |
PauseState + whenNotPaused guard. Pause is origination control on a keyless ledger. |
Each library package is daml-script-free. Tests and the example-consumer
templates that demonstrate the usage pattern (RoleCheck, PauseCheck, the
typed-wrapper bridge) live in the separate test/ package, which data-depends on
all three DARs.
Build and test the whole workspace in dependency order:
dpm build --all # builds all packages, including the three libraries
cd test && dpm test # runs the shared test package, including experimentsLatest local run (2026-06-21, SDK 3.4.11 / Java 21): dpm build --all builds all
packages and dpm test passes 60/60 scripts (14 AccessControl, 20
Cip112Settlement, 6 Ownable, 4 Pausable, 2 ComplianceShapeA, 6 ComplianceShapeB,
1 IdentityHookShapeA, 6 IdentityHookShapeB, 1 IdentityHookUpgrade).
Or build a single library standalone (proving its independence):
cd pausable && dpm buildStatus: 0.1.0, unstable — these are not yet public API (no stability ADR),
so DAR SHAs are intentionally not pinned here while the shape may still change.
The experimental settlement package models a Token Standard V2-aligned
request/instruction/allocation/settlement lifecycle with optional D1 and D2
extension points. It is designed against the hyperledger-labs/splice
token-standard-v2-upcoming interfaces; the DAR import remains gated.
The package intentionally uses local stand-ins and toy holdings. Do not import or vendor Splice DARs from this repo until a later slice satisfies the promotion boundary ADR's published-DAR or reproducible-build evidence, package ID/checksum, Apache-2.0 license/NOTICE, and DPM dependency requirements.
MIT. See LICENSE.