[Ethereum] Does having a separate contract for storage increase gas cost of making a transaction

contract-designgassoliditystorage

I've been reading a lot about upgradability of smart contracts, and it seems like major prevailing practice is that it is generally a good idea to keep contract logic separate from contract storage, so it is possible to upgrade one and not have to change the other one.

My question is the following: does the fact that one contract has to call another contract increase the amount of gas that is spent by that logic. For example, say I had a contract that looked up a number X and then added it to the number 5.

In one case, the contract stores in X itself, and so it can directly look it up. In the other case, a separate contract is responsible for storing X, causing one contract to make a function call to get X. Does one cost more gas? If so, is it possible to tell how much more?

Thanks!

Best Answer

I would say yes, a little, but no it's not terribly important in most cases. Setting aside one-time deployment cost, there will be additional code to run with each transaction. It's not free, but the additional code won't be especially more expensive to operate in most cases.

Have a look at gas costs per operation (no warranty implied): https://docs.google.com/spreadsheets/d/15wghZr-Z6sRSMdmRmhls9dVXTOpxKy8Y64oy9MvDZEQ/edit#gid=0.

A basic heuristic is that state change opcodes (e.g. SSTORE) are quite high compared to compute opcodes that don't change the blockchain. One can generally add additional low-cost overhead steps (e.g. look up a contract address and form a message) without greatly increasing the overall cost of a state change. The state change will be expensive in any case.

Read operations are often handled with constant functions or local calls that don't use gas at all. So, transaction cost concerns are generally limited to transactions that will result in a state change. So, create/insert, update and delete have a cost (the lion's share from ops like SSTORE). Reads are usually cost-free regardless of complexity. Also consider that many systems use offchain storage fed by event emitters that maintain a copy of "official" facts for performance reasons. Another example of a situation in which only the cost of updates is of any concern at all.

To play around with a specific example and compare costs, you could consider coding representative functions both ways and comparing actual gas consumption. Solidity Realtime compiler will show the bytecode after compilation. You can step over source code to see which actual steps are "expensive" and optimize accordingly.

As a footnote, beware of the hidden cost of additional complexity. While upgradable contracts are advantageous in many ways, there's a yin-yan-like set of tradeoffs to consider for each use-case. For example, upgradability could reduce trustworthyness in some cases and is potentially a new source of bugs.

Hope it's helpful.

Related Topic