This article explains the concept of gas in Ethereum and the basics you need to know when developing smart contracts in Solidity.
What is Gas in Ethereum?
In Ethereum, we have to pay for each computational operation, measured in the unit called gas.
In the Ethereum documentation, gas is defined as follows:
“Gas refers to the unit that measures the amount of computational effort required to execute specific operations on the Ethereum network.
Since each Ethereum transaction requires computational resources to execute, each transaction requires a fee. Gas refers to the fee required to conduct a transaction on Ethereum successfully.” – Source: What is gas?
To understand what gas precisely is, let’s zoom out and take a quick look at Ethereum transaction fees.
Ethereum transaction fees
Back in the old days (the 1960s or 70s), people were sharing computers due to the high cost of computer resources and were very conscious of the cost of computational operations. Then, the development of personal computers made computer resources much more accessible, and people no longer think about the cost much except when there are strict resource constraints.
The Ethereum Virtual Machine is a shared computer across the Ethereum network, so we have to think about how efficiently we can use the resources like in the old days. But instead of using time-sharing systems, Ethereum uses transaction fees due to the distributed nature of its execution environment.Β
The following formula calculates transaction fees:
Gas units * Gas price
The first term of the formula is the total cost of the computational operations measured in the unit called gas. How much gas each operation consumes is defined in the Ethereum Yellow Paper (Appendix G. Fee Schedule). Still, when sending a transaction, we don’t usually know the exact cost of the operations in advance. So, we (the sender) pay the maximum amount of gas we are willing to pay for the transaction upfront, called the gas limit. After the transaction finishes, the remaining balance (gas limit – actual gas used) is returned to the sender. It is like buying a pre-paid card before making a telephone call. Ethereum will deduct the actual amount of gas from the gas limit, execute the transaction and then return the remaining balance to the sender.
The second term of the formula is the price of gas in ether (ETH), or more precisely in a fraction of ether called gwei, which is equal to 0.000000001 ETH (one billionth ETH). The gas price fluctuates primarily depending on the Ethereum network utilization. The way to calculate the price itself sometimes changes as well. For example, there was a significant change in August 2021 when the London Upgrade was implemented. You can find all the details in the Ethereum documentation.
The rest of the article focuses on the first term of the formula (Gas units) to understand the basics of gas when implementing smart contracts in Solidity.
Basics of gas in Solidity development
The opcode fee schedule
As mentioned in the previous section, the cost of each operation is defined in the Ethereum Yellow Paper (Appendix G. Fee Schedule). However, it is not straightforward to know precisely how many gas units our Solidity code costs. The gas units are based on Ethereum Virtual Machine opcodes, which are generated by the Solidity compiler. So, the cost will depend on how the compiler generates opcodes from our Solidity code.
It is nonetheless helpful to know the cost of some of the frequently used operations. For example,
- Every transaction costs at least 21,000 gas (“base fee”).
- Each CREATE operation (creating a smart contract) costs 32,000 gas.
- Each SSTORE operation (writing a uint256 value to storage) costs as follows:
- 20,000 gas when the storage value is set from zero to a non-zero value
- 5,000 gas when the storage value is set from zero to zero or a non-zero to a non-zero value
- Each CALL operation with a non-zero value costs 9,000 gas, in which 2,300 gas is given to the recipient.
How do you estimate gas on Remix IDE?
The Remix IDE can indicate the gas estimation wherever possible. After compiling the code, click on the function name on the editor. At the bottom of the editor, we can see the Execution code in gas.
The following is an example of a simple smart contract to set a value and make it accessible to other smart contracts.
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.16 <0.9.0; contract SimpleStorage { uint storedData; function set(uint x) public { storedData = x; } function get() public view returns (uint) { return storedData; } }
The function get()
reads a value from the storage (storeData
). The following screenshot shows that the estimated total cost of the function is 2,437 gas, which more or less matches the cost of storage access (2,100 gas).
On the other hand, the function set()
sets a value to the storage, so the estimated cost of the function is 22,498 gas. Again we can see that it more or less matches the cost of operation to set a non-zero value to storage (20,000 gas)
How do you see execution cost on Remix IDE?
In real-world situations, you would interact with the Ethereum network using MetaMask or other web3 interfaces. Still, you can see how much gas your code would cost by executing it using JavaScript VM on Remix IDE.Β
When we deploy the contract and execute the function get()
, we see the execution cost in the console output.
It shows the cost was 23,501 gas. It is because every transaction costs the base fee of 21,000 gas. If we add 21,000 gas to the estimated cost of 2,437 gas, we get 23,437 gas, which is close to the actual execution cost above.
When we run the function set()
, we see the execution cost below.
It shows the execution cost was 43,702 gas. Again this is close to the estimated 22,498 gas plus the base fee of 21,000 gas (=43,498 gas).
How do you find more details using the debugger?
If you want to know the detailed breakdown of the execution cost, you can use the debugger on Remix IDE. Open the debugger by clicking the Debug button on the console after running the function.
You can run the code one operation at a time and see the detail of each operation, including the amount of gas.
The debugger usage is beyond this introductory article, but you can find more details in the Remix IDE documentation.
What is out of gas error?
Earlier I explained that the sender pays the transaction fee up front by specifying the gas limit and will receive a refund of the remaining balance after the transaction finishes. If the actual execution cost of the transaction exceeds the gas limit, the transaction will fail with an out of gas error. It is like the pre-paid card runs out of credit, so the telephone call suddenly disconnect.
When the out of gas error happens, the state change during the transaction reverts, but the transaction fee is not returned to the sender because the EVM already executed the operations up to the point of the error.
The following example illustrates how out of gas error happens using the JavaScript VM on Remix IDE.
The execution cost of the function get()
is 23,501 gas, so as long as the gas limit is equal to or larger than this number, the function successfully runs, as shown in the screenshot below.
But if we set the gas limit to 23,500 gas, the transaction fails with the following error:
call to SimpleStorage.get errored: VM error: out of gas. out of gas The transaction ran out of gas. Please increase the Gas Limit.
So, it is essential to set the gas limit large enough to execute transactions.
Summary
Gas is the unit of computational work on the Ethereum network. Each operation requires a pre-defined amount of gas to execute, and the total amount of gas for a specific transaction needs to be paid by the sender in the form of a transaction fee.
When developing smart contracts in Solidity, it is vital to be aware of the gas consumption of the code, although it is not always straightforward to understand precisely how much gas our code costs.
Remix IDE can estimate the gas unit of functions wherever possible. Alternatively, you can run your functions on the JavaScript VM and see how much gas they consume. You can even find a detailed breakdown of gas consumption on the opcode level by using the debugger.
This article only scratched the surface. You can find more information about gas in the following resources:
- Gas (soliditylang.org)
- Gas Limit and Loops (soliditylang.org)Β
- Gas Considerations (Mastering Ethereum)
- GAS AND FEES (ethereum.org)
- Ethereum yellow paper (Appendix G. Fee Schedule)Β
- Gas (solidity-by-example.org)
- Gas and Fees (eth.wiki)
- 8 Ways of Reducing the Gas Consumption of your Smart Contracts
Learn Solidity Course
Solidity is the programming language of the future.
It gives you the rare and sought-after superpower to program against the “Internet Computer”, i.e., against decentralized Blockchains such as Ethereum, Binance Smart Chain, Ethereum Classic, Tron, and Avalanche – to mention just a few Blockchain infrastructures that support Solidity.
In particular, Solidity allows you to create smart contracts, i.e., pieces of code that automatically execute on specific conditions in a completely decentralized environment. For example, smart contracts empower you to create your own decentralized autonomous organizations (DAOs) that run on Blockchains without being subject to centralized control.
NFTs, DeFi, DAOs, and Blockchain-based games are all based on smart contracts.
This course is a simple, low-friction introduction to creating your first smart contract using the Remix IDE on the Ethereum testnet – without fluff, significant upfront costs to purchase ETH, or unnecessary complexity.