Tutorial: Write safe smart contracts with OpenZeppelin

How to use the OpenZeppelin smart contract framework with Superblocks to #buidl secure DApps.

When it comes to learning how to program on blockchain, we are all a little bit in the dark. It’s hard to get the hang of Solidity, this fairly young programming language. And it’s also a bit tricky to understand the best practices and the smartest approach to developing smart contracts. We will make tutorials to make sure you have both the tools and knowledge to make secure and well running DApps.

Yupp, we love OpenZeppelin. ❤

Why this focus on security when it comes to blockchain development? Well, once deployed to the blockchain, your code stays engraved on the chain forever. Therefore you have to be sure that what you decide to deploy is well tested and bug-free. Programming mistakes can be costly, see Dao hack. Back in 2016, there weren’t any engineering best practises/standardization/ frameworks available in this industry to help you get started on your development journey.

The Open Zeppelin library has been created to tackle this problem. It is is a battle-tested framework of reusable smart contracts, which have been created and curated by the Ethereum community.

Nowadays, the Open Zeppelin library serves as one of the cornerstones of Solidity smart contract development and fortunately using OpenZeppelin smart contracts with Superblocks is so easy that you can do it in your sleep.

Don’t worry, I will show you how to do it, but first, let me show you a real example of why we would need it in the first place.

The first step is to create an empty project in Superblocks.

Start buidling your DApp!

If we go to the contracts folder we will see a pretty barebone smart contract called MyContract.sol. Clicking on it reveals its precious source code. 😍

The basic starting point for writing Solidity.

Although it’s a pretty basic smart contract, it is a perfect way to get started. Let’s transform it into a simple calculator with only one function: addition. Let’s add the following function and variable to the Solidity file:

uint public sum;
function add(uint number1, uint number2) public {
sum = number1 + number2;
}

sum is a variable that stores the result of our addition.

add is just a super simple function that takes two unsigned integers as an input (stored on 256 bits by default) and adds them together. It couldn’t get any simpler than this!

Your first lines of DApp buidling

Don’t forget to save using the red floppy icon and let’s deploy our smart contract!

Click on ‘Deploy’ and we will be greeted with a compilation and a deployment success message. Awesome! So much green text!

MyContract.sol

By clicking on ‘Interact’, we will have the option to play around with our newly deployed calculator.

In the interact menu, we will see our add function and sum variable. If we click on the green icon sum, we will see that its current value is 0.

Running our add function with two arguments we will have a transaction hash in return. If we click on sum now, we will see that its value has been updated to the sum of our two arguments.

Interact directly with the deployed contract.

Great! Our super simple smart contract is functional and works perfectly. OR DOES IT?

Let’s test our contract with different arguments. How about adding

115792089237316195423570985008687907853269984665640564039457584007913129639935

and 1?

Add your arguments.

What the heck? We get a 0? How is it even possible? Where did our huge number go?

Do you remember when I earlier said that our integer numbers are stored on 256 bits? Well, turns out our large number is no ordinary number. It is the largest representable integer in Ethereum (²²⁵⁶ -1). So when adding any value to it, the result “overflows”. This is similar to what happens when an old-school car odometer cannot hold numbers larger than ‘999,999’. It simply rolls over and you are back to square one. Now you can sell your old car as “brand new, straight from the factory”. 😃

Your old car becoming brand new.

It can be amusing when it happens in real life, but would you be as humored if one of the variables in your smart contract, that handles a few million dollars, would overflow? Probably not!

Fortunately, it can easily be prevented. By using the import feature in Superblocks, you can build on top of existing smart contracts, so you don’t have to reinvent the wheel. A reliable source of smart contracts is the OpenZeppelin project, which can help developers focus on building their own thing. Just like Superblocks does. 😉

It is very straightforward to use the OpenZeppelin library with Superblocks. Just right-click on any folder (with the exception of ‘app’), and select ‘Import’ from the dropdown menu. On the next screen, you can see a list of smart contracts that can be imported (organized in folders). It is important to note that the file will be imported into the folder that you have clicked on! To find out more about our import functionality click here.

In the ‘Import a Smart Contract’ modal select the SafeMath.sol file from the math library and hit the ‘Import’ button! The smart contract will be imported into your selected folder (in our case it is the contracts folder).

SafeMath.sol

You should be able to see the newly created math folder in your file browser. If you do, you are ready to use the SafeMath library.

The SafeMath library was created to make mathematical operations safer and more reliable with Solidity. It can be used to defend against the previously shown integer overflow issue.

To use SafeMath in our project, we should open our smart contract (MyContract.sol in this example), carry out the following modifications:

In order to import the SafeMath.sol from our math folder add:

import “./math/SafeMath.sol”;

In our contract field we should add:

using SafeMath for uint;

This means that the functions contained in our SafeMath.sol library are added to objects of type uint, which we will understand clearly in the next line of code we are adding.

We should declare a new function that takes advantage of SafeMath. To do this add the following:

function safeAdd(uint number1, uint number2) public{
sum = number1.add(number2);
}`

The new safeAdd function takes two arguments, similarly to our previously defined add function. The difference comes from how we assign our value to the sum public variable.

Instead of using a mathematical function add to sum our numbers, we call a function defined by SafeMath on our uint type. As number1 is of type uint, the add function will be defined.

The final code should look something like this:

Your final code

If we navigate to the math folder and open SafeMath.sol, we can scroll to the bottom, where the add function is defined. Taking a look at the SafeMath library, we can see how this addition is exactly defined.

Check for an integer overflow to revert the operation.

So in essence, all the function does is check for an integer overflow and reverting (canceling) the operation, if an overflow is detected. This way the operation never completes, thus protecting us from any malfunction in our code.

Now that we know the inner workings of the SafeMath library, it is time to try it out as well.

Let’s deploy our smart contract, where we have defined the safeAdd function. At the interaction screen, we will find safeAdd in the bottom. Let’s test it first with two smaller numbers.

Testing safeAdd with the numbers.

Adding 1 and 3, in our example yields the sum of 4, which is correct. This means that safeAdd works indeed. Let’s test it again with our magical number. In case you forgot, the huge number we have previously used was:

115792089237316195423570985008687907853269984665640564039457584007913129639935.

After carrying out the operation, we can inspect our sum variable and we see that our previous sum (4 in this example) hasn’t changed at all. How could it be?

Opening the ‘Transactions’ tab on the right reveals that an error has occurred during the execution of our last function call. This is hinted to us by the red square in the upper-right corner of the transaction. As we can see, all previous transactions have been successfully executed, hence the green square.

This means that whenever an operation would be executed that would result in an integer overflow, our safeAdd function can prevent it. This way our smart contract is safe and we don’t have to worry about an integer overflow happening again.

Thank you for reading this article. I hope that you found it to be useful. 🙌

Janos Gulacsy
Full stack Developer
janos@superblocks.com

Superblocks
Twitter

LinkedIn