Creating your first Token from scratch

Leandro Dardick
SOUTHWORKS
Published in
11 min readMay 18, 2021

If you ever intended to start reading about development in Ethereum you might have crashed into a large pile of words that sounded unfamiliar to you.

Let’s start from the ground. As we discussed in our previous article, the programmable nature of the Ethereum Blockchain is made possible by Smart Contracts. Those contracts are developed in a Turing-complete languages such as Solidity or Vyper, and runs in a Ethereum Virtual Machine (Usually referred as EVM) by the nodes.

The code for the Smart Contracts is translated into it’s bytecode equivalent and included in the blockchain by transactions. When deployed on the network, the contracts have an address which allows the clients to connect to them.

Whenever a user wants to call a method in a Smart Contract, a transaction should be emitted. Each transaction has a cost, called Gas Money, which is the incentive given to the people maintaining the network nodes to keep it working. Even though you may have seen ETH or Ether as the currency used for Ethereum, the reality is that the ETH is a large denomination and used in limited cases. To talk about gas money, you will see that we usually refer to Wei instead, being 1 ether equal to 1018 Wei.

Any deployed contract can be seen by browsing the Blockchain. Etherscan is a popular tool that provides a user-friendly interface to do that. For example, CryptoKittie’s Smart Contract can be seen in this link. At the same time, most of the major project open-sources their contracts available in public repositories.

Choosing a Development Suite

The first thing you must do before writing a single line of code is to choose the development environment of your choice.

Here is where things starts to get complicated. As expected, several development tools appeared Ethereum ecosystem over the years: Hardhat, OpenZeppelin, Truffle, Embark, Brownie and Etherlime to name some.

When we started our first projects one of the things that we had to ask ourselves was what were we expecting for the frameworks. At that point we had to decide, and after an extensive research we ended up leaning to Hardhat as it had all the things we needed plus seemed to be the most popular choice at this time.

Hardhat granted us:

  • The possibility configure the connection to multiple networks
  • A local network to run and test the contracts locally
  • Extended debugging tools
  • A testing framework
  • The support to run automated scripts from the CLI
  • A rich and healthy plugin ecosystem

As an advantage, Hardhat did not came with a static set of tools but instead allowed us to create our own recipe:

  • We chose Typescript over JavaScript to be type-safe
  • We chose Ethers over Web3 as interface to interact with the network
  • We chose Waffle with Chai matchers for testing, what allowed us to work with the same set of tools we were already familiar with

In addition, the npm ecosystem used by HardHat gave us the chance to build our own automation scripts to be used in the development.

We won’t go into details on how to set up the project boilerplate as it’s extensively defined in the official documentation.

It’s important to say that there’s no one-fits-all choice. You should evaluate all the available options and select the one that fit your needs, mind that what could be ideal for one project may not be for other.

Selecting the Base contracts

OpenZeppelin maintains a series of base contracts and presets for the most popular ERC’s that can be used as the supporting stone for our project.

Once you have the framework of your choice, the next step is to look for base contracts that best suits in your project.

A good starting point are the OpenZeppelin presets. Those can be found in the official website, and come in various flavors, for example:

  • ERC20PresetMinterPauser preset models the creation of an ERC20 token adding access control for minting tokens and pausing.
  • ERC20PresetFixedSupply preset models an implementation of a pre-minted, fixed supply ERC20 token. In this case, the access control is not implemented as all the tokens are previously minted.
  • ERC721PresetMinterPauserAutoId preset models the implementation of an NFT (ERC 721) with access control and Token ID auto-generation.

Check the official website for the full list of presets.

In case the predefined presets does not meet the requirements, the base contracts on the official GitHub repository can also be used as starting point. Most of the base contracts are expected to be used via inheritance. Check the official documentation for more details.

Those presets and base contracts allows the developers to avoid worrying on the underlying implementation and focusing on what’s really important: What makes the implementation unique.

Handling Upgradeability

One of the things that every developer will ask himself at some point is how to update the contracts once they are deployed. The short answer is that you can’t, but there are some tricks that allows that.

The hardhat-upgrades plugin (as well as other similar ones) came to the rescue. The idea is very straightforward: Instead of deploying the contract that contains all the logic and connecting to it, the plugin will allow deploying a contract that has a reference to the actual contract and will act as a proxy.

