Neosify - Buy, Stake & Earn Crypto
Neosify - Buy, Stake & Earn Crypto
Neosify - Buy, Stake & Earn Crypto
Photo by Jon Cartagena on Unsplash.

Smart Contracts: Don't Reinvent The Wheel

By alexroan | Blockchain Developer | 26 Apr 2020


Always use OpenZeppelin


Don’t get me wrong, writing smart contracts from scratch is a great learning tool. Tasking yourself with creating an ERC20-compliant contract from start to finish is one of the best ways to gain an understanding of the logic behind it.

However, for production applications, don’t reinvent the wheel.

Libraries like OpenZeppelin are scrutinized by the Ethereum development community at large. They’re continuously being updated and reviewed. They’re also publically accessible and easy to use. It doesn’t make sense to create your own when libraries like this exist.


Importing OpenZeppelin

To install OpenZeppelin into your project, run the following command:

npm install @openzeppelin/contracts --save

This will download all smart contracts into node_modules/.

Once installed, you can import smart contracts into your own. This is an example of importing the OpenZeppelin ERC20 token contract in a smart contract:

pragma solidity ^0.5.5;
import "@openzeppelin/contracts/token/ERC20/ERC720.sol";

contract MyContract is ERC20 { ...

Here are some useful Token, Math, Utils, and Ownable contracts from OpenZeppelin you can easily implement in your projects.


Tokens

ERC20

There are six publically available functions that ERC20 contracts need to implement, as well as two events. By importing OpenZeppelin’s ERC20 contract, you don’t need to implement any of these yourself.

pragma solidity ^0.5.5;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol";

contract MyERC20 is ERC20, ERC20Detailed {
  constructor(string memory _name, string memory _symbol, uint8 _decimals) public ERC20Detailed(_name, _symbol, _decimals) {
  
  }
}

ERC20Detailed is used to initialize the name, symbol, and decimals for the token, but they aren’t necessary if your project doesn’t require a named ERC20 token.

ERC721

Since ERC721 tokens are unique, a struct and an array of structs are commonly used to store them.

pragma solidity ^0.5.5;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";

contract MyERC721 is ERC721 {

	struct Person {
		string name;
		uint8 age;
		uint8 height;
	}

	Person[] public people;

	function newPerson(string memory _name, uint8 _age, uint8 _height, address _to) public returns (uint)
	{
		uint id = people.length;
		people.push(Person(_name, _age, _height));
		_safeMint(_to, id);
		return id;
	}
}

Instead of implementing all nine functions and three events, this contract inherits those and exposes the ability to create new Person tokens.


Math

SafeMath

In most modern programming languages, safety in arithmetic operations is accounted for, so little thought goes into their implementation. However, in Solidity, overflows and underflows present a security risk.

SafeMath is a library that ensures safe arithmetic operations by reverting the transaction if the bounds of an integer data type are exceeded.

pragma solidity ^0.5.5;

import "@openzeppelin/contracts/math/SafeMath.sol";

contract BasicSafeMath {

  using SafeMath for uint;
  
  function doSomeMath(uint _a, uint _b) public returns (uint) {
    return _a.sub(_b);
  }
}

The using statement indicates to the compiler that the contract is using functions defined in SafeMath for uint operations. Instead of using arithmetic operators (+, -*, /%), use the functions add()sub()mul()div(), and mod().


Utils

SafeCast

Casting uint variables for an integer of a smaller size may present an overflow risk. Use SafeCast to cast larger integer data types to smaller ones (i.e. uint256 to uint8).

This can be used in tandem with SafeMath, which performs the arithmetic operations on uint256 only.

 

pragma solidity ^0.5.5;

import "@openzeppelin/contracts/math/SafeCast.sol";

contract BasicSafeCast {

  using SafeCast for uint;
  
  function castToUint8(uint _a) public returns (uint8) {
    return _a.toUint8();
  }
}

Ownership

Ownable

Access to certain functions in a smart contract sometimes needs to be restricted so that only the owner of the contract can successfully invoke them. A common pattern is to use the onlyOwner modifier in function definitions. Instead of coding this pattern yourself, OpenZeppelin’s Ownable contract does this for you.

pragma solidity ^0.5.5;

import "@openzeppelin/contracts/ownership/Ownable.sol";

contract OwnableContract is Ownable {

  function restrictedFunction() public onlyOwner returns (uint) {
    return 99;
  }

  function openFunction() public returns (uint) {
    return 1;
  }

}

Conclusion

Always use libraries for the most basic implementations of coding standards. At this point, the best in the industry is OpenZeppelin. It’s safer, quicker, cleaner, and easier than reinventing the wheel yourself.


Learn More

If you’re interested in Blockchain Development, I write tutorials, walkthroughs, hints, and tips on how to get started and build a portfolio. Check out this evolving list of Blockchain Development Resources.

If you enjoyed this post and want to learn more about Smart Contract Security, Blockchain Development or the Blockchain Space in general, I highly recommend signing up to the Blockgeeks platform. They have courses on a wide range of topics in the industry, from Coding to Marketing to Trading. It has proven to be an invaluable tool for my development in the Blockchain space.

 

How do you rate this article?

38


alexroan
alexroan

Blockchain Developer


Blockchain Developer
Blockchain Developer

Tutorials, walkthrough, hints and tips on Blockchain Development for all levels of expertise.

Send a $0.01 microtip in crypto to the author, and earn yourself as you read!

20% to author / 80% to me.
We pay the tips from our rewards pool.