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 Github.com.
Initializing the Smart Contract
Solidity, like other object oriented languages, has a constructor that gets called when the contract is activated.
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 Github.com 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
I’m imagining that the first thing that will happen after the attorney initializes the contract is that he or she will send the address of the contract to the client to sign (or, more likely, send a link on a distributed app). Here’s how the client would sign the 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
Of particular interest to attorneys is how the contract gets funded. For that, we use the fund() function.
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
Remember that both the client and the attorney need to sign. The way the attorney signs is pretty similar to the way the client signs it.
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
Now let’s talk about the evaluateContract method works and why it’s the “smart” of the smart contract.
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
If the contract gets funded but the contract never gets fully executed (through the client signature and the attorney’s countersignature), we don’t want the funds to get locked into the contract. So I added a safeguard that would let anyone return the funds to the client up until the point where the funds get transferred to the attorney.
Again, not sure if this is the right way to approach it — but at least the funds don’t get lost.
One thing that’s interesting to note about this is that the funds are held in suspension, within the contract’s account, until all the conditions of the Solidity logic are met. This is different from being held in trust, which creates all kinds of ethical concerns for attorneys. But it’s similar too in that it simplifies the ability of the parties to return funds to the client if the contract never gets fully executed through the returnFundsToClient function.
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”.