Creating your first Daml smart contract
Build a PaymentObligation contract step by step.
This walkthrough teaches the core Daml mental model by building a very small contract from scratch.
Before you begin, complete the environment setup in Getting Started.
What you will build
Imagine Alice owes Bob money. You want to record that obligation on a ledger. Before writing any code, ask yourself:
- Who are the parties? Alice (the debtor) and Bob (the creditor). In Daml, a
Partyrepresents a real actor in the system, like a person, company, or institution. - Who must authorize this contract to exist? Should Bob alone be able to create a ledger record saying Alice owes him money, without Alice's approval? Clearly not. Both Alice and Bob must agree. These authorizing parties are called signatories.
- Who can trigger payment? Alice, the debtor. The party allowed to perform an action on a contract is called the controller.
These three concepts (Party, signatory, controller) are the foundation of every Daml contract. Here is what the full interaction looks like:
You will now turn these concepts into code.
Create a project
dpm new payment-obligation --template skeleton
cd payment-obligationThis gives you a project with a daml/Main.daml file. Open it and replace the contents as you follow along.
The module declaration
module Main whereEvery .daml file starts with a module declaration, similar to a Go package or a JavaScript module. The module name must match the file name (Main.daml maps to module Main).
Define the template
template PaymentObligation
with
debtor : Party
creditor : Party
amount : Decimal
whereA template is the blueprint for a contract. Think of it like a class in Python or a struct in Go. Each contract created from this template will have its own debtor, creditor, and amount.
| Field | Type | Purpose |
|---|---|---|
debtor | Party | Alice, the party who owes |
creditor | Party | Bob, the party who is owed |
amount | Decimal | How much is owed |
Party is a built-in Daml type that represents an identity on the ledger. Decimal is a fixed-precision number suitable for financial amounts.
Signatories
signatory debtor, creditorA signatory is a party that must authorize the creation of a contract. By listing both debtor and creditor, we encode the rule we established earlier: a contract should only exist if the parties affected by it agree to it.
Back to our example: Bob cannot create a record saying "Alice owes me $100" without Alice's consent. Both signatures are required.
The Pay choice
nonconsuming choice Pay : ()
controller debtor
do
archive selfA choice is an action that can be performed on an active contract. Let's break down each part:
nonconsuming choice Pay : ()declares a choice namedPaythat returns nothing (()). Thenonconsumingkeyword means the choice does not automatically archive the contract when exercised.controller debtormeans only Alice (the debtor) can trigger this choice. The controller is the party allowed to exercise a choice, and the ledger enforces this, not just a code convention.archive selfexplicitly removes this contract from the active ledger.
Why nonconsuming + archive self?
By default, Daml choices are consuming: they archive the contract automatically. Here we use nonconsuming and then explicitly archive self in the body so the contract lifecycle is visible in code. This makes it clear to readers that exercising Pay ends the obligation.
Full contract code
Here is the complete daml/Main.daml. Copy this into your project:
module Main where
template PaymentObligation
with
debtor : Party
creditor : Party
amount : Decimal
where
signatory debtor, creditor
nonconsuming choice Pay : ()
controller debtor
do
archive selfBuild your project
Verify the contract compiles:
dpm buildIf you see no errors, your template is valid and ready for testing.
Why this model matters
The three concepts you just learned (signatory, controller, and archive) map directly to the questions we started with:
signatoryanswers "who must authorize this contract to exist?"controlleranswers "who can perform each action?"archive selfanswers "what happens when the obligation is fulfilled?"
Next step
Now that you have a working contract, learn how to verify it behaves correctly in Testing your first Daml smart contract.