Is It Safe To Store Private Data On Smart Contracts?

How private variables in smart contracts can be exposed

Senudajayalath
Coinmonks
Published in
4 min readFeb 10, 2023

--

Use cases for blockchain are growing day by day. Therefore, various breeches due to the exploitation of the capabilities of blockchain technologies or breeches due to the ignorance of developers have been common news during the past couple of years. As developers, we should be careful how we build applications on top of blockchain protocols. A very common point most developers tend to overlook on is security concerns when storing data inside smart contracts. Let us take this common use case as an example.

Photo by Annie Spratt on Unsplash

Let us assume that a medical insurance agency wanted to build a fully distributed application using blockchain principles. This application would need to store personal information such as previous medical histories of each person. These data are really personal, and should by no means fall into the hand of any third party. One option developers taking on this task will have is to store data in smart contracts using state variables. Let us evaluate if this would be the best thing to do.

First let us see what variables are in Solidity. This is how we declare a variable in Solidity,

<type> <access modifier> <variable name> ;

eg:
uint8 public number

There are three types of access modifiers in Solidity: public, private and internal. The difference of each type is a whole new topic and will be discussed in another article. For now, let’s consider what public and private access modifiers are, and how they differ from each other on a high level basis.

Public variables allow other contracts to read the stored value, while private variables prevent other contracts from accessing it. Coming back to the previous problem, can developers securely store private data like past medical records in private variables? It is obvious that public variables won’t do the job. But going by the definition of private variables in Solidity, it looks like private variables would be ideal for the job.

This is where most developers get it wrong. Although private variables prevent other smart contracts from accessing the stored value, it does not guarantee that the variable cannot be accessed from the outside.

Before we get to that let us see how data is physically stored in smart contracts.

Data is stored sequentially in slots, in order of declaration.

Storage is optimized to save byte space. So if sequential variables will fit in a single 32-byte slot, they will share the same slot, indexing from the least significant bits (from the right).

A visualisation of how Ethereum storage looks like and how space optimization is done:

Photo by 0xSage on Medium

Since we got that cleared out, let us take the below example and see how a person can exploit a private variable to see what it has stored.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Vault {
bool public locked;
bytes32 private password;
constructor(bytes32 _password) {
locked = true;
password = _password;
}
function unlock(bytes32 _password) public {
if (password == _password) {
locked = false;
}
}
}

In the above smart contract, locked and password are two state variables. Locked is a public variable and therefore we can access that variable from the outside. On the other hand, password is a private variable.

Conveniently, Web3 allows you to reach into contract storage via:
await web3.eth.getStorageAt(contractAddress, slotNumber)

According to the above definitions we can read what is stored in the password variable via:
await web3.eth.getStorageAt(contractAddress, 1)

and locked variable via:
await web3.eth.getStorageAt(contractAddress, 0)

NOTE — Irrespective of a variable being private or public web3.eth.getStorageAt can be used to read the stored value.

From the above example you can see how easy it is for an outside entity to expose private variables in smart contracts.

Key Security Takeaways

It’s important to remember that marking a variable as private only prevents other contracts from accessing it. State variables marked as private and local variables are still publicly accessible.

To ensure that data is private, it needs to be encrypted before being put onto the blockchain. In this scenario, the decryption key should never be sent on-chain, as it will then be visible to anyone who looks for it

Resources

  1. Web3 GitHub Repo — https://github.com/web3/web3.js

New to trading? Try crypto trading bots or copy trading on best crypto exchanges

--

--