Min-Kyu Jung Subscribe

Sign up for new posts in your inbox

If you just want to say hi, my email is mkyujung@gmail.com

The future of contracts is code

Contracts and computer programs are surprisingly similar. If you accept this, it follows that the way contracts and computer programs are written could become surprisingly similar too.

This means that coding best practices now are a leading indicator of contract drafting best practices in the future. If you are a lawyer, you can find clues in the way your job will look in ten years by looking at how code is written now.


I. Contracts are like code

A contract is made up of clauses, which act as a set of instructions for the parties to execute. A computer program is made up of code, which acts as a set of instructions for the computer to execute.

Both share some similar fundamental attributes. Here are some examples.

Variables

1
let theCompany = "ACME Company Limited"

The code above is declaring a variable.1 Even if you aren’t familiar with the syntax being used, you might still be able to make a guess at what it is doing.

Here’s a translation:

JavaScript English
Let theCompany = “ACME Company Limited” “The Company” means “ACME Company Limited”

Declaring and assigning variables in code is like defining terms in legal agreements. The word let indicates that a variable theCompany is being declared, and the = sign indicates that the text "ACME Company Limited" is being assigned to the variable theCompany. In other words, we are defining the term theCompany to mean "ACME Company Limited".

Why would you assign a variable in code? The same reason you would define a term in a contract. Variables are concise and readable. Imagine how tedious it would be to type out the name of the parties in full every time instead of referring simply to the “Vendor” and “Purchaser”. Not only would this be annoying, but you’d also increase the chances of making a mistake, or a party making an error in interpretation.

In programming, there’s a concept called DRY — Don’t Repeat Yourself. It means you should avoid repeating identical code by using abstractions like variables. The opposite of DRY is WET — “write every time” or “write everything twice” or the weirdly aggressive “waste everyone’s time”. Defined terms are DRY, and you don’t want to be WET.

Operative clauses

An operative clause is a clause that requires something to be done or not done. Operative clauses are often condition precedents that must be fulfilled to trigger the obligations of the contract. In a sale and purchase agreement, for example, the obligation to transfer the property being sold only arises when the purchase price has been paid.

The structure of conditions in contracts look like this:

If condition X and / or condition Y is fulfilled, then action Z will happen.

For example, let’s say you want to raise money for your awesome app idea (it’s like Tinder, but you can only communicate in emojis). Your friend Sally says she will fund you, but only if you can find 1,000 users within 150 days of launch. The agreement could be expressed like this:

If the Company has 1,000 users and it has been less than 150 days since launch, then the Company can take Sally’s funding.

We can reformulate this as a test of whether conditions X and Y are true or false. Every condition in a contract will have logic that evaluates to either of these two values. This is called “boolean algebra”, and forms the basis of programming logic.

For example, if your app is featured on TechCrunch within a month of launch and instantly receives 1,000 sign-ups, both conditions evaluate to true and you are entitled to take Sally’s money.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//Declare variables
let daysSinceLaunch = 20;
let userCount = 1200

//Check whether conditions have been met
if (userCount >= 1000 && daysSinceLaunch < 150) {
  isFundingOptionAvailable = true;
} else {
  isFundingOptionAvailable = false;
}

if isFundingOptionAvailable === true {
  // You can now choose to take Sally's funding
};

Let’s break this down. The code on lines 2 and 3 declares two variables.2 First, the variable daysSinceLaunch is set to 20, indicating that it has been 20 days since launch. Second, the userCount variable is set to 1,200, which means that there are 1,200 users.

Now that the variables have been declared, the code starting on line 6 sets up a conditional operation. It says that if the userCount value is greater than or equal to 1,000 (that is, if there are 1,000 or more users), and the daysSinceLaunch value is less than 150, then the isFundingOptionAvailable variable will be toggled to true, making the option to take Sally’s funding available. If either the userCount or daysSinceLaunch condition isn’t satisfied, then the else operator is triggered, setting the isFundingOptionAvailable variable to false.

In our example, the userCount value is greater than 1,000, and the daysSinceLaunch value is less than 150, setting the isFundingOptionAvailable variable to true. This means that you can take Sally’s funding, and presumably become a billionaire as you dominate the nascent market for emoji-based dating services.

Each operative clause in a contract is itself an implicit if / then statement. If this clause is breached, then I have a legal entitlement to whatever damages that may arise from that breach. And every legal agreement, when stripped away to its bare logic, is boolean, sort of like how every computer programme ultimately compiles down into 1s and 0s that represent binary true and false values.

1. George Boole, the father of boolean algrebra. 2. A visual representation of boolean logic gates. Source: Dave Whyte for Quanta Magazine

Non-operative clauses

Some clauses aren’t readily conditional because they deal with the wider relationship between the parties. They’re non-operative clauses.

