Off-Chain Data Storage: Ethereum & IPFS

Saving on gas

Adil H
Adil H
Oct 17, 2017 · 3 min read

The Ethereum gas costs issue

Most Decentralized Apps running on the Ethereum Platform need to store/retrieve data, just like conventional or “centralized” apps do using PostgreSQL, MongoDB, Redis, etc. The EVM (Ethereum Virtual Machine) does indeed allow us to save variables/state in permanent storage. Let’s look at this simple Solidity contract:

pragma solidity ^0.4.17;contract Database {
    bytes x;    function write(bytes _x) public {
      x = _x;
    }
    
    function read() public view returns (bytes) {
      return x;
    }
}

I’ve deployed this contract on test net and generated 1024 of random bytes using then stored 1kB of data using the write function. The resulting transaction can be seen here :

The Gas used amounted to 754,365 @ 20Gwei Gas price = 0.0150873 Ether. At the time of writing this post (Oct 17, 2017) the Ether price is currently 328.79 USD/ETH. So storing 1kB of data would have cost $4.96 to run on the Ethereum Main Net. That means ~ 5 Million USD / GB !

Alternatives

Saving a few bytes to the EVM is ok but for larger chunks of data the costs are probably too high for most projects. One solution is to modify our data storage strategy and save the data off-chain (as opposed to the on-chain approach we took above). There are multiple off-chain storage options: and are 2 popular ones. I’ll use IPFS in this post but Swarm works equally well.

Enter IPFS

Looking at the on IPFS :

InterPlanetary File System (IPFS) is a designed to create a permanent and decentralized method of storing and sharing files

IPFS allows p2p storage and we can use it as a distributed file system to store data.

Low Cost Data Storage Strategy

Saving data on IPFS provides a unique hash. Instead of storing the data on the contract, we’ll only store the hash on the contract and then we can use the hash to retrieve the data.

In production we’d need to create our own IPFS node, but provides a node for developers which we can use for free.

Here is a js snippet you can try out on to save data to IPFS :

const IPFS = require(‘ipfs-mini’);
const ipfs = new IPFS({host: ‘ipfs.infura.io’, port: 5001, protocol: ‘https’});
const randomData = “8803cf48b8805198dbf85b2e0d514320”; // random bytes for testing
ipfs.add(randomData, (err, hash) => {
 if (err) {
   return console.log(err);
 }
 
 console.log(“HASH:”, hash);
});

this should return the hash “Qmaj3ZhZtHynXc1tpnTnSBNsq8tZihMuV34wAvpURPZZMs” which we can use to query our data:

const IPFS = require(‘ipfs-mini’);
const ipfs = new IPFS({host: ‘ipfs.infura.io’, port: 5001, protocol: ‘https’});
const hash = “Qmaj3ZhZtHynXc1tpnTnSBNsq8tZihMuV34wAvpURPZZMs”;
ipfs.cat(hash, (err, data) => {
 if (err) {
   return console.log(err);
 }
 
 console.log(“DATA:”, data);
});

and this should return our data : “8803cf48b8805198dbf85b2e0d514320”

One remark is that the hash string size is independent of the data size, which means we can store large data chunks or files on IPFS (I couldn’t find a current size restriction) without increasing our Ethereum transaction costs !

I’ve used our previous contract to store the IPFS hash generated above :

The gas usage has decreased to 40,907 @ 20Gwei Gas price = 0.00081814 Ether = 0.27 USD

We now have a much more acceptable storage cost and it should be pretty much constant independently of what we’re storing on IPFS !

Example Project: Stone Dapp

I’ve built a small proof-of-concept project around this idea called , feel free to check it out :

P.S.: In the examples above I’ve set the Gas Price to 20 GWei. To help you choose the Gas Price you want to pay, you could check out . ETH Gas Station provides transaction confirmation time estimates and other useful network stats.

Adil H

Written by

Adil H

Freelance Backend Developer. Golang, Python, Node.js, GCP