This project provides a Daml implementation of an m-of-n multi-signature wallet on the Canton Network. It allows a group of parties to collectively manage assets, where any transaction requires approval from a minimum number of members (m) out of the total n members.
This pattern is essential for applications like:
- DAO (Decentralized Autonomous Organization) treasuries
- Corporate expense accounts
- Joint savings accounts
- Escrow services
Daml provides a robust framework for modeling multi-party workflows with built-in authorization and privacy. Canton, as a privacy-enabled distributed ledger platform, ensures that wallet details and transactions are only visible to the involved parties, a critical feature for enterprise and institutional use cases.
- Privacy by Default: Canton ensures that only the signatories of a specific wallet can see its state and pending proposals. Unrelated parties on the network have no visibility.
- Verifiable Execution: Daml's smart contract logic guarantees that transactions are only executed when the pre-defined signature threshold is met. The rules are code and are enforced by the ledger.
- Clear Authorization: The
signatoryandcontrollerkeywords in Daml make it explicit who can create wallets, propose transactions, and approve them. - Interoperability: Canton's design allows multi-sig wallets to interoperate across different domains and blockchains, enabling complex cross-chain treasury management.
The workflow is designed around two primary Daml templates:
-
Wallet: This is the main contract representing the shared account.- It holds the list of
signatories(nparties). - It defines the
minSigsrequired for any transaction (m). - It acts as the authority for creating new transaction proposals.
- It holds the list of
-
TransactionProposal: This contract represents a pending transaction that has been proposed but not yet fully approved.- It contains the
payloadof the transaction (e.g., transfer details). - It tracks the parties who have already
cosignedthe proposal. - Once
minSigsis reached, the transaction can be executed.
- It contains the
The typical lifecycle of a multi-sig transaction is as follows:
-
Wallet Creation: A group of parties (e.g., Alice, Bob, and Charlie) agree to create a shared wallet. One party creates the
Walletcontract, specifying allsignatoriesand the signature threshold (e.g., 2-of-3). All other parties are signatories on this contract. -
Transaction Proposal: Any signatory (e.g., Alice) can propose a transaction by exercising the
ProposeTransactionchoice on theWalletcontract. This creates aTransactionProposalcontract, with Alice as the first signatory. -
Co-signing: The other signatories (Bob and Charlie) are observers on the
TransactionProposal. They can review the transaction details and, if they agree, exercise theCosignchoice to add their signature. -
Execution: When the number of co-signers reaches the
minSigsthreshold, theCosignchoice automatically triggers the final action. For example, if Bob is the second person to sign a 2-of-3 proposal, hisCosignaction will not only add his signature but also execute the transaction payload. -
Cancellation: The original proposer can cancel the
TransactionProposalat any time before it is fully signed and executed by exercising theCancelProposalchoice.
- Daml SDK v3.1.0
- A running Canton environment. A minimal configuration is provided in
canton/canton.conf.
Compile the Daml code and create a distributable .dar file:
daml buildExecute the test scenarios defined in daml/Test.daml:
daml test-
Start the Canton Ledger: Open a terminal and run the Canton console from the project root.
canton -c canton/canton.conf --bootstrap canton/bootstrap.canton
This script will start a participant node, connect it to a mediator and domain, and allocate the necessary parties (
Operator,Alice,Bob,Charlie). -
Deploy the DAR file: In the Canton console (
canton>), deploy the compiled DAR file to the participant node (p1).p1.dars.upload(r".daml/dist/canton-multisig-wallet-0.1.0.dar")
-
Run the Setup Script: In a new terminal, run the
Daml.Scriptto initialize the contracts on the ledger. This will create a 2-of-3 wallet for Alice, Bob, and Charlie.daml script \ --dar .daml/dist/canton-multisig-wallet-0.1.0.dar \ --script-name Main:setup \ --ledger-host localhost \ --ledger-port 10011 # Default port for participant p1
You can now interact with the wallet by proposing and co-signing transactions via Daml Script or the JSON API.