A clause that states that a contract should be under the jurisdiction of New Zealand law, for example, doesn’t set up a condition in and of itself. Instead, it sets up a framework that determines how the rest of the contract should be interpreted, kind of like a set of rules.

Computer programs have rules, too. After all, code is just text. It’s the language that the program is written in that determines how that text should be interpreted or compiled.3

So non-operative clauses, which are a set of rules on how a contract should be governed, are like programming languages or frameworks, which are a set of rules on how the code should be governed. For example, theCompany = "ACME Company Limited" is valid code in Python and Ruby,4 but it could cause bugs in JavaScript, where declaring a variable first is best practice: let theCompany = "ACME Company Limited". Likewise, a contract governed by Australian law is read differently to a contract governed by New Zealand law.

Just like legal systems, there is diversity in programming languages. The split between object-oriented and functional programming languages might seem familiar to a lawyer who has worked across common law and civil law jurisdictions.

It’s true that programming languages share a lot of similarities — a competent Ruby programmer should be able to pick up Python relatively easily. But the rules are different, and if you’re switching languages you better be aware of them.


II. The future of contracts

Contracts are like code. This suggests that the process of drafting a contract could look like the process of developing a computer program.

I think most people intuitively assume that lawyers draft contracts the way a student might write an essay for a class. First, they gather information on the subject. Then, they sit down in front of a computer and compose an original 3,000-word document based on their findings. After a few proofreads, it’s ready for submission.

In practice, the contract writing process is more about assembly than creation, and more about pattern matching than creative thinking. The starting point is to compare the current matter against previous matters you have worked on, and to the extent that one is similar to the current fact situation, you copy sections of that contract to your new one.5

If building a contract is like writing an essay, it makes sense that it would be done on a word processor. You don’t need powerful software to write an essay. But if building a contract is more like writing a computer program, writing a contract like an essay is like painting a wall with a toothbrush - you’re working at the wrong level of abstraction. When you start thinking about contracts as computer programs, it opens up interesting possibilities for how contracts could be built. Here are two examples.

Reusable clauses

A contract could be built by mixing and matching clauses together, the way a child might build a toy by assembling Lego blocks.

Assembling contracts like Lego blocks is like the concept of modular programming, where software is designed so that the functionality of a program is contained in independent and interchangeable modules. The modules are reusable, so you don’t have to type the same code out twice.6

Reusable components in libraries like React are an example of modular programming. Here they are in action:

1
2
3
4
5
6
7
8
9
// Bring in components from bank of clauses
import restraintOfTrade from './clauses/restraint-of-trade'

// Render Sale and Purchase Agreement 
export default saleAndPurchaseAgreement = () {
  render () {
      <restraintOfTrade />
  }
}

The restraintOfTrade component is being imported from a component bank. The saleAndPurchaseAgreement component is being exported, rendering the imported restraintOfTrade clause. When this code is interpreted, the end-user will see something like this in their application:

1.0 Restraint of Trade

1.1 The Vendor will not, in the [•] area, engage in, conduct, or carry on business the same as, similar to or otherwise competing directly with the Company

1.2 Clause 1.1 will apply for [•] months after Completion.

What are the blobs meant to signify? Those are placeholders. We’ll get to those in a moment.

There are three advantages to treating clauses like reusable components:

  1. Speed
  2. Central source of truth
  3. Fewer bugs

Speed

Just as reusable components speed up development, reusable clauses would speed up contract drafting.

Lawyers currently get by with either “precedents” — generic template agreements to be personalised in a word processor — or a recent analogous contract as a starting point. Building contracts with reusable clauses is a more sophisticated way of architecting contracts. You would be able to generate bespoke documents by selecting which reusable clauses to import, and you could customise these clauses by passing in parameters.

In the example below, the values for the “months” and “area” parameters are passed into the restraintOfTrade component.

1
2
3
4
5
6
7
8
export default saleAndPurchaseAgreement = () {
  render () {
    <restraintOfTrade 
      months = 12;
      area = Auckland;
    />
  }
}

The blob placeholders now have values given to them:

1.0 Restraint of Trade

1.1 The Vendor will not, in the Auckland area, engage in, conduct, or carry on business the same as, similar to or otherwise competing directly with the Company

1.2 Clause 1.1 will apply for 12 months after Completion.

Single source of truth

If you’re breaking a large app into smaller component pieces, you can run into problems with the way you store data. Should the data also be separated into the different components, or should they be held in a separate, central location?

Single source of truth is the practice of structuring data so the primary data, or the “master state”, is only edited from one place. Any link to that data is by reference only, so if the reference is edited, the underlying data remains unchanged.

The concept of a single source of truth isn’t inherent to reusable components, but if you’re working with multiple components it helps to have your data stored in a single location. This way, you can avoid having to manually change values in each component when you want to update anything. You just need to update from the single source of truth.7

