Introduction
Hopefully it is clear from the title that the methods outlined in this article are not safe for production smart contracts!
The intent here is to give some ideas for solidity gas optimization contests. Usually, these contests are for smart contract programmers to create a smart contract that accomplishes some functionality while costing as little gas as possible. Here are 9 techniques.
Use selfdestruct
The inappropriate use of selfdestruct
as behind the Parity Wallet freeze. However, you don’t care about that in a gas optimization contest do you? Ethereum gives you a slight refund for selfdestructing the contract, so if you can end your execution with a selfdestruct, do so.
Use gasprice()
or msg.value
to pass information
Passing parameters to a function will at bare minimum add 128 gas, because each zero byte of calldata costs 4 gas. However, you can set the gasprice
or msg.value
for free to pass numbers that way. This of course won’t work in production because msg.value costs real Ethereum and if your gas price is too low, the transaction won’t go through, or will waste cryptocurrency.
Use gasleft()
to branch decisions at key points
Gas is used up as the execution progresses, so if you want to do something like terminate a loop after a certain point or change behavior in a later part of the execution, you can use the gasprice()
functionality to branch decision making. gasleft()
decrements for “free” so this saves gas.
Mine for efficient function names
The function selector is the first four bytes of the keccack256
of the function signature. The more leading zeros it has, the less space it takes up in the smart contract. This leads to funny function names, but do you care? Use this tool here: https://github.com/jeffreyscholz/solidity-zero-finder-rust
Count to zero if using a storage variable
When a storage variable is set to zero, a gas refund is issued. This means you can’t keep counting or you will get an underflow (or a revert if you are using solidity 0.8.0 or higher and no unchecked
block). However, in a gas optimization contest, once you accomplish what you set out to do, the smart contract no longer needs to be usable.
Use send()
to move ether, but don’t check for success
The difference between send
and transfer
is that transfer
reverts if the transfer fails, but send
returns false
. However, you can just ignore the return value of send, and that will result in fewer op codes. Ignoring return values is a very bad practice, and it's a shame the compiler doesn't stop you from doing that.
Make functions and interfaces payable
Although this is not dangerous per se, payable
functions can lead to unexpected state changes, so it’s safer to not mark a function as payable if the intent is not to receive ether. But in a gas optimization contest, this will save some op codes, because non-payable functions explicitly check msg.value
and revert if it is non-zero, whereas payable functions simply skip this check.
Implement nested mappings or multidimensional arrays with assembly
Under the hood, a nested mapping and a multi-dimensional array is the hash of the concatenation of the storage slot and first key, then the hash is concatenated with the second key, and hashed again. This double hashing is fairly expensive. You can concatenate the keys yourself and then do one hash followed by an sstore
. This could lead to a storage collision if you have another nested hash map somewhere that uses the same types as keys. Solidity doesn’t know how many nested hash maps you have, so it is conservative about how it computes the storage slot. But you don’t like to play it safe in solidity gas optimization challenges do you? You can learn more from our video about this here.
Use unchecked
liberally
As mentioned above, solidity 0.8.0 checks if an arithmetic operation overflowed or underflowed. Wrap it in unchecked
to remove that check. But you better know what you are doing if you do this with a production smart contract!
Apply to our blockchain solidity bootcamp here.
Our twitter page posts gas optimization contests, some of which have gitcoin bounties, so be sure to give it a follow!
Top comments (0)