Short Types in Solidity: Rare Tricks Uncovered
0xB25C
October 10th, 2022

Greetings dear readers!

We continue our series of educational articles and today we’ll look at some specific tips for optimizing gas in the development of smart contracts on Solidity!

Read an original article via the link below:

In Solidity, some data types have a higher gas cost than others. And that is what is often required of a smart contract developer and that’s why you should understand the gas utilization of the available data types; — in order to choose the most efficient one according to your needs. For the purposes of this article, we refer to uint8-uint248 and int8-int248 types as “short types”.

With all said, the main reason to use short types in Solidity is to save gas when working with storage due to tightly packed variables, structure fields and array elements. The following will be our observations — only dry facts, tricks and the best life-hacks shared by our best auditors. Let’s get started!

By the way, there are some vacant slots now so if your project needs an audit — feel free to write to us, visit our public reports page here.


I — TLDR:

  • Solidity compiler tightly packs short types (if possible) to reduce storage footprint of storage variables, struct fields, array elements;

  • Short types require more opcodes and gas in all other cases (calldata, memory, stack).

II — Besides, short types are more error-prone:

  • Overflows happen more often;

  • Solidity 0.8 and SafeMath do not check for overflows during type casts;

  • Short types behave differently for abi.encodePacked and other abi.encode* calls.

III — We recommend:

  • Using short types only to reduce storage footprint;

  • Local variables, return values, function and event parameters should be uint256 or int256

  • Converting uint256 values to shorter types right before you write them to storage. Utilize libs like a SafeCast; — they have a pretty good syntax;

  • When you read short type value from storage, convert it to uint256 immediately

  • Utilizing storage location when possible: function foo(MyStruct storage ms, uint32[] storage array) internal {…}

  • Read individual fields or elements if you don’t need the whole structure or array: uint256 value = uint256(ms.field) + uint256(array[i]);

IV — In other situations short types rather increase gas consumption:

  • Solidity ABI encoder puts every value into a separate slot, i.e. the size of calldata or returndata remains the same.

  • The compiler often inserts additional opcodes — it may inflate the size of the contract.


We hope that this article was informative and useful for you! Thank you for reading!

What instruments should we review? What would you be interested in reading about?

Please leave your comments, we will be happy to answer them, and the best answers and questions may be included in the next article!

Thanks to Alexander Seleznev!

Subscribe to Officer's Blog
Receive new entries directly to your inbox.
Collectors
View
#1
#2
#3
View collectors
This entry has been permanently stored on-chain and signed by its creator.
Author Address
0xB25C5E8fA1E53…9F6A66B786ED77A
Content Digest
SnmH8v6QV6jHa64…8oiSP7zxgss_BEU