Daml smart contracts for bridging ERC-20 tokens between Ethereum and Canton Network
This repository contains the Daml implementation of a token bridge connecting ERC-20 tokens on Ethereum with CIP-56 compliant tokens on Canton Network. The Go middleware implementation is maintained in the parent canton-middleware repository.
CANTON NETWORK
+---------------------------------------------------------------+
| |
| +-----------+ +------------+ +------------+ |
| | common |--->| cip56-token|--->| bridge-core| |
| | (types) | | (standard) | | (contracts)| |
| +-----------+ +------------+ +------+-----+ |
| | |
| v |
| +--------------+ |
| | wayfinder | |
| | (PROMPT) | |
| +--------------+ |
| |
+-----------------------------------------------------------------+
|
v
+-----------------------------------------------------------------+
| GO MIDDLEWARE |
| (Event Streaming + Command Submission) |
| canton-middleware repo |
+-----------------------------------------------------------------+
|
v
+-----------------------------------------------------------------+
| ETHEREUM |
| (ERC-20 + Bridge Contracts) |
| ethereum-wayfinder submodule |
+-----------------------------------------------------------------+
canton-erc20/
├── daml/ # Daml packages
│ ├── multi-package.yaml # Workspace configuration
│ │
│ │ # === Core Infrastructure ===
│ ├── common/ # Shared types and utilities
│ ├── cip56-token/ # CIP-56 token standard + unified TokenConfig + Events
│ ├── bridge-core/ # Core bridge contracts (MintCommand, WithdrawalRequest)
│ │
│ │ # === Bridge ===
│ ├── bridge-wayfinder/ # Wayfinder PROMPT token bridge
│ │
│ │ # === Test Packages (with daml-script) ===
│ ├── common-tests/ # Tests for common
│ ├── cip56-token-tests/ # Tests for CIP-56 token + TokenConfig
│ ├── bridge-core-tests/ # Tests for bridge-core
│ ├── bridge-wayfinder-tests/ # Tests for bridge-wayfinder
│ └── integration-tests/ # Cross-package integration
│
├── ethereum/ # EVM Bridge (Solidity)
│ ├── contracts/ # Solidity smart contracts
│ │ ├── CantonBridge.sol # Main bridge contract
│ │ └── TokenRegistry.sol # Token registration
│ ├── script/ # Foundry deployment scripts
│ ├── test/ # Solidity tests
│ └── web/ # Bridge web UI
│
├── docs/ # Documentation
│ ├── E2E-TESTNET-SETUP.md # End-to-end testing guide
│ └── DAML_ARCHITECTURE_PROPOSAL.md # Technical design document
├── CHANGELOG.md # Version history
└── README.md # This file
- Daml SDK 3.4.8 - Install Guide
- Go 1.21+ - For middleware (optional, for E2E testing)
- Foundry - For Solidity contracts (optional, for E2E testing)
daml version # Should show 3.4.8From the parent canton-middleware repository:
./scripts/setup/build-dars.shOr build individually from this directory:
cd daml/common && daml build --no-legacy-assistant-warning
cd ../cip56-token && daml build --no-legacy-assistant-warning
cd ../bridge-core && daml build --no-legacy-assistant-warning
cd ../bridge-wayfinder && daml build --no-legacy-assistant-warning# Run all DAML tests
./scripts/test-all.sh --verbose
# Or run individual test packages
cd daml/cip56-token-tests && daml test
cd daml/bridge-core-tests && daml test
cd daml/bridge-wayfinder-tests && daml testThese packages are deployed to Canton Network and do not include daml-script to avoid bloating the package store.
| Package | Description | Status |
|---|---|---|
common |
Shared types (TokenMeta, EvmAddress, ChainRef, FingerprintAuth) |
Stable |
cip56-token |
CIP-56 compliant token, unified TokenConfig, unified MintEvent/BurnEvent |
Stable |
bridge-core |
Issuer-centric bridge contracts (MintCommand, WithdrawalRequest, WithdrawalEvent) |
Stable |
bridge-wayfinder |
Wayfinder PROMPT token bridge (thin EVM layer delegating to TokenConfig) |
Production |
Test packages include daml-script and are not deployed to production ledgers.
| Package | Tests |
|---|---|
common-tests |
FingerprintAuthTest |
cip56-token-tests |
Mint, Transfer (with merge), Lock, Compliance flows |
bridge-core-tests |
Full bridge cycle, audit events, partial burns |
bridge-wayfinder-tests |
E2E Wayfinder flow, fingerprint validation, observer management |
integration-tests |
Cross-package integration |
common (no dependencies)
└── cip56-token
└── bridge-core
└── bridge-wayfinder
All tokens -- whether native Canton tokens or EVM-bridged -- share the same core logic:
TokenConfig (CIP56.Config)
├── IssuerMint --> CIP56Manager.Mint + MintEvent
└── IssuerBurn --> CIP56Manager.Burn + BurnEvent
TokenConfigholds aCIP56Managerreference and token metadata. Every mint produces aCIP56Holdingand aMintEvent; every burn produces aBurnEvent. Optional fields (evmTxHash,evmDestination) distinguish native operations from bridge operations.WayfinderBridgeConfigis a thin EVM layer. It holds atokenConfigCidreference and delegates all minting and burning toTokenConfig. The bridge itself only handles EVM-specific concerns: fingerprint registration, deposit validation, and withdrawal initiation.
To add a new bridged token (e.g. USDC), create:
- A new
TokenConfiginstance with its ownCIP56Managerand metadata - A new bridge config module that holds a reference to that
TokenConfig
The core mint/burn/event logic is identical for every token. The bridge is just an optional EVM entry point.
# CIP-56 Token tests (mint, transfer with merge, compliance)
cd daml/cip56-token-tests && daml test
# Bridge Core tests (full bridge cycle, audit events)
cd daml/bridge-core-tests && daml test
# Wayfinder tests (E2E deposit/withdrawal flow)
cd daml/bridge-wayfinder-tests && daml test| Package | Tests | Coverage |
|---|---|---|
cip56-token-tests |
test, testTransferWithMerge, testTransferNoExisting |
Mint, Transfer (with/without merge), Lock, Compliance |
bridge-core-tests |
testBridgeFlow, testAuditObserverVisibility, testPartialBurnWithAuditEvent, testBasicToken |
Full bridge cycle, audit events, partial burns |
bridge-wayfinder-tests |
testIssuerCentricBridge, testAuditObserverManagement, testFingerprintMismatchRejected, testMultipleUsers |
E2E flow, observer management, fingerprint validation, multi-user |
The ethereum/ directory contains the Solidity smart contracts for the EVM side of the bridge:
| Contract | Description |
|---|---|
CantonBridge.sol |
Main bridge contract with deposit/withdraw |
TokenRegistry.sol |
Registry for bridgeable ERC-20 tokens |
See ethereum/README.md for contract details.
For full end-to-end testing with Ethereum integration, see:
docs/E2E-TESTNET-SETUP.md - Complete guide covering:
- Canton Network quickstart setup
- EVM contract deployment (Sepolia)
- Middleware configuration
- Deposit/withdrawal testing
- Troubleshooting
All contracts implement Canton privacy best practices:
- Need-to-Know Visibility - Contracts visible only to relevant parties
- No Global Observers - No admin parties that see all transactions
- Privacy-Preserving Compliance - Whitelist checks without leaking user lists
- Issuer-Centric Model - Issuer controls minting/burning on behalf of users (no user Canton keys required)
- Fingerprint-Based Authentication - EVM addresses map to Canton parties via cryptographic fingerprints
| Document | Description |
|---|---|
| CHANGELOG.md | Version history and migration guides |
| E2E Testnet Setup | Full end-to-end testing guide |
| Architecture Proposal | Technical design and roadmap |
| EVM Bridge | Solidity contracts documentation |
- Documentation: See docs/
- Issues: GitHub Issues