Using proxies to grant upgradeablity

This proxy contract exposes a method to change the address to the actual one allowing the owner of the contract to deploy a new contract and change the address in the proxy. Given that one of the blockchain features is the immutability, the old contract become outdated and will live in the blockchain, forever unless its self-destructed.

Upgrading contracts by replacing the reference on the Proxy contract
Smart Contract Upgrade process

And that takes another issue into discussion. If the original contract held the storage of the information and we changed the contract we should start from scratch and lose everything, and that’s not acceptable at all.

This could be easily solved in two ways:

  • Storing the status in a separate contract or even in the proxy contract
  • Migrating the data
State management using upgradeable contracts
Internal State management using upgrades

But that’s not everything. Remember that we said that the contracts could be used as escrow between two untrusted parties? Let’s make an exercise:

Let’s suppose that someone that I don’t know or trust asked me for 100 dollars with the promise or returning me 200 the next month, I would definitely say no.

Let’s change the example a bit, and now suppose that the other person created a Smart Contract for that, and that contract did not have any upgrade mechanism. As the contract would ensure that the other person re-payed me what he promised, I would surely accept the deal, there is no way he can avoid paying back!

Okay, let’s change the example once again and suppose that now the contract it’s upgradeable and the other party can change the behavior discretionally. This takes me back to the first situation as there is nothing that prevents me being scammed.

Why are we saying that? Just mind that the power of the Smart Contracts lies on the fact that they are auditable and enforce rules, and that’s where the trust relies. If those rules could be unilaterally changed by the issuer, the trust relationship is broken.

Implementing upgrades on Smart Contract is possible, but at the same time can be dangerous for the trust and may be the difference between being popular or being buried.

Using utilities and libraries

As we said before, OpenZeppelin does not only maintain base contracts and presets, also maintains utilities and libraries that can be used for some of the most common requirements on Ethereum applications.

Among others:

  • Utilities to deal with common limitations of Solidity on data structures (EnumerableSet, EnumerableMap, Address)
  • Libraries to perform Safe Math operations (e.g., Catching divide-by-zero, overflow, underflow or truncating errors)
  • Utilities to allow dealing with common attack vectors (ReentrancyGuard)
  • Utilities to halt the contracts activity by enabling the owners to pause or unpause them. (Pausable)
  • Utilities to control the access to contract’s methods by implementing roles (AccessControl)

You can check the full list of utilities in the official documentation

Even if you are a skilled developer, using those utilities make sense as they are reliable and were extensively audited.

Hardening the solution with audit Tools

A lot has been written about hacker attacks on Blockchain, and there are even lists with known attacks!

If you develop a Token, regardless of which type you chose, you’ll be dealing with valuable assets (or even money!), and that can be terrifying.

As a new developer dabbing in the Ethereum world, you may use some help. Fortunately, there are some Open Source tools that can make your life — at least a bit- easier:

  • Slither is a tool that can perform security audits as well as give some advices on the styling of your code. The tool can give suggestions on how to deal with some of the most common attack vectors.
  • Solhint is a linting utility for Solidity that provides security and style guide validation.
  • Echidna is a contract-fuzzer that can be used to automatically create assertions and evaluates the contract to detect violations.

There’s a lot of information, but, luckily, all those tools (plus others) are available by just using the eth-security-toolbox Docker image, without having to worry about installing them and wasting time dealing with dependencies.

Running and testing the solution locally

Up to this point, you are familiar with the base contracts, presets, tools and understand how to create your own tokens just by writing a few lines of code, great!

Now it’s time to test your changes. As said before, the contracts should be deployed to the blockchain for them to be accessible, for this reason, we need a network where to test them.

As a bit of context, there are different type of networks. At the highest levels, they are categorized as Local or External, being local the ones that are running locally and external the ones that runs anywhere else.

At the same time, the externals could be categorized by their access, being Public the ones that anybody can access and Private the ones whose access is restricted.

Finally, the public networks can also be divided into Main and Test nets, being the Main Nets used for production and Test Net to test the contracts.

