8 Security Vulnerabilities in Ethereum Smart Contracts that can now be easily avoided!


As Ethereum smart contracts find their application mostly in e-commerce applications, we believe these are more commonly vulnerable to attacks. In these smart contracts, we mainly focus on identifying vulnerabilities that programmers and users of smart contracts must avoid. This post aims at explaining these seven application-level security vulnerabilities and their earlier adopted methods of prevention. Our main focus is on the Solidity updates up to the most recent Solidity v0.6.0 that fix some of these vulnerabilities.

A reentrancy attack can drain a smart contract of its ether, can aid an intrusion into the contract code. When an external call function to another untrusted contract is made and an attacker gains control of this untrusted contract, they can make a recursive call back to the original function, unexpectedly repeating transactions that would have otherwise not run, and eventually consume all the gas.

Figure 1. Reentrancy example — Simple DAO Attack

The reentrancy vulnerability exploitation in the DAO attack (as shown in Figure 1) was accomplished in four steps,

  • Step 1: The Attacker initiates a transaction by calling the Withdraw function of the Victim;
  • Step 2: The Victim transfers the money and calls the fallback function of the Attacker;
  • Step 3: The fallback function recursively calls the withdraw function again, i.e., Reentrancy;
  • Step 4: Within an iteration bound, extra ether will be transferred multiple times to the Attacker.

Re-entrancy vulnerability can be prevented by ensuring that state changing logic is committed before ether is sent out of the contract through an external call. It is also a good coding practice to put any logic that performs external calls to unknown addresses at the last operation in a program’s execution. This is known as the checks-effects-interactions pattern. Another technique is to use a mutex by adding a state variable which locks the contract during code execution, thus preventing re-entrant function calls.

When a function invocation or an ether transfer unexpectedly invokes the fallback function of the callee/recipient. Some of the primitives of Solidity language that causes this are:

  • call used to invoke a function or transfer ether
  • send, used to transfer ether from the running contract to some other contract
  • delegatecall, used to invoke a function or transfer ether in the caller environment
  • direct call (see listing 1)

If an invoked function’s signature does not match with any existing function, then the call results in a call to the recipient’s fallback function.

Solidity has provision for implementing library contracts by using the keyword library. These library contracts are stateless and non-self-destructive. Forcing libraries to be stateless mitigates attacks whereby attackers modify the state of the library directly to affect the contracts that depend on the library’s code. Therefore, when using call, DelegateCall, the call-to-the-unknown attack that may change the state of the victim contract can be prevented by building stateless libraries.

Solidity V0.6.0 splits the logic behind the earlier fallback function into two different functions, one with the fallback keyword and a receive ether function defined using the receive keyword. The receive ether function is implicitly payable and is called whenever the call data is empty. Whereas, the new fallback function, now with the fallback keyword, is called when no other function matches. This fallback function may or may not be payable. If it is not payable then transactions not matching any other function which sends value will revert.

This Solidity update would, therefore, solve the issue of unexpected code getting executed when the fallback function of an external smart contract is called.

Querying data in an Ethereum Blockchain


As you may have come across that Ethereum is a public blockchain network that transacts billions of dollars in value. But you may have not realized that the Ethereum codebase is also used by organizations worldwide to form business blockchain networks. These private Ethereum Blockchain networks are usually permissioned, although separating them from the public Ethereum main-net, they have an option to access the data on the main-net. This adaptation of Ethereum Blockchain Technology requires a good understanding of ways to read and write using Smart Contracts.


Ethereum Smart contracts are mostly developed in a newly designed high-level Turing-complete programming language, Solidity. Solidity has gained popularity as it has been specifically designed to provide the requirements outlined by an Ethereum transaction. These programs are compiled to the Ethereum Virtual Machine(EVM) bytecode, a low-level stack-based language, and then deployed on the Ethereum Blockchain network where it runs on all Ethereum nodes. For instance, the following listing shows a Smart Contract written in the Solidity programming language. The first line of the program declares Solidity’s version used in this Smart Contract. The program contains a constructor to create an instance of the contract, and functions.

