IPFS Storage Cost – How Much Does It Cost to Store Each IPFS Hash in Ethereum Blockchain

blockchaingasipfssolidity

I've looked in some of the resource on calculating the Gas costs like this spreadsheet I found on this thread. But the spreadsheet only have computations gas costs but not storing of hashing.
I'm a bit confuse, the way to store IPFS hash in the blockchain contract is also a bit different based on this thread. I thought it would be straight forward as having to store strings or bytes but it needs to be in Struct?
Can anyone assist me. * sorry im still new in smart contract programming

Best Answer

When storing data on the Ethereum blockchain, each computation task has a cost (in gas unit) and you usually want to reduce as much as possible the cost of the transaction for your application.

You want to store an IPFS hash (or Multihash) (or CID) like QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u in a smart contract

First: Read this to understand multihash


Here is three solutions to store an IPFS hash with the gas cost associated.

Assuming gasPrice: 20 000 000 000 (wei)

1. Store it as a String

Smart contract:

contract IPFSStorage {
    string hash;
    function storeCIDAsString(string _hash) public {
        hash = _hash;
    }
}

Truffle Test:

it('should store the IPFS CID as a string', async () => {

    instance.storeCIDAsString(cid, {'from': accounts[0]}).then(function(txReceipt) {
        console.log('# should store the IPFS CID as a string');

        let gasUsed = txReceipt.receipt.gasUsed;
        console.log("gasUsed: " + gasUsed + " units");

        let gasCost = gasUsed*gasPrice;
        console.log("gasCost (wei): " + gasCost + " wei");

        let gasCostEth = web3.fromWei(gasCost, 'ether')
        console.log("gasCost (ether): " + gasCostEth + " ether");
    }).catch(function (error) {
        console.log(error);
    });
});

Result:

# should store the IPFS CID as a string
gasUsed: 85986 units
gasCost (wei): 1719720000000000 wei
gasCost (ether): 0.00171972 ether

2. Store it as a struct

Smart contract:

contract IPFSStorage {
    struct Multihash {
        bytes32 hash;
        bytes2 hash_function;
        uint8 size;
    }

    Multihash multihash;

    function storeCIDAsStruct(bytes32 _hash, bytes2 _hash_function, uint8 _size) public {

        Multihash memory multihashMemory;
        multihash.hash = _hash;
        multihash.hash_function = _hash_function;
        multihash.size = _size;

        multihash = multihashMemory;
    }
}

Truffle Test:

it('should store the IPFS CID as a struct', async () => {

    let mh = multihashes.fromB58String(Buffer.from(cid))
    let args = {
      hashFunction: '0x' + mh.slice(0, 2).toString('hex'),
      digest: '0x' + mh.slice(2).toString('hex'),
      size: mh.length - 2
    }

    instance.storeCIDAsStruct(args.digest, args.hashFunction, args.size, {'from': accounts[0]}).then(function(txReceipt) {
        console.log('# should store the IPFS CID as a struct');

        let gasUsed = txReceipt.receipt.gasUsed;
        console.log("gasUsed: " + gasUsed + " units");

        let gasCost = gasUsed*gasPrice;
        console.log("gasCost (wei): " + gasCost + " wei");

        let gasCostEth = web3.fromWei(gasCost, 'ether')
        console.log("gasCost (ether): " + gasCostEth + " ether");
    }).catch(function (error) {
        console.log(error);
    });
});

Result:

# should store the IPFS CID as a struct
gasUsed: 55600 units
gasCost (wei): 1112000000000000 wei
gasCost (ether): 0.001112 ether

3. Store it in the event log

Smart contract:

contract IPFSStorage {
    event CIDStoredInTheLog(string _hash);

    function storeCIDInTheLog(string _hash) public {

        emit CIDStoredInTheLog(_hash);
    }
}

Truffle Test:

it('should store the IPFS CID in the logs', async () => {

    instance.storeCIDInTheLog(cid, {'from': accounts[0]}).then(function(txReceipt) {
        console.log('# should store the IPFS CID in the logs');

        let gasUsed = txReceipt.receipt.gasUsed;
        console.log("gasUsed: " + gasUsed + " units");

        let gasCost = gasUsed*gasPrice;
        console.log("gasCost (wei): " + gasCost + " wei");

        let gasCostEth = web3.fromWei(gasCost, 'ether')
        console.log("gasCost (ether): " + gasCostEth + " ether");
    }).catch(function (error) {
        console.log(error);
    });
});

Result:

# should store the IPFS CID in the logs
gasUsed: 27501 units
gasCost (wei): 550020000000000 wei
gasCost (ether): 0.00055002 ether

As you can see, each solution work, the only difference is the gas cost of the transaction for storing an IPFS hash in the Blockchain.

You can find the code here (Truffle project)