One of the things that describes the Main Nets is that the Wei have value, while in the other type of networks are worthless. In case of the Test Nets, the money can be obtained by just putting your address in a Faucet (For example, the Ropsten Faucet), and, in case of the local networks, the wallets can be funded discretionally by just setting up the network.

Normally, you will use a local network for testing your contracts locally, but at some point, you will need to evaluate which network type fits better for your requirements, minding that if you plan to work with money, you will have no option but to go for a Main Net.

Going back to the original point, there are many ways of setting up a network for development: There are Docker images to set up the network in a few clicks and even tools like Ganache that lets you fire up a personal network.

Once again, luckily, Hardhat comes to the rescue. Hardhat can set up a local network and create some test addresses with funds to test our contracts with a single command. You can check the documentation on their website.

Integrating the Smart Contracts with a UI

At some point you will be adding your solution a nice UI so the users can interact with the contracts in a user-friendly way.

As we said, the communication with the contracts is made by issuing transactions and those transactions should be added on the mempool by someone with access to the network to be later included in the Blockchain by a node. Usually, to allow external applications to connect to the network, an RPC Endpoint is exposed by a node on the network. That endpoint will behave as a proxy to allow the users to sign transactions and send them to the network.

There are two de-facto standards in terms of libraries to interact with RPC endpoints: Web3.js and Ethers. Both libraries expose simple interfaces allowing the developers interacting with the network effortless.

Browser Wallets are browser extensions used to connect web applications to the network. Those extensions will allow the user to configure their wallets and the settings to connect the desired network and inject pre-configured web3 objects into the global JavaScript namespace. This way, the developers can use the injected objects to send transactions to the network. Refer to this video for details on how browser wallets work.

There are multiple browser-based wallets, and they perform very similarly, but MetaMask is the most popular one.

But there is one catch, and it’s that setting up MetaMask may not be easy for the non-tech-savvy users (and even more if connecting to a network other than Ethereum MainNet) as it requires a basic understanding of the blockchain technologies. To deal with that, there are the so-called hosted-wallet services that will take care of the technical part of managing the wallet, providing a secure authentication mechanism and, once again, injecting a Web3 object just as MetaMask does.

This may be ideal for casual users but using them exposes a huge risk: As the proof of ownership for the addresses is made by being the only person with the Private Key, if the hosted-wallet service is compromised, the funds in the user’s wallets will be in danger too. At the same time, as other services, they are usually paid and that might make them not suitable for some projects.

But what happens if we wanted to support the best of the two worlds and let the users decide about their security? Well, there is where services like Web3Connect comes to the rescue. Those libraries allow the developers support multiple browser wallets and hosted wallet services by hiding the complexity and exposing a common interface.

Automating Tasks

Apart from a nice UI, there will probably be some administrative actions that you would want to automate or plug in into pipelines.

Among others, automated tasks could be created to:

  • Deploy or upgrade contracts
  • Pause or unpause the contracts as needed
  • Manage roles on your application
  • In case of Contract implementing ERC20 or ERC721, for minting
  • In case of Contracts modelling other flows like Auctions or Selling, automating withdrawals

Those tasks can be run using a CLI using the most popular terminals, which allows the developers to integrate them to other processes as needed.

Of course, in the case of the above-mentioned actions, the sender of the transactions sent to trigger those actions will be validated and thus, the tasks should be run using a sender address with permissions. Integrating the tasks allows the developers to avoid worrying about sharing the Private Keys needed as no-one will need to have access to them.

Once again, Hardhat provides an interface to create and run automated tasks. Refer to the official documentation for more details.

Wrapping up

We went through a lot during this article, and hopefully, you were able to grasp a new concept or two, but we wanted to give some closing words for anyone reading this article.

As said in the introduction, the goal of this article wasn’t to go deeply into technical details, instead we wanted to show that as opposite as it might seem, the Ethereum ecosystem is actually very friendly for new developers and that the community did an exceptional job creating tools and assets that makes things much easier.

Once again, when implementing tokens, the complexity is not in the creation of the tokens, but in what give them value.

As in everything in life, there is no silver bullet. There is no toolset that will fit the needs of all projects. Our goal was to give you kickstart that will help you choose your own path.

--

--