You could assemble a clause bank that acts as a single source of truth. Your firm’s clauses would be stored as independent modules within this clause bank. One advantage of this is that if the data in the clause bank is maintained, you would know that you are using the latest “recent market practice” version of each clause. In fact, there could be multiple “latest” versions of the same clause to account for different situations.

For example, if you were drafting a sale and purchase agreement, you might have at least two variations of clauses that you could choose from depending on who you were acting for: one that is favourable to the vendor, and one that is favourable to the purchaser.

Fewer bugs

Reusable clauses and a single source of truth means there’s less room for human error. If you identify a mistake in your drafting, or something needs to be changed, you can update the contract’s primary data, rather than updating every clause individually and risking an oversight.

Instead of copying and pasting an existing contract to create a new document, you would generate a new contract from a clause bank, passing bespoke data into components to auto-fill references to that data. When you change something in a contract, you wouldn’t then need to make sure to change everything that results from that change, because it would happen automatically.

Collaboration tools

Contracts are meant to be a meeting of the minds, but this isn’t reflected in the way they are developed.

If software developers were to build software the way lawyers write contracts, they would send each other .html, .css and .js files as email attachments, with file names like “index (draft 1 January 2020).html” and “index FINAL (2 January).html” and “index REAL FINAL2 (3 January).html”. Internal collaboration would involve cutting code into separate riders to later paste back into the file because only one person would be able to work out of a file at a time. This is spectacularly inelegant, so it’s no surprise that software developers have figured out better ways to collaborate through version control systems like Git.

Git is used to track changes in source code during development. Think of Git as being like a more sophisticated version of Google Docs, in the sense that it allows multiple people to work in the same project. Unlike, Google Docs, each person works on a copy of the project, rather than directly from the central source. The central source is held in a remote repository and acts as the ultimate version of the project. The copies talk to this repository and to each other to make sure they are aligned.

This is how it looks like in practice: users are able to “pull” code from the repository, make changes, “commit” these changes, and “push” them to the repository.

Some core Git commands look like this:

  • Git commit is used to commit to making your changes to the repository
  • Git push is used to send your committed changes to the repository
  • Git pull is used to fetch and merge changes on the remote repository to your local copy
  • Git merge is used to combine multiple sequences of commits into one unified history

To apply this analogy in law, lawyers acting for Party A could review a contract by each making a pull request to fetch the contract from the remote server. After making some changes, they could commit these changes and push them to a new branch in the central repository. The lawyers acting for Party B could then review the commits that have been made by Party A’s lawyers and merge the ones they agree with to the master branch.

Git allows programmers to control branches in a project at a granular level. You could create a branch for a particular section of the contract, or even a specific clause, putting it through iterations of edits before merging it with the rest of the document.


III. What’s next?

Why should lawyers look to programmers for inspiration in rethinking how to build their products, rather than the other way around? Because the software development process is far more optimised than the contract drafting process. People who develop software are able to engineer solutions to their own process problems. Not only that, the fact that a programmer develops software means that they can be aware of potential optimisations that a non-technical person might not even consider as a possibility in the first place. It’s hard to come up with a solution to a problem if you aren’t aware that a problem exists at all.

Most lawyers haven’t considered that people in other industries might have invented 10x better ways of doing version control, or assembling documents. When these concepts do end up getting adopted by lawyers, the implementation details will look different — after all, the promise of a superior version control system won’t mean lawyers start becoming comfortable with entering commands in a terminal.

The general shape of these ideas, however, will look familiar. And when it happens, we’ll look back and realise that the future of contracts was code.


Thank you to Jun Kim, Han Li, Sarah Butterfield, Annie Christina and Josh Eaton for giving feedback on drafts of this.

Cover art by Joanna Ławniczak.


  1. This code is written in a language called JavaScript, which is popular for web development. 

  2. While this code is written in JavaScript, it is pseudocode — i.e. code that can’t actually be compiled and run like a regular program, and is just used for illustrative purposes. 

  3. A computer program called a compiler will translate code that is written in a “high level” programming language written by humans down to machine code that your computer can understand. 

  4. Python and Ruby are high-level programming languages. 

  5. Why is this possible? Clauses tend to act as independent obligations, which means that it doesn’t usually matter if the termination clause is before or after the restraint of trade clause. On the other hand, a good essay has carefully ordered paragraphs. It wouldn’t make sense if the third paragraph was swapped with the first; each paragraph connects logically to the next, carrying a crescendo as the argument is built towards a conclusion. 

  6. This is consistent with the DRY programming principle I touched on in the variables section. 

  7. React doesn’t use a single source of truth natively, because state is stored in each component independently. This is why the React community developed and adopted Redux as a tool to manage state by having a single source of truth.