Recommended resources
The freely available resources this lesson will direct you to.
Hello! Welcome back to our journey in building a cryptocurrency.
In our last lesson, you mastered the art of testing access control by using .connect() to simulate calls from different users. This ensures that sensitive functions, like minting new tokens, are properly secured. Now that we're confident in our contract's security and functionality, let's turn our attention to its efficiency.
Today, we're diving into a crucial topic for any successful blockchain project: gas consumption. For your token to be adopted and used, transactions must be affordable. High gas costs can deter users and harm your project's viability. This lesson will equip you with the skills to measure, understand, and analyze the gas costs of your smart contract functions, a vital step before deploying to the mainnet.
By the end of this 60-minute session, you will be able to set up a professional tool to measure gas usage and analyze how different coding patterns impact the transaction costs of your contract.
1. Why Gas Is Your Concern
On Ethereum, "gas" is the unit used to measure the amount of computational work required to perform an operation. Every single action—from a simple addition to writing data into storage—has a fixed gas cost. The total gas used for a transaction, multiplied by the current gas price, determines the fee a user pays in ETH.
As the creator of a token, you have a direct incentive to make your contract as gas-efficient as possible.
- User Adoption: Cheaper transactions make your token more attractive to buy, sell, and use.
- Network Health: Efficient contracts reduce bloat on the Ethereum network.
- Complex Interactions: If your token is part of a larger DeFi ecosystem (like staking or liquidity pools), high gas costs can make these interactions prohibitively expensive.
To get a better handle on this, let's start with a resource that frames the importance of gas testing.
How to Test Gas Usage in Ethereum Smart Contracts
This article from MyWeb3Startup provides a great introduction to why gas testing is critical and the tools involved. It sets the stage for what we're about to implement.
Please read the introduction (the first few paragraphs before the 'How to Calculate Gas Usage' heading) and the FAQ question 'How does the hardhat-gas-reporter plugin help optimize gas usage in smart contracts?'. These sections will give you a clear, high-level understanding of our goal today.
2. Setting Up the hardhat-gas-reporter
To measure gas usage, we don't need to guess. We can use a popular Hardhat plugin called hardhat-gas-reporter. This tool automatically intercepts your test runs, measures the gas used by each function call and contract deployment, and presents a detailed report.
Step 1: Installation
First, add the plugin to your project as a development dependency. Open your terminal in your project's root directory and run:
npm install --save-dev hardhat-gas-reporter
Step 2: Configuration
Next, you need to enable the plugin in your Hardhat configuration file, hardhat.config.ts. You'll import it and add a gasReporter object to the configuration.
The setup process is straightforward. Let's refer to a guide that walks through the necessary steps.
Hardhat: Optimizing the gas usage of smart contracts
The documentation on docs.base.org provides a clear, step-by-step guide to installing and configuring the hardhat-gas-reporter plugin.
Please read the section 'Setting up the Hardhat Gas Reporter plugin'. Follow the instructions to add import "hardhat-gas-reporter" and the gasReporter object to your hardhat.config.ts file.
Your hardhat.config.ts file should now look something like this:
import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
import "hardhat-gas-reporter"; // <-- Add this line
const config: HardhatUserConfig = {
solidity: "0.8.24",
gasReporter: {
enabled: true, // Set to false to disable
},
};
export default config;
For more advanced and useful reports, you can add a few more options. A common configuration includes setting a currency to see real-world costs and disabling color codes for cleaner output if you save the report to a file.
// A more detailed configuration
gasReporter: {
enabled: true,
currency: 'USD', // Show costs in USD
coinmarketcap: 'YOUR_COINMARKETCAP_API_KEY', // Optional: for accurate price conversion
noColors: true, // Recommended for cleaner file output
outputFile: 'gas-report.txt' // Save the report to a file
}
Obtaining a free API key from CoinMarketCap will give you up-to-date ETH prices for your cost estimates. For now, you can omit this line; the plugin will use a default value. The video below briefly mentions where to place this configuration.
How to Upgrade to Hardhat Toolbox in 2 Minutes
This short clip from EatTheBlocks visually shows where the gas reporter configuration goes in your Hardhat config file.
Watch the segment from 01:03 to 01:25. It provides a quick visual of a complete gasReporter configuration block, including the coinmarketcap API key option.
3. Generating and Reading Your First Gas Report
The best part about this plugin is its simplicity. To generate a gas report, you just run your tests as you normally would:
npx hardhat test
When the tests finish, you will see a new table in your console output. This is your gas report!

