How To Save 50% Or More On Smart Contract Gas Fees
The Lizard Lab was ready for launch when suddenly the market took a shift for the worse, creating dire conditions for minting. October 19th marked the lowest day in trading volume on OpenSea in months, with gas prices rising to an average of 100 gwei as altcoins and rising ETH price congested the network. The NFT space went into a panic while daily floor monitors turned from green to red as activity ground towards a halt.
With a community that had been developing for months and an upcoming launch finally in front of us, we were put into a difficult situation. The consensus was that we had two options: Launch with high gas fees or delay until gwei is lower.
Launching with high gas fees wasn’t a realistic option. We couldn’t ask people to pay gas fees equal to the mint cost, simply out of impatience. We also couldn’t indefinitely delay and wait for lower gas fees – especially when low numbers could only last for a small window before we’re brought back to our original problem.
Then we realized a third solution: Take fate into our own hands and solve the gas problem.
What Changes We Made & Why
ERC-721 NFTs are built on the OpenZeppelin standard contract. Over time there have been a number of optional extensions and other practices that add functionality to the standard contract. While useful, these extensions come at the cost of extra gas consumption. Over the years, these open-source contracts have seen iterations and additions that were made during a different time and landscape – most notably cheaper ETH and lower gwei.
The biggest gas guzzler we identified was ERC721Enumerable.sol. This extension was first added near the end of 2018, when the average gwei was 20, and ETH was $100. Adding an extra 50% to the gas fee is a much bigger deal now than it used to be – It’s not sustainable for people to pay an additional 50% on top of a mint price in transaction fees, and it’s not good for the network either.
We noticed that older ERC-721 tokens were able to mint with very low gas fees, due to using fewer of these optional extensions. Bored Ape Yacht Club was a shining example with their prominence in the NFT space while running a lean contract – most importantly, they did it without the Enumerable extension.
After many test contracts and long nights, we found many small optimizations to reduce our gas usage, like using constants instead of variables when available and dropping the safemath function. These improvements paled in comparison to the savings from removing Enumerable, so we had a tough question to answer – is Enumerable worth the gas right now?
So what does the Enumerable extension offer? It’s an optional extension to the standard ERC-721 that adds additional indexing methods to the smart contract. These indexing methods are a way for other smart contracts and decentralized applications to more easily interact with your contract through the blockchain, as opposed to using an API. There are pros and cons to each method, which we’ll explore in the following example.
Let’s say you have opened the “Metaverse Mall” that has a private room, for lizard owners only. This room has a “security guard” who has 3 different common methods to check if you have an official Lizard Lab Token.
Check the wallet for any Lizard tokens
The security guard asks you to empty your entire wallet, and he looks at every single token in your wallet and inspects it for an official Lizard Lab sticker.
This requires the security guard (or front-end in these examples) to look at each individual token in your wallet, and then check which contract it belongs to.
If the token is from the allowed contract, then you’re good to go.
Inspect the entire wallet one token at a time
The security guard calls the official Lizard Lab Lizard Registry, and asks if your wallet owns any Lizard Lab tokens. This Registry checks each item in the database (starting from the beginning) to see if any of the Lizard Lab tokens show you as the owner.
This enables a front-end developer to specify the contract, go directly to the contract and call the OwnerOf method on each and every token, and if the person entering the room’s wallet shows up in any of them, in you go!
Get a list of every Lizard token in a wallet
The security guard again calls the official Lizard Lab Lizard registry, and asks a very specific question, “what tokens does this person own?”
This allows a front-end to get this information by calling a single method. No loops, no filters, nothing except asking the contract for information behind Method Three – using methods built-in and based on the Enumerable extension.
Method 3 is the most effective way to tell which individual tokens from a specific contract are inside of a wallet – but it comes at a great gas cost. There’s a great Twitter thread from @gaslimitreached with a detailed explanation on why it’s so expensive to maintain these mappings and a potential fourth solution that is definitely worth exploring more, demonstrated by the Toy Boogers contract.
The first two options are meant to show how cumbersome it can be to find the token owners of a contract without the Enumerable extension. This is fine for anything operating off-chain, like a web front-end or external API, but are not recommended for any on-chain transactions. The third option is meant to show the power and efficiency that the Enumerable extension provides further down the line.
Dropping The Enumerable Extension
The decision to drop the Enumerable Extension took many long nights of research and testing. We broke down every decent contract we could find across a range of projects, and had conversations with experts who had opinions on both sides. The argument came down to a philosophical level – should the functions within Enumerable be achieved with a smart contract at the cost of gas, or should these database-like functions be handled with an API?
Ultimately we decided to remove Enumerable – the gas savings were too significant in our current conditions to ignore for an optional extension that could very well be obsolete before we know it, given how fast the space moves.
Lessons Learned & Takeaways
All of these decisions were made considering our project’s needs and the current landscape. This isn’t meant to be a template for a “best contract” but rather an explanation of our approach, and our reasonings. None of our optimization decisions were made lightly. We’ve spent countless hours balancing between today’s needs while also building with future integrations in mind. Deciding what functions should be in a smart contract is a multifaceted debate with many questions and angles to consider.
Right now while we are (sorry for the cliché) still very early and figuring out better ways to do things. New solutions are being developed – for example, The Graph is monitoring and indexing everything and anything on every chain, enabling scalable and flexible communication between different contracts and platforms, without contributing towards ETH network congestion.
At the end of the day, we are building in an agile way for modern times. New problems require new solutions, and the ETH NFT landscape was facing a new issue with high gwei and ETH. High gas contracts can “clog up” the network and slow other activity down to a halt.
We all have our own “footprint” on the ETH network, and it’s worth considering the ways to reduce our impact. A single contract reducing gas fees is a drop in the bucket, but if it becomes a standard, these improvements will have a huge impact and contribute towards a better and more sustainable ETH for everyone. Right now whenever the average gas is high, newly minting projects suffer along with the secondary market, which isn’t good for anybody.
It’s important to think about how changes on your own contracts impact developers and creators that you may be looking to work with in the future. Future collaboration and integration are what this is all about. The more sustainable and flexible solutions we can find and ease the implementation of, the quicker we’ll progress towards a seamlessly interconnected metaverse.
We hope that other projects use and iterate from what we’ve learned here. We’re here to try new things, and share our discoveries with the world in our lab reports and public experiments.
You can see our contract here: https://etherscan.io/address/0x9048de699869385756939a7bb0a22b6d6cb63a83#code
Join us in Discord to chat with the team and continue the discussion with our friendly and smart community. We love meeting new creators and are always looking for feedback & improvements.
Our minting is live, so you can try out our low-gas minting for yourself here: https://mint.lizardlab.io
See you in the lab!