One Code Many Storages

Angel Java Lopez
2 min readApr 9, 2021

--

When you deploy a compiled smart contract to an Ethereum-like blockchain like RSK, your transaction includes the compiled bytecode, including the constructor code.

An example, if you want to deploy Counter.sol:

pragma solidity >=0.5.0 <0.6.0;contract Counter {
uint public counter;

function increment() public {
counter++;
}

function add(uint value) public {
counter += value;
}

function incrementFail() public {
counter++;
require(false, "fail error");
}

function fail() public pure {
require(false, "fail error");
}
}

your transaction will contain:

Deploy Transaction for Counter.sol

The data field is huge, for such small smart contract. Imagine its size when you deploy a more complicated DeFi-related contract. The size of the payload and the size of the runtime bytecodes in the contract HAVE an associated cost in gas. This is because you must pay for the work every node in the network will execute to deploy this contract.

Some times, you need to deploy the same contract many times. IE, a liquidity pool in a DeFi project, or a surrogate contract for representing a user without balance using metatransactions (see my project https://github.com/ajlopez/EthMeta)

For those cases, I have a proposal and associated code. Instead of sending the smart contract code EVERY TIME you need a new instance, you can say:

“I need a new instance BUT WITH THE same code another instance has”.

Then, this new instance will have its own storage, but the code is shared with another account.

The way to specify this intention is SENDING THE another instance ADDRESS as part of the data field. My proposal: send a data field with 32 bytes, including the address padded to the right:

data: 0x000000000000000000000000157973f817512a87a4f5eb12b1a1ec448d1d7049

In this way, the cost could be lower, and it could be significant impact, for example, in metatrasactions implementations that support thousands of surrogate contracts representing users without balance.

I coded a first implementation in my personal BlockchainJ project, see commit https://github.com/ajlopez/BlockchainJ/commit/206c1d57a47608b5ead619ca493c3e444f02aee2

The price to pay: you lost the constructor. But it is a common pattern now, with upgradable contracts, to have an initialized() function to be called immediately after the creation of the new instance.

Usually this kind of deploy are executed using scripts, so there is no change in the wallet implementations.

Angel “Java” Lopez
@ajlopez

--

--