Save Gas with Packing in Solidity

Assumptions for the Post

Presumptions in this post: You know what gas is in Ethereum. You know a bit of Solidity (i.e. what a struct is).

If you do not, then I’d recommend going through CryptoZombies tutorials atleast until finishing the Advanced Solidity tutorial (lesson 3) and up to Chapter 4, entitled “Gas”. It will explain to you the basics of Solidity and what gas is in relation to smart contracts in a fun, succinct way.

Strategies for Saving/Optimizing Gas

There are several strategies for saving and optimizing gas utility with Solidity smart contracts. I’m going to go over a couple I could find with a variety of sources namely struct packing and variable packing, as well as list more you can research on your own.

Why does saving gas do? It allows you to spend less ETH/money executing smart contracts that you write and deploy to the Ethereum mainnet.

What costs Gas?

For information on what exactly costs gas, please look at the Yellow Paper Excel Breakdown of Gas Costs by Opcode. This paper breaks down exact gas costs by operation code such as ADD for addition and SUB for subtraction. Each opcode corresponds to an operation that you can execute in a Solidity smart contract.

Here is a sample of what costs gas by opcode: Source: Stackexchange)

All prices are in wei.

For a frame of reference for how much this actually is in ETH, please visit this ETH converter.

Struct Packing and Variable Packing Strategies:

(1) Use structs packing (Source: CryptoZombies)

Inside structs, smaller unsigned integers,like uint32, will save you gas and allow Solidity to store these variables together in less space.

struct NormalStruct {
  uint a;
  uint b;
  uint c;
}

struct MiniMe {
  uint32 a;
  uint32 b;
  uint c;
}

// `mini` will cost less gas than `normal` because of struct packing
NormalStruct normal = NormalStruct(10, 20, 30);
MiniMe mini = MiniMe(10, 20, 30); 

(Code source: CryptoZombies Lesson 3: Advanced Solidity: Chapter 4: Gas)

(2) Variable Packing (Source: Will Shahda)

only occurs in storage. memory and call data will not be packed.

Each storage slot has 32 bytes(256 bits) in Solidity. In order to pack variables, we need to arrange them in a way that they fit in a single slot because each slot costs gas.

Unpacked variables:

uint128 a;
uint256 b;
uint128 c;

(source: Will Shahda Article)

Packed variables:

uint128 a;
uint128 c;
uint256 b;

(source: Will Shahda Article)

The second example is packed because it groups together uint a and c to add up to 256, which means it will only take up one slot, instead of the 3 slots it would have taken in the previous example.

More techniques to save gas:

(1) Inheritance (Source: Will Shahda)

(2) Initialization of variables (Source: Will Shahda)

(3) Deletion (Source: Will Shahda)

(4) Storing data in events (Source: Will Shahda)

(5) Use Assembly Code (Source: Julien Klepatch)

(6) Turn on the Solidity optimizer (Source: Julien Klepatch)

(7) Write literal values instead of computed ones (Source: Julien Klepatch)

(8) Use fixed arrays instead of dynamic arrays (Source: Stackexchange)

Conclusion

There are a variety of methods that can be used to save and optimize gas usage in Solidity smart contracts. Hopefully, this post has given you a good starting point to explore all the strategies available right now and the knowledge to be able to implement them as well.

Sources/Further Reading on Optimizing Gas:

CryptoZombies by LOOM network

Gas Optimization in Solidity Part I: Variables by Will Shahda

How to Write An Optimized Gas Cost Smart Contract? - Stackexchange

How to optimize gas cost in a Solidity smart contract? 6 tips by Julien Klepatch

Solidity tips and tricks to save gas and reduce bytecode size by Mudit Gupta

Solidity Gas Optimization - storage and local variables of basic types

Solidity gas optimization tips by Mudit Gupta

Published 13 Dec 2019

Full Stack Dapp && Smart Contract Engineer.
Max Goodman on Twitter