Blockchain for Censorship Resistance - 97% cheaper storage

When collaborating with Civil one of the biggest asks from Newsrooms publishing in the ecosystem was censorship-resistance, a way to store all documents inside blockchain itself.

A few requirements:

  1. Anyone needs to be able to get an index of all listed articles

  2. Articles need to be retrievable on the front-end

  3. The costs can’t be prohibitive, under $1 per article

We’ve set out to research the problem and ended up with the following technical framework. Each Newsroom would be a singular smart-contract on the blockchain, and each article would emit an Event. That way, anybody can grok all the Events and rebuild the index on the client side.

We’ve iterated storing of articles until we’ve ended up with a solution that costs only $0.04 per 100 sentences.

First we’ve decided on a simplest way possible — storing the article straight into smart-contract’s Storage array

contract Example {
  event ArticleStored(uint id);
  string[] public articleArray;

  function storeArticle(string calldata content) external {
    emit ArticleStored(articleArray.length);
    articleArray.push(content);
  }
}

Which ended up costing around $1.42 per article, way too much.

According to Ethereum’s Yellow Paper you have to pay the three times per byte of article.

  1. The cost of transaction data

  2. The cost of loading the transaction data into memory

  3. The cost storing the data from memory into storage

This solution is the most expensive, but the only one if you want to allow other contracts to read the articles themselves.


Afterwards, we’ve stored the article into the Event itself. Storing data into Events is substantially cheaper than storing anything in permanent Storage.
The downside here is that the article can now be only extracted from outside the blockchain, from the client side.

contract Example {
  event ArticleStored(string content);
  function storeArticle(string calldata content) external {
    emit ArticleStored(content);
  }
}

We still have to pay three times for the article, the difference here is that Event storage costs only 32 gas per word compared to 20000 gas for Storage. That already is a huge cost saving.


We want to pay for the article only once, and put it only into the function call itself.

contract Example {
  event ArticleStored();
  function storeArticle() external {
    emit ArticleStored();
  }
}

To do that we need to understand the call structure we’re using.

1_WDlpy4Vw33FEePCP015Btg.png

First is the encoded smart-contract instructions, this is what the smart-contract reads to understand which function to call. Then it’s the article itself in a gzipped way and last is the length of the gzipped article formatted to 8 bytes.

Here’s how to send the transaction using Truffle.

// Node has a built-in deflate function
const deflatedArticle = (await deflate(ARTICLE)).toString("hex");
// Data to call the function of the contract
const encodedABI = instance.contract.methods.inTransaction().encodeABI();
// Length of the article padded to 8 bytes so it's constant in length
const hexLength = deflatedArticle.length.toString(16).padStart(16, "0");
const txData = encodedABI + deflatedArticle + hexLength;const web3 = Example.web3;
await web3.eth.sendTransaction({
  from: (await web3.eth.getAccounts())[0],
  to: instance.address,
  data: txData,  gas: 4000000 // A random big number
}));

And we end up with an article that is forever stored in blockchain, searchable and costs only $0.04!

Check out the repository itself to see the full example

EngineeringOlaf Tomalka