The only valid smart contract is a voluntary one — easier said than done
Daml models, tracks, and enforces smart contract rights and obligations
In What properties must an enterprise smart contract language have?, Simon and Neil defined several properties that “a smart contract language must enable for it to be acceptable for automating financial workflows.” The first of these specified that “for the consequences of a contract to be compulsory, entrance must be voluntary.” Sounds pretty straightforward, right? But let’s probe this property more deeply and see what surfaces.
A contract is universally considered to be a voluntary arrangement between two or more parties that is enforceable by law as a binding legal agreement. It’s only when all parties enter into a valid contract voluntarily that they become obligated to perform to the terms of the agreement and can be compelled to do so by judgement in a court of law; if a party had no say in the formation of a contract, a court can’t compel them to perform to the contract’s terms.
Because the voluntary nature of contracts has been an aspect of the rules codifying contractual human interaction for centuries, voluntary entry tends to be taken for granted since all modern business processes are based on contracts built in this fashion.
In fact, very few programmed business processes today even check beyond the initial terms of service box that you are required to voluntarily mark whenever you sign up for a new credit card, join a loyalty program, authorize an account for electronic transfers, create an ID on an online service, etc. Once you’ve agreed to the terms, all future interactions are simply assumed by the programming to have been made voluntarily because you ticked that service agreement box — if there’s a dispute, it’s sorted out via customer service or, if necessary, the courts.
However, managing agreements on a distributed ledger is an entirely different beast. A goal of DLT is the automated processing of contracts, and a property of the ledger itself is provable integrity — every party to an agreement validates that everything recorded on the ledger is properly formed. In practice, it’s actually quite hard to maintain provable integrity in an automated DLT system.
Maintaining provable integrity of the ledger requires proof that every obligation arising from an action taken on a contract was entered voluntarily. One obvious way to ensure this is to require every party to every contract to sign every action taken on those contracts. Some DLT architectures are in fact engineered this way, but such a brute-force method is not just highly inefficient; it can in certain circumstances cause the progression of the system to halt (this is covered by the next blog in this series). Finding a way to automate the codification of contracts to ensure their voluntary formation without forcing multi-signature protocols is proving, for some, to be a rather difficult task.
What’s needed is a smart contract language that natively models the rights of each party to a contract, and automatically manages how those rights change as a contract progresses through its workflow.
As Ben and Ed pointed out in A new language for a new paradigm: smart contracts, Digital Asset’s contract modeling language, Daml, is “a language of contracts, where the contracts and parties to them are native constructs”. It is a Domain-Specific Language (DSL) whose programming model provides concise notation using specialized vocabulary and abstractions familiar to the domain expert, and its expressivity is restricted to disallow nonsensical content.
Through this programming model, Daml enables an important — and unique — safety mechanism for financial contracts that guarantees that for every contract entered on the ledger, any obligation associated with a party must have involved that party’s prior authorization.
Describing how contracts are formed. Daml greatly simplifies the task of contract formation through a set of built-in types and functions that allow contracts, parties, rights, obligations, and authorization to be expressed directly in the language.
In Daml, a developer codes contract templates that use high-level abstractions to precisely express agreements among parties, defining the rights and obligations of all parties involved in those agreements. A concrete contract instance is then created on the ledger by instantiating a contract template with parameters describing the specific agreement being formed.
Rights are modeled as choices, each with a defined controller. When the controller exercises a choice on a contract, the Daml code detailing the agreement is executed — which can create further contracts and exercise other choices. Obligations come in two forms: they can either arise from off-ledger obligations that are part of the agreement, or they are accrued from contracts that can be created when other parties use their rights to exercise choices on a contract that has already been approved.
Contracts are written to the ledger whenever a party directly instructs the ledger to do so, or exercises a choice on an existing contract whose code creates new contracts. Complex business workflows can be defined using sequences of contracts as the basic building blocks. Each contract within such a sequence provides choices to create the next workflow step(s).
Specifying which parties have authorized this formation. In Daml contracts, the notion of signatories — who sign a transaction — is distinct from that of obligable parties — who have obligations as a result of the current state of the ledger. Other smart contract languages do not make this distinction. This separation gives the developer of a Daml smart contract great flexibility to delegate rights and model complex real-world business workflows.
In Daml, a developer can explicitly identify the parties that have obligations under an agreement — requiring their consent to the creation of a contract on the ledger — and Daml’s built-in obligation checker will guarantee that all such “signatories” to the agreement have made the explicit choice to enter into that agreement. This mechanism allows Daml to protect parties from being forced into an agreement by explicitly indicating which parties may accrue an obligation due to a contract being added the to ledger.
When a contract is created directly by sending a create command to the ledger as part of a transaction, it must have exactly one signatory, and this signatory must be the party committing the command. Because this party is the only signatory it is also the only one who can have an obligation as a result of this command.
However, things get really interesting when contracts are created indirectly — through the exercising of choices that had previously been authorized by all parties.
Recall that earlier we described how every choice in a contract has a corresponding controller, the party with the right to exercise that choice. One thing that sets Daml apart from other languages is the fact that, in Daml, when signatories authorize the creation of a contract they also authorize the controllers to effectuate the changes to the ledger that may be performed by the code linked to these choices. This may include creating new contracts which impose obligations on the signatories of the contract the choice is being exercised on, or exercising choices on their behalf.
This ability enforces the rule that a contract can only be created on the ledger after it has been authorized by all parties for whom obligations arise from it, without requiring parties to be involved in the authorization workflow if they had previously authorized the agreement that triggered that workflow. This very powerful feature of Daml — delegation of rights — is best understood when examining multi-party agreements.
Forming contracts between multiple obligable parties. Parties voluntarily enter into agreements by creating contracts to which they are the only signatory, or by exercising choices on existing contracts. Because of the rules that Daml enforces, it is not possible for a single party to create an instance of a multi-party agreement as such a creation would force the other parties into that agreement without their consent. To create a multi-party agreement, the actual contract is preceded by a sequence of offer contracts, each of them giving a particular party the choice to enter the agreement.
This “offer-acceptance” pattern for instantiating contracts is very common in Daml and proceeds in two steps. First, an originating party, say Alice, creates a contract that contains a choice controlled by the receiving party, say Bob. Second, when Bob exercises this choice, a new contract is created on the ledger and Alice’s offer contract is archived. This new contract identifies both Alice and Bob as signatories and spells out their rights and obligations. Alice and Bob have both authorized this contract; Alice when she created the offer contract, and Bob when he exercised the choice on that offer.
Denoting which parties have delegated rights under a contract. In this example, Bob had control over a contract choice on the ledger that led to the creation of a new contract with obligations for both himself and another party, Alice. Effectively, Alice’s original offer contract allowed Bob to perform an action on behalf of Alice — without Alice explicitly committing the action herself. Put differently,
Alice gave Bob the right to create a contract on her behalf.
In such a delegation scenario, Alice is an obligable party of the offer contract, and hence has to authorize its creation, but her authorization is not required to create the contract that resulted from Bob exercising a choice on that offer. It is precisely this feature that allows for the sort of efficient market operations that will be discussed in the next blog, and it is only possible because the Daml programming model contains the proper contract abstractions and the Daml obligation check enforces contract rules.
Automatically checking code for problems. As Ben and Ed pointed out in their blog post, “The fact that Daml expresses contracts directly also means that the Daml system itself can reason about these contract concepts directly, automatically checking the code for problems involving rights, obligations, and lack of authority.”
While an ultimate authorization check at runtime prevents parties from creating a contract with obligations without prior authorization from the obligated parties, the Daml developer does not have to resort to runtime testing to see whether their contract code inadvertently contains unauthorized obligations.The Daml SDK tooling can analyze the code at development time, and flag potentially illegitimate contracts in workflows as the code is being written — greatly simplifying the effort required to produce correct models and workflows which don’t place any party into an obligable position without their consent. The Daml SDK will be the focus of a future blog in this series.
Daml is a language of contracts
Daml’s encoding and analysis of obligable parties is a powerful aid to the contract developer. Because contracts, parties, rights, obligations, and authorization are native constructs, Daml is able to explicitly and continuously track the flow of authorization between rights, obligations, and delegations of rights. When a party tries to commit an update that would create a contract instance, Daml first checks that all obligable parties for the contract have authorized the committing party to do so in prior choices. This check ensures that all parties enter obligations voluntarily, and therefore Daml guarantees that all contracts on the ledger are indeed arrived at voluntarily.
The ability to analyze obligable positions is a huge timesaver for the developer. Our Daml SDK partners have been reporting that this instant feedback highly increases developer productivity and catches bugs as they’re being written, greatly reducing development feedback cycles. And it’s not merely convenient; as we’ll see in the next entry in this blog series, this exclusive Daml feature can also help streamline business workflows — which has huge ramifications on the way these workflows are automated through the ledger for certain DLT architectures. In fact, the way Daml is designed allows for DLT architectures that would not even be possible otherwise. Later on, the series will also discuss how being a “language of contracts” simplifies the formal verification of contracts written in Daml.
Read Part 5: “Trust but verify” is a valuable DLT model — does your language support it?
New to this series about Daml? Click here to read from the beginning!
Join the community and download the Daml SDK.
This story was originally published 31 May 2018 on Medium
About the authors
Martin Huschenbett, Ph.D, Senior Software Engineer — Language Engineering, Digital Asset.
Martin joined Digital Asset’s language engineering team in 2017, where he works on the Daml compiler and obligation checker. Previously, as a member of the trading systems team for the proprietary trading firm Jane Street Capital in London, he contributed to the research infrastructure used by the quantitative analysts, and the monitoring systems for the compliance team.
Martin holds a Ph.D from Technische Universität Ilmenau in Germany, where he worked as a research associate at the Department of Theoretical Computer Science. His academic work included research and teaching primarily in the fields of computational logic, automata theory and formal verification. He held a postdoctoral position at the Ludwig-Maximilians-Universität München prior to joining Jane Street Capital.
Jost Berthold, Ph.D, Senior Software Engineer — Language Engineering, Digital Asset. http://jost-berthold.de
Jost joined Digital Asset’s Sydney team in mid-2017 to focus on solution engineering and Daml language engineering. Prior to joining DA, he spent several years at the Commonwealth Bank of Australia, working on big data analytics and customer data insights solutions for the bank.
Jost holds a Ph.D with distinction from Philipps-Universitat Marburg in Germany, where he focused on parallel programming with functional languages. Prior to applying his knowledge in a financial industry setting, he held several positions in academia — first interning at Microsoft Research Cambridge, then holding postdoctoral positions at the University of St. Andrews and the University of Copenhagen (DIKU). In 2011 he joined the faculty of DIKU full-time as an assistant professor to teach canonical computer science topics at the Bachelor and Master levels. During this time, his research centered on parallel functional programming concepts and domain-specific languages for mathematical finance.
Even though he now works in industry, Jost has always maintained his links to academia — serving on programme committees and as a reviewer for conferences and workshops in functional programming, and maintaining a Haskell variant that executes programs in parallel on distributed memory platforms.