avatarAlex Roan

Summary

This article provides 15 tips for writing better smart contracts, including defining the purpose, checking if it has been done before, naming the contract, choosing the development environment, deciding if it's a standalone contract, choosing the Solidity version, avoiding arithmetic operators, restricting access to some functions, sending value safely, reducing complexity, saving space, testing thoroughly, showing others, considering how it could be exploited, and making sure it works.

Abstract

The article emphasizes the importance of defining the purpose of a smart contract before starting and checking if it has been done before to avoid reinventing the wheel. It suggests naming the contract clearly and succinctly, choosing a development environment, and deciding if it's a standalone contract or part of a larger project. The article also recommends choosing the latest stable version of Solidity and avoiding arithmetic operators to prevent vulnerabilities. It suggests restricting access to some functions, sending value safely, reducing complexity, saving space, testing thoroughly, showing others, considering how it could be exploited, and making sure it works as intended.

Opinions

  • The article suggests using Openzeppelin's SafeMath library for unsigned integer operations to avoid vulnerabilities.
  • The article recommends using the onlyOwner pattern to restrict access to some functions.
  • The article suggests using transfer() instead of call() when sending Ether or ERC-20 tokens to other addresses.
  • The article recommends using off-chain computing to take some load off the blockchain application.
  • The article suggests using Openzeppelin's SafeCast library to cast integer values down to smaller data types.
  • The article recommends testing on as many Testnets as possible to mimic the Mainnet environment more closely.
  • The article suggests using auditing services and static code analysis tools to consider how the smart contract could be exploited.
  • The article recommends writing an application front end to turn the smart contract into a full DApp.

15 Tips to Write Better Smart Contracts

Start by defining the purpose and end by making sure it works

Photo by Moose Photos from Pexels

1. Define the Purpose

Before starting, make sure you have a clear understanding of what your smart contract is supposed to do. What value does it add? How should it be used? Consider the question of whether or not it even needs to be a blockchain application. Would it be better implemented on more well-established technology platforms?

Have a clear view of the purpose of your smart contract.

2. Check if It Has Been Done Before

Never spend the time rewriting something that already exists. If what you’re trying to create is a different flavour of an existing concept, consider extending work that has been done by others.

Don’t reinvent the wheel.

Openzeppelin provides a library of contracts that implement EIPs like ERC-20, and ERC-721. Utilise these by extending their functionality instead of writing your own from scratch.

3. Name It

Having a clear purpose should make naming your smart contract easy. If you have experience developing in object-oriented languages, name it as you would a class.

Names should be clear, descriptive, and succinct. It should have as few words as possible, ideally one or two. It should describe what the contract is, what it does, and indicate what it’s responsible for.

4. Chose Your Development Environment

If you’ve had experience developing software already, you’ll likely have a preferred IDE to code in. Multiple IDEs support Solidity development. My favourite is VS Code, a free text editor created by Microsoft, with the Solidity extension.

If you’re less experienced and don’t want to have to worry about setting up your environment, Ethereum provides a great online IDE called Remix. It allows you to start coding, compiling, and deploying immediately.

5. Is It a Standalone Smart Contract?

Sometimes smart contracts get very long and very complicated. If your contract has so many responsibilities that the name doesn’t describe everything it does, consider separating concerns and using multiple smart contracts.

If you expect your project to span across multiple smart contracts, consider using Truffle Suite as the framework for your project. Truffle makes it easy to write DApps on top of your contract.

6. Chose Solidity Version

Find out the latest stable version of Solidity and familiarise yourself with its syntax. If you’re extending libraries, make sure your chosen version isn’t ahead of the version that the libraries support.

For example, Openzeppelin contracts library version 0.2.5 supports Solidity version 0.5.5, but not 0.6.x.

7. Does It Do Any Maths?

If you expect your smart contract to perform mathematical calculations, refrain from using arithmetic operators like plus(+), minus(-), multiply(*), divide(/), and modulus (%). Without proper checks, they have the potential to introduce underflow and overflow vulnerabilities.

Use Openzeppelin’s SafeMath library for unsigned integer operations.

8. Restrict Access to Some Functions

Most smart contracts will need access restrictions on functions that only the owner of the contract should be able to invoke. A commonly used pattern for this is the onlyOwner pattern. This is where a custom modifier requires that the caller of the function is equal to the owner address.

To save writing your own logic for this, Openzeppelin provides a contract called Ownable, which you can extend in your code.

9. Send Value Safely

If you expect your smart contract to send Ether or ERC-20 tokens to other addresses, you must consider the vulnerabilities that can introduce. Reentrancy attacks are well known throughout the industry due to high-profile hacks over the past few years.

Always use transfer() instead of call() when sending Ether, and never assume that address you’re sending to is a good actor.

10. Reduce Complexity

Functions should be concise and self-explanatory. Any functions which look too large, or perform nested loops or recursion should be revisited. More computation means more gas, meaning it costs more to perform those functions.

Consider off-chain computing to take some load off your blockchain application. For example, decentralised exchanges use off-chain order filling algorithms to fill orders, since the algorithm is quite complex. Once an order is filled, the settlement is performed on the blockchain.

If reducing complexity is too difficult, consider the possibility that blockchain may not be the ideal solution to your problem.

11. Save Space

Are there any variables that will never fill their data type size? If so, you should be able to reduce the amount of space your smart contract uses by changing the data type.

If all of your integer values are uint data type, but some only ever reach a maximum value of 100, consider uint8. It has a maximum value of 255.

Openzeppelin provides a library called SafeCast that casts integer values down to smaller data types.

12. Test Thoroughly

Make sure you write as many tests as possible. Account for every possible scenario occurring and test every code path to ensure the expected result happens every time.

As well as testing on your local blockchain, deploy and test on as many Testnets as possible. These mimic the Mainnet environment more closely, so are a better representation of how your app will perform once live.

13. Show Others

Making code available for others to see is valuable.

Having a fresh set of eyes, not hampered by tunnel vision, often catches bugs that slip through the developer’s net. Second opinions and expert advice are very valuable tools, so use them where possible. They have the benefit of making your more critical of your work before you allow yourself to show it to others.

You could also write thorough documentation or articles about your smart contracts to explain them to others. This will help them understand the underlying concepts of your work and will aid them in hunting any bugs you might have introduced.

14. Consider How It Could Be Exploited

Think like a bad actor.

Think about how you would try to exploit the smart contract if you wanted to steal its funds or render it useless. Ask yourself where your smart contract is vulnerable and how you can mitigate the risks.

Use auditing services and static code analysis tools if necessary.

15. Make Sure It Works

Finally, does it do what you expect it to do? Ask yourself if it serves the purpose you envisaged when you set out from the beginning. Can you write an application front end, turning your smart contract into a full DApp?

Blockchain
Programming
Ethereum
Cryptocurrency
Smart Contracts
Recommended from ReadMedium