It is well known that most transactions on Ethereum require a fee to ensure that the network is spam-resistant and doesn’t get stuck in an endless loop of calculations. The gas fee is the amount of gas required to complete the transaction multiplied by the cost per unit of gas. The fee is paid whether the transaction succeeds or fails. As of November 2023, gas costs about 10 gwei. Although 1 gwei is now equivalent to about US$0.000002, we need to understand that this is just one unit, and you have to pay tens and sometimes hundreds of thousands of gas to complete transactions, which will be a more tangible amount. That is why we need to keep optimization in mind. As developers, we cannot influence the price of gas, so we need to focus on the units of gas consumed by the code to reduce it as much as possible. Due to the optimizations, developing on is different from developing Web 2.0 applications because we have to give up familiar patterns, such as splitting into small functions, for ease of testing. In this article, I will provide several examples, for each of which I will give an optimized and unoptimized smart contract with the amount of gas consumed. Ethereum Optimizations and operation codes There are two main approaches to optimization: (minimizing the size of the smart contract and the cost of Optimizing the cost of deployment executing the constructor) Optimizing each function call The first thing to check is that the smart contract does not contain unnecessary and unused code, as deployment is compiled to bytecode, and the more of it there is, the more expensive deployment will be. Here are some expensive gas operation codes in EVM: – Deploys a smart contract (32,000 gas) CREATE/CREATE2 – Stores the value in memory (20,000 gas if the slot has not been accessed, 2,900 SSTORE otherwise) (address(this).balance) – (2,600 gas if not previously accessed) BALANCE A complete list of all the codes for the different forks can be found here: . https://www.evm.codes Optimizing each function call is a better strategy because the smart contract is deployed once. Tips Do not initialize variables with default values If a variable is not initialized, the compiler assumes that it has a default value: for , for , for , for . So, initializing with default values is a waste of gas. 0 uint “” string false bool 0x(0) address Organize variables stores variables in cells of 32 bytes. If a variable is smaller than a cell, it is packed with another variable, but such variables must be declared side by side. Solidity Do not truncate variables When declaring a single variable, it makes sense to use , because otherwise, the variable has to be truncated, which takes a bit more time. uint256 Use static values In cases where there is an option to pre-calculate static values, it is better to use it, even if it is hardcoded. For instance, in the example below, you need to call two functions that increase the gas consumption. Use constant variables For variables that will be constants, just one keyword will save a lot of gas. immutable Do not declare temporary variables It may seem harmless to introduce an extra variable that is stored in memory rather than on the , but adding an intermediate variable requires more gas. blockchain Use mappings instead of arrays This is not always possible, but where possible, arrays should be avoided as they are more expensive to work with. Prefer a fixed-length array to a dynamic one In some cases, you cannot avoid using arrays. Dynamic arrays are more expensive than fixed-length arrays because you have to change the array length when using the push and pop functions. Use the data type you need in the array What applies to variables does not apply to arrays. If you specify the required type, the engine will pack the data in the correct way. Do not create many functions that call each other In any other language, the smaller the function, the better it is for debugging and testing, but things are not the same in Solidity. It is also desirable to minimize function calls to third-party smart contracts. Avoid multiple changes to state variables If there is a variable in the blockchain whose value needs to be changed multiple times, it is better to create a temporary variable and write the final value to the blockchain after the loop is executed. Optimize gas by removing unnecessary variables Ethereum offers gas refunds for deleting variables. Using the keyword with a variable name will return 15,000 gas but no more than half of the transaction value. delete Use selfdestruct() to compensate for gas Deleting a contract without the option to restore will return 24,000 gas but no more than half of the transaction value. Use Solidity Gas Optimizer The built-in optimizer allows you to adjust the value of iterations depending on your optimization goals. A lower value should be set to minimize deployment costs, and a higher value should be set to optimize runtime costs. Below is the configuration file for the Solidity Optimizer with Hardhat. Summary At compile time, contract code is converted to byte code for EVM, and transaction codes have a cost depending on the Ethereum fork. Despite initiatives to reduce the cost of gas (in particular, the introduction of variable size blocks in the London update, which changed the way fees are calculated), as developers, we need to optimize both the deployment and function calls in smart contracts to save money on deployment and execution.
Share Your Thoughts