Let's break down what the report tells us. The following resource provides an excellent example.
Hardhat: Optimizing the gas usage of smart contracts
Let's return to the Base documentation to see an example of a gas report and learn how to interpret it.
Read the section 'Your first gas profiling'. Look at the sample contract and the test, then carefully examine the gas report table. Pay attention to the columns for Method, Avg (average gas), # calls, and the separate Deployments section.
As you saw, the report gives you two main sections:
- Methods: Details the gas cost for each function that was called during your tests.
Min,Max,Avg: The minimum, maximum, and average gas consumed by that function across all calls. This is useful if a function's cost varies (e.g., based on input).# calls: How many times the function was executed in your test suite.
- Deployments: Shows the gas cost to deploy each of your contracts. This is a one-time cost but can be very significant.
4. Analyzing and Optimizing Gas Usage
Now for the "analyze" part. A gas report is a diagnostic tool. It tells you where your contract is spending gas. Your job is to use this information to identify "hot spots"—expensive functions—and see if they can be optimized.
Let's explore a few common optimization patterns and see their impact directly in the gas report. Your background in backend development has likely taught you that some operations are more "expensive" than others (e.g., disk I/O vs. memory access). The EVM has a similar hierarchy, where storage operations are by far the most expensive.
Hardhat: Optimizing the gas usage of smart contracts
This resource demonstrates several powerful gas-saving techniques by showing the code before and after the change, along with the corresponding gas report. This is the best way to analyze the impact of your code.
Carefully read the sections under 'Common strategies to optimize contract sizes': 'Using immutable variables': Notice how changing address owner to address immutable owner reduces both deployment and function call costs. 'Avoid unnecessary data storage': This is a key one. See the dramatic gas savings achieved by removing the mapping and using an event instead. This is a classic trade-off between on-chain storage and off-chain indexing. 'Using custom errors': Note the small but easy saving on deployment cost by switching from require strings to custom errors, a feature available since Solidity 0.8.4.
These examples illustrate a fundamental principle of smart contract optimization: reduce writes to storage.
immutablevariables: When a variable is declaredimmutable, its value is set once in theconstructorand then baked directly into the contract's runtime bytecode. Reading it later is as cheap as reading a constant, avoiding an expensiveSLOAD(storage load) operation.- Events vs. Storage: Storing data in a
mappingcosts a lot of gas because it involvesSSTORE(storage store) operations. If you only need to broadcast that data for off-chain applications to see, emitting aneventis vastly cheaper. Your dApp frontend can then listen for these events and build its own state.
Test your understanding!
In the MyToken contract from our previous lessons, the owner is likely set in the constructor. The contract inherits from OpenZeppelin's Ownable, which stores the owner's address in a state variable.
Based on what you just learned, if you could change that state variable to be immutable, what would you expect to happen to:
- The gas cost of deploying the
MyTokencontract? - The gas cost of calling a function protected by the
onlyOwnermodifier?
Show answer
- Deployment Cost: The deployment cost would likely decrease. By making the
ownervariableimmutable, the Solidity compiler can perform optimizations, reducing the overall bytecode size and setup cost. - Function Call Cost: The gas cost for calling a function like
mint(which usesonlyOwner) would also decrease. TheonlyOwnermodifier needs to check ifmsg.sender == owner. Reading animmutablevariable is much cheaper than reading a regular state variable from storage (SLOAD), so every call to a protected function becomes more efficient.
(Note: OpenZeppelin's Ownable contract doesn't use immutable for the owner because it's designed to be transferable via the transferOwnership function. This is a great example of a design trade-off between gas efficiency and flexibility.)
Conclusion
Fantastic work today! You have added a critical tool to your developer toolkit. Understanding and managing gas costs is a hallmark of a professional smart contract developer. It's a skill that directly impacts your project's bottom line and user experience.
Key Takeaways:
- Gas represents computational cost on the EVM, and minimizing it is crucial for creating successful, cost-effective dApps.
- The
hardhat-gas-reporterplugin is an essential tool that integrates seamlessly with your test suite to provide detailed gas consumption reports. - You can generate a gas report simply by running
npx hardhat test. - The most significant gas savings often come from minimizing on-chain storage operations. Techniques like using
immutablevariables and emittingeventsinstead of writing to mappings can drastically reduce costs.
Preview of the Next Lesson:
This lesson concludes our module on automated testing. You can now test for functionality, security, and efficiency. We are now ready to move on to Module 6: Smart Contract Security Principles. In our next lesson, we will tackle one of the most infamous vulnerabilities in Ethereum's history: reentrancy attacks. You will learn what they are, why they are so dangerous, and how to write code that is invulnerable to them using the "Checks-Effects-Interactions" pattern.