The structure and flow of Daml smart contracts: Part 1

In this two-part series, I will walk you through the Daml smart contract structure (static view) and flow (dynamic view). These two views together convey the full picture of what Daml smart contracts are, and the business value they carry.

Underlying these two views of smart contracts is the Daml ledger model, which describes how a Daml ledger, acting as a kind of smart contract storage or database, records facts, rights, and obligations.

unnamed-15

The abstract view of a Daml ledger

How Daml smart contract structure mirrors the purpose

The Daml smart contract structure follows from 1) the purpose of the Daml platform, and 2) usability requirements.

Daml ledgers, similarly to other solutions commonly called “blockchains” or “distributed ledger technologies”, help solve for a long-common societal need: distributed systems that record facts and enforce rights and obligations — think hard currencies, contracts, bookkeeping, land and birth registries, trade finance, and so on. For thousands of years, these systems of record were built on analogue technology, like paper documents, handwritten “wet ink” signatures, seals, and postal services. In the last couple of decades, however, we have started to digitize these systems of record, which promises a tremendous improvement in scale, efficiency, and reliability. The Daml platform is an advanced stage of this digital evolution. 

To sum it up concisely, the purpose of Daml smart contracts, which live on Daml ledgers, is the following: A Daml smart contract is either a unilateral declaration or a multilateral agreement. In both cases, the smart contract architecture reflects that it records facts, rights, and obligations, enforcing need-to-know-basis visibility rules.

Let’s take a closer look at parts of the Daml smart contract structure using a concrete smart contract example — a ticket offer template, outlined on our Why Daml? page.

unnamed-14

https://gist.github.com/gyorgybalazsi/d8e546eed4bee8b9c4fe539348ebe5c3

Templates vs. instances

The “template” keyword indicates that the code itself is a smart contract template, out of which smart contract instances can be created on the ledger, or smart contract storage. The concrete implementation of the ledger can be a database or blockchain.

Recording facts

No matter whether a Daml contract expresses a unilateral declaration or a multiparty agreement, it always records certain facts. Under the template name, the template has two main blocks. The first block is marked using the “with” keyword. This part is called the contract payload, listing fields and data types, which specify the stakeholder parties and other details. Daml templates can also specify constraints the payload must satisfy.

Real-world actors

There is always a party who declares a fact, or parties who must agree on something. Correspondingly, every Daml contract involves one or more real-world actors, which are represented on the ledger by ledger parties, indicated by the “Party” data type, which contains a unique party ID, along with some other details. The link between real-world actors and ledger parties are the signed access tokens which contain the party ID, and have to be attached to the API call whenever someone requests a ledger transaction.

Ledger parties are either signatories, who agree to the creation of the contract (being in a sense “owners” of the smart contract), or observers, who can only view it.

Rights and obligations

We usually don’t record facts just for the sake of it. We want to use the recorded data to enforce some rights and obligations between transaction parties. This is reflected in the smart contract structure.

The “where” block of our Daml template specifies who can do what with the already created contract instance. These options are called “choices”. The example contains one single choice, “Accept”, which entitles the “buyer” to accept the offer, specifying a reference to a “Cash” contract to pay for the ticket. 

Composing workflow steps

A basic feature of Daml is workflow composition, which is reflected in the smart contract architecture. The “do” block of the “Accept” choice contains a list of actions:

  • the fetching of the “Cash” contract of the buyer 
  • ensuring that the amount of the money represented by the “Cash” contract is equal to the ticket price
  • the transfer of the cash from the buyer to the organizer
  • the creation of a “TicketAgreement” contract, which represents the ownership of the ticket 
  • and, through the hidden “Archive” choice, the archival of the “TicketOffer” contract

The “do” block notation makes sure that all these actions are performed in an atomic or “all or nothing” way: if the “Cash” contract specified by the buyer doesn’t exist, or the amount of cash is not equal to the ticket price, none of the actions listed in the “do” block gets committed.

This atomic composition of actions is guaranteed by what’s called “monadic composition” in functional languages. We’ll have more on that in the next part of this series. In the meantime, if you want to know more about “do” blocks and actions, check out the Actions and do blocks section of the Daml docs.

Usability considerations

You might have noticed that the TicketOffer template is fairly easy to read, after you’ve understood what the components of the smart contract architecture do. This is not a coincidence.

The intended audience of the Daml code is not only programmers, but also business stakeholders and lawyers, so Daml wants to be as close to being a “Business Readable DSL” (as Martin Fowler put it) as it gets with current programming languages. Daml is a Haskell-based language, inspired by a famous article written by Haskell creator Simon Peyton Jones and others, titled Composing Contracts: An Adventure in Financial Engineering.

Some features of Haskell help to achieve this level of readability. Haskell uses indentation to signify blocks instead of curly braces. Function application doesn’t require parenthesis — the arguments are just written after the function name, divided by spaces (similarly to CLI commands). Functions can easily be composed: “Do” blocks express atomic composition of a series of actions, etc.

Check out our interactive tutorial on fundamental Daml concepts, and stay tuned for part two of this series, in which we’ll explore the flow of Daml contracts.

 

About the author

György Balázsi is a certified Daml developer and an active community member on the Daml Forum. Holder of one of the community recognition rewards. He is a digital strategist and consultant, working in the intersection of business and IT.

Follow György on Daml Forum and Twitter.