Data in Solidity

One can say that Solidity is like other programming languages, with an exception being in running the code and handling data. It is interesting to note that Solidity handles data only in the EVM or the blockchain network and is peculiar about its storage. There are mainly two types of variables in Solidity: state variables and local variables. State variables are responsible for storing the state of a Smart Contract by saving the values in a block on the blockchain. These variables are like a global variable in other programming languages as they are defined in the contract section and are available anywhere in the smart contract. And like local variables of other programming languages, local variables in Solidity are defined inside functions. These variables save their values only during the execution of the function they are defined in.

Data storage in Ethereum Blockchain

Ethereum implements a trie data structure to manage temporary and permanent data. The three types of trie data structures in the Ethereum Blockchain are State Trie, Storage Trie and Transaction Trie.

A mined and confirmed transaction is recorded in the transaction trie. Temporary data like the above mentioned local variables and account addresses are stored in the state trie where it changes and gets updated continuously, thereby updating the state of the complete Ethereum Blockchain.

State trie

There is one global state trie in Ethereum that is constantly updated. It contains a key-value pair, where a key is the address of an Ethereum account and value is the Recursive-Length Prefix (RLP) encoded value of nonce, balance, storageRoot, the hash of an account on Ethereum network.

Storage trie

A storage trie is where all of the contract data is stored. Each Ethereum account has its own storage trie. A 256-bit hash of the storage trie’s root node is stored as the storageRoot value in the global state trie.

Transaction trie

The path to a specific transaction in the transaction trie is via (the RLP encoding of) the index of where the transaction sits in the block. Mined blocks are never updated; the position of the transaction in a block is never changed. This means that once you locate a transaction in a block’s transaction trie, you can return to the same path over and over to retrieve the same result.

Geth and LevelDB to access Ethereum Blockchain Metadata

Go Ethereum is one of the three original implementations (along with C++ and Python) of the Ethereum protocol. It is written in Go, is fully open-source and is available as a standalone client called Geth. Geth downloads the complete Ethereum blockchain and indexes it with some database to enable efficient lookup and retrieval of data or to store the state. Geth uses LevelDB because LevelDB is implemented in GO, has key-value pairs and includes modern data storage (i.e. multiple layers on disk, organized in the background)

However, there are also some limitations to using LevelDB:

  • Ethereum uses hashes that are uniformly randomly distributed identifiers. LevelDB organizes the keys “alphabetically” on disk, therefore, accessing values associated with hashes is very expensive.
  • As long as most of LevelDB can fit into memory, it performs very well, but with increasing disk space, the performance gets degraded.
  • Querying LevelDB returns encoded results because Ethereum uses a “Modified Merkle Patricia Trie” implementation when interacting with LevelDB.

However, to access data stored on the Ethereum Blockchain, there are some existing tools as well. If the data is associated with a transaction, Ethereum (ETH) BlockChain Explorer can be used to view the data. If the data is stored in some smart contracts, the smart contract’s interface can be used to read the data. To write some data onto the Ethereum Blockchain, either sending some ethers to an address with embedded data or interacting with smart contracts on the Ethereum blockchain can enable writing data for you.

Web3.js to access events data on Ethereum Blockchain

Web3.js can be used to effectively query and listen for contract events on the Ethereum blockchain enabling specifications of actions that get triggered when certain criteria are met.

An event listener to upcoming events to specify a callback that will occur when the event is emitted can be used in the following way,

  • For any event, contract.events.allEvents() can be used to specify a callback for all events.
.on('data', (event) => {
.on('error', console.error);
  • For a specific event, contract.events.EventName() can be used to specify actions for specific event types. For example, Transfer:
.on('data', (event) => {
.on('error', console.error);

The output of the above-described event listeners returns valuable data which is described in detail in the table below.


Ethereum Blockchain functioning is fairly straightforward, the different storage space for permanent and temporary data in different tries ensures that data is safe and the data is easily manageable. Therefore, enabling access to the data stored on the Ethereum blockchain safe and easy.