Client-attorney retainer agreement, implemented as a smart contract

As I mentioned yesterday, thought I’d play around with a smart contract implementation of an attorney/client retainer agreement this weekend.

Here’s how the agreement works, at a high level. Attorneys don’t always need retainer agreements, but they do if the attorney is going to limit the range of services he or she provides, which attorneys almost always do when they accept a one time, flat fee for their work. The agreement needs to define the terms and both the lawyer and the client need to sign it. That’s all we really need.

In this smart contract, I added a funding mechanism with an automatic transfer feature, which I think is a useful addition that takes advantage of the Ethereum virtual machines. Each time a significant action happens such as the client signing, the attorney signing, or funding the contract, the contract evaluates itself to determine whether it should transfer funds (ether) to the attorney.

The contract is written in Solidity, a language for smart contracts running on the Ethereum network. If you’re an attorney seeing this for the first time, you might be surprised to see how low level the Solidity language is. Take a deep breath. Another thing to note is that, as I write this, I only know the code compiles but I’m not certain it actually works yet. More about that later. The full code is available on

Initializing the Smart Contract

The constructor is also defined as a function except that it has the same name as the contract (you’ll see that in a moment). In this constructor, the contract needs to know what the required fee (_requiredFee) will be and what the terms (_terms) of the contract are. It also assumes that whoever launched the contract on the network is the attorney (counsel) who owns it. It does this by looking at the built in structure msg, which includes the sender.

In the code above, you see where the data from the constructor and the other values gets stored. You’ll also notice that smart contracts in Solidity are defined with the keyword, “contract,” which is kind of cool. By looking at the data structures I’ve put into the retainer agreement, you can also see some other assumptions in this smart contract, such as the fact that there can only be one client.

The terms could be the full text of the terms (maybe stored in markdown) or maybe an immutable link to a check in or something. Probably putting the terms into the contract make the most sense to make ensure immutability.

How the Client Signs the Smart Contract

The function does three interesting things. First, locks in the address of the client (as inferred by the sender of the message through the msg construct) through the assignClientIfNotAssigned function.

You can see that whoever signs it gets locked in as the client. This has an interesting consideration on the funding piece, which we’ll talk about in a moment.

Next, you can see that the clientSign function marks a state variable called clientSigned as true. You might think this isn’t really necessary because once we know we have a client, then we can assume it’s signed. But I think there’s some value, given that this is intended to be a legally binding contract, to have a clarity and redundancy that violates the efficiency principle that many software engineers live by. Also, as you’ll see below with my implementation, it might just be wrong to assume that if you have a client address that you have assent.

Finally, you can see that we call the evaluateContract function to see if it’s ready to fund. Theoretically, the client signature could be the last step in the process. More about the evaluateContract function later.

How the Client Funds the Contract

Recall that I’m not 100% sure this actually works as intended, but let’s talk through it. First, you can see that it will infer that the message sender is the client, which creates the assent problem I mentioned above. We talked about the assignment function previously.

Next. you can see that there’s a check in the function to make sure that the fee matches the required fee (no more, no less). If not, the contract will throw an error to client. Then it captures the fee as an integer, which is the part I’m most uncertain about right now. After that, it runs the evaluateContract again.

As I mentioned in the comments to the contract, you can see that this smart retainer agreement accepts only one client, which might be a problem for domestic relations attorneys or anyone dealing with multiple parties.

Finally, you’ll notice that the Solidity language asks for the payable keyword whenever you’re funding a contract.

How the Attorney Signs the Contract

Notice here that there’s an extra check to make sure that the attorney signing is actually the attorney who initiated the contract. You’ll notice that we’re relying heavily on the security mechanisms built into Ethereum’s blockchain.

Again, as mentioned previously about inferring assent: as a software engineer, you might be tempted to assume that the attorney manifests assent by uploading the contract (and capturing the account address). Since smart contracts are so new, however, I think it makes sense to have an explicit, extra step.

Since usually the attorney is the last to countersign, let’s turn to the magic of the smart contract.

How the Smart Retainer Agreement is Smart

Pretty short, huh? All it does is ask this question: did the client sign, the attorney sign, and is the fee paid? If so, transfer the funds (ether) to the attorney.

Remember this function doesn’t magically get called. The contract evaluates the condition on every major phase of the contract.

I’m not sure this is the best approach, but it’s the simplest thing that came to mind as I was constructing it. There are other constructs and possibilities in Solidity that might be more elegant or more fun such as events. As I learn more, I’ll try to update this post!

What If Something Goes Wrong

Again, not sure if this is the right way to approach it — but at least the funds don’t get lost.

Closing Thoughts

A final thought on this is that I understand this two party contract isn’t exactly the most exciting contract for the Ethereum community in the sense that it’s just bidirectional. There was no third party in the original contract. Still, I thought it was a fun exercise and it does show off some of the exciting features, such as the automatic funding of the contract.

This post originally appeared on the Smart Contracts Lawyer blog as “Client-attorney retainer agreement, implemented as a smart contract”.

buidl + legl = Compiling the law into EVM bytecode. California lawyer. Open source legal solidity smart contracts contributor.