We Need Some Best Practices For Smart Contracts

Smart Contracts on the Ethereum Blockchain are handling real money; this week over $150mm in a single contract. See daohub for more about The DAO.

Last week, I dug in to a few smart contracts published online with an eye toward assessing complexity and security. You can read more about my reactions here, but the first look wasn't pretty.

Technical debt can be 100% fatal in a smart contract. I'd like to propose some standard functions and questions to be answered for authors of smart contracts that can help protect from a number of problems.

edits May 23

Joey Krug from Augur sent on some thoughts about whitelisting and upgrading contracts in general, which I've included below.

I added a short section on incentive-compatibility, and links to the FC 2016 paper by Delmolino et al.

TL;DR

Too lazy to read the long form essay, or trying to refer back? Here's the short:

Functions

should all be in nearly every smart contract.

Entities With Control

Additionally, rights and responsibilities for the following should be settled:

  • Return of Funds scenario
  • Transfer of Ownership of Contract
  • Outside Demands (Government or Other)

Incentive Compatibility

Put simply -- does the contract incentivize everyone to complete all required actions? This is an area long-time Bitcoiners will have no trouble with; griefers abound in cryptocurrency. For those new to the highly adversarial world of digital currencies, there may be some painful surprises.

Read on for some reasoning on these and suggestions.

Who's Doing The Thinking About This?

Ethereum as of current writing has over $1bn in market value. But, there doesn't seem to be a central repository of coding practices or even a guru. At least, Twitter was crickets when I last asked. I don't want to step on anybody's toes here, but I don't think that I am as of current writing (May, 2016).

While I'm not a newcomer to Ethereum, I am not embedded in the community; I engaged in the first month after announcement, and have spent almost no time since. So, it's possible I'm missing a key resource. But, my guess is there's not much out there. update May 23: Andrew Miller sent me a link to this FC 2016 paper by Delmolino et al Step by Step Towards Creating a Safe Smart Contract. It's worth reading.

I'd like to lay out a framework of questions smart contract authors should answer before they embark on writing and publishing. I have a few suggested answers, but what will be most valuable will be for smart contract authors to start digesting these and discussing them, both in general and in their specific cases.

Comments are welcome: email me and educate me. I'll be sure and incorporate all feedback.

Questions To Answer

Background -- Ethereum contracts are published as bytecode onto the Ethereum chain. For most contracts, a source version is published at on online ethereum explorer, for example The DAO's code can be reviewed at etherscan.io.

As a side note, because contracts are published as bytecode, verifying that the claimed and published readable source code compiles to the bytecode is an ongoing area of work for the Ethereum crowd. This will get sorted out fully, but as of recently, the AST-generator for compiled code has some randomization inherent in its optimizing step. Of course you want optimized code, but you also want verified code.

This is just growing pains; eventually, contracts will be easily verifiable against source code. Without that verification, there is no way for users to trust that inspection of the code has any value at all.

Legal Considerations

You should have answers for the following questions.

Is there a desire to keep others from copying the source code for their own purposes? Should a person own it, or someone else? Should there be a mechanism to change the holder of the copyright in the code? Will it be licensed in a non-permissive way?

Who owns the published source code provided to allow users to verify safety of a smart contract? This is a philosophical question for some; crypto-anarchists may not want any copyright exerted at all. In fact my quick review of the published code out there shows most people do not include Copyright notices.

This is a mistake, I think. Even if the philosophical perspective is that the Contract owns itself, it should have licenses and notices for protection, unless it would like to be copied freely.

Many contracts will benefit from being the sole destination for a certain activity, (consider an options market -- better liquidity will help create a competitive advantage) and copyright laws may provide some help in keeping other participants from creating rapid knock-offs.

License

You should have answers for the following questions:

Do I want to limit use of this contract in some way? Do I wish to limit copying or other derivative works related to this contract? Do I wish to limit my legal liability in some way by spelling out approved and unapproved use cases?

If yes to any of the above, a license of some sort is probably appropriate.

As a side note, I think it's an interesting idea to have a geo-licensed status for a contract. Many will not want the idea of government licensing to impinge on their smart contracts, and for most legal jurisdictions I am aware of, there is very little clarity as to who might regulate these contracts.

That said, there are some historical blockchain businesses that have chosen to try and comply with geo-licensing. Satoshidice.com shows a 'blocked in US' webpage, but their addresses can be sent to (and thus used to gamble) from anywhere in the world. That sort of 'polite nod' to licensing requirements is an interesting one I could imagine being worthwhile for some contracts or developers of contracts.

Contact

There should be canonical contact information in each contract; probably a URI is the right way to go. This seems so basic, but I haven't seen a single contract publish this information on the API side. (Of course, there is often contact information in the source code).

This would be such simple tooling to add, and really valuable information for wallet UI designers helping users to engage with contracts.

LifeCycle Considerations

On to more technical considerations. Because of the (possibly) immutable nature of these contracts, special consideration needs to be given to their lifecycle.

Birth

You should have a perspective on most of these questions: What happens for setup in the contract? Is there any logic or variable information that needs to be set to something other than default false? Are there any assertions to be made about the blockchain, owner or anything else that would indicate we are ready to go?

What if the contract relies on information from a published RealityKeys contract? Should that contract be tested for existence, or (is this even possible right now?) expected functionality?

What if the contract relies on a certain amount of funding before it can function? Should there be a global state variable that only moves to 'ready' once it's funded? Which functions should check this global state?

NaturalDeath

Birth / Setup is required for testing; essentially, in order to use and play with the contract, the developer has had to think about most of those things. On the other hand, end of contract life is often skipped in the code I'm seeing right now.

This is one of the contract areas that should be considered and reviewed carefully -- leaving the contract in a bad state could easily trap money which cannot be released.

Questions To Answer: Is there a simple function that tests if it's time to die and is safe to die? What happens to the money when the contract ends naturally? Should the contract be left on the chain and allow reporting-type API calls? Should there be a soft / hard death state with some time limits?

VersionUpgrade

If you plan on being a typical (or even very good) engineering team, you're going to need a new version of this contract at some point. (See this post about error rates in Smart Contracts.)

What is the process going to be? Who will decide if it's safe to move to the new contract, or approve the move? Will money be sent along as well when the upgrade happens? Would you like to enable some sort of passthrough calling of functions so that old code still works? (Although note gas costs here. I'm not aware of this sort of passthrough being used yet.)

Update Augur has done a fair amount of practical work and thought work about how this can and should function in a larger heterogenous network of contracts. If you want to search for more, most of the proposed solutions use a registry, with some sort of voting scheme optionally attached. I will post a follow-up on this, because

  • The problem is doubly difficult
  • The current proposed solutions do not seem fully baked to me yet
  • I haven't had a chance to fully engage with Augur to see what they think works and doesn't yet.

Deprecate

Similarly, there may be a period before death when the contract shouldn't be used but is still available to the public. How do you want to approach this in the code? (Maybe you keep charging more and more gas for running the code with some cleverly bad algorithms?)

Do you want to have a time limited deprecation status? Which stakeholders should be allowed to deprecate / undeprecate the code?

MostRecentVersionAddress

If Upgraded or Deprecated, do you want to point consumers to the newest version of the code?

I like this idea a lot, it's a way of using the blockchain as its own reference point rather than requiring users to go elsewhere. This is also the sort of tooling that a wallet could use to add a lot of value. Imagine if addresses at deprecated contracts showed up as 'Old / Deprecated Contract' in the UI.

Oh $#[email protected] Considerations

It's going to happen. Someone will steal your private key. A 75 year old judge may require a contract be turned off and not care that "it's immutable on a blockchain". There is an off-by-one error in your payment code triggered only when the block height is rounded incorrectly during periodic payouts. A trusted group overseeing part of the code has turned into an untrusted cabal.

Not everything can be accounted for, but there is currently almost no thinking put in on the contract side for these eventualities. Like insurance, it's a waste of time and money to get it unless you need it -- then you'll be very, very glad you have it.

I'm not advocating contracts be made more mutable than they should be. There are plenty of use cases for truly unchangeable contracts. But unless you are very, very sure of your code it is worth thinking through what control you want to leave yourself in the future.

UnexpectedBug

What if you just got it wrong, published the contract, and it's out in the wild, people are using it, and something bad has happened?

Should there be a 'pause' option for the owner, or some other set of stakeholders? What should happen to money if there's an unexpected bug that leaves the contract underfunded? What general categories of states could a bug leave us in, and how should each of those be dealt with or remediated?

Pause

Can you ever imagine a time, for any reason, that you might like to pause processing of the contract? How do you want to handle that? Who should have the right to pause it? Should there be time limits on the pausing? Should there be a limit as to how often the code can be paused?

Transfer of Contract Ownership

This is already a pattern in many Smart Contracts, and I think it's sensible. The owner might wish to sell a contract, or more likely upgrade their wallet or address. Keeping private keys around for a decade can be hard, as many Bitcoiners have learned -- this is just an acknowledgment that the blockchain itself lasts longer than most clients.

Other things I haven't seen considered yet for owners of contracts:

Should there be a 'cooling off' period for a new owner? Should there be a transfer confirmation process, and from whom? Should the new owner be required to confirm the ownership, for technical (e.g. yes, someone has control of this address), or political (e.g. no, you can't just "give" me ownership of this assassination market) reasons?

Many blockchain wallet transfers that were problematic would have been much less so if there were a one week waiting period. Such a thing is easy to implement in Ethereum and could radically improve security.

Whitelist

Joey Krug from Augur sent on some comments about whitelisting in response to this post.

In his use case (and I presume how Augur generally thinks of this), it can be useful to have a list of trusted contracts; contracts that are allowed to call certain functions inside your contract.

There are two general times this could be useful as far as I can tell right now -- the first is if you have an interlocking set of contracts, and you don't want to publish them as one giant contract. Perhaps for UI reasons, you want different functions to have different addresses on the blockchain. Then you will want each contract to know what contracts / callers it trusts.

A second use case would be the more general library functionality: it's expensive and a waste to republish library code on the blockchain. But, perhaps the library code moves money around, and therefore needs a high-trust relationship.

So, good questions here: Who is trusted to call each function? Are they all properly secured for that whitelist? What is our facility for updating the whitelist, and/or pointers to the whitelist?

Incentive Compatibility

It's important to think through and make sure that all parties are incentivized to do all required actions.

Often, this isn't possible in the first pass of a defined protocol or set of actions. For example, in an escrow situation, if both parties are honest, then escrow is easy. If, on the other hand, one or both parties are dishonest, creating proper incentives for a transaction to complete is significantly more complex.

Questions to consider: What outside actions are required for this contract to complete? What will happen if someone chooses not to do one? Are there any actions which will have negative economic incentive to complete?

Summary and Recommendations

I will try and keep this post updated as I see new patterns, and hear back from experienced contract authors.

In brief, every contract should have concrete birth, death, change of owner, license/terms and copyright functions.

Almost all should have pause and unexpected bug facilities. The terms and conditions of the contract should clearly spell out what happens in those cases and require the users to agree ahead of time to the plan in the code.

All contracts should have a clear answer to the questions: who can delete, terminate, pause or deprecate this contract?

Will working on answering these, and implementing the answers slow engineering for your version 1 smart contract launch? Yes. But, technical debt in a smart contract can be 100% fatal.

By thinking through answers to these questions, resultant code will be cleaner, better thought-out, and correspondingly less likely to have a catastrophic failure.

As always, send comments -- I'm interested in all feedback. [email protected]

Peter Vessenes

Read more posts by this author.

Subscribe to Peter Vessenes

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!