Blockchain is a technology for Decentralized Networking Architecture. It’s designed to starlight trust among users without needing third-party intermediaries. For all its benefits, like every emerging tech we can see drawbacks in costs, specifically in blockchain transactions.
Smart contracts’ premise of automation & removal of the middlemen comes in executing smart contract functions on top of an infrastructure known as Ethereum Virtual Machine (EVM). A means to Ethereum blockchain programming is deploying and executing functions written in the smart contract (SC), which requires network transactions, thus incurring costs and network fees. The amount of GAS spent on each transaction depends on the amount of operation you incur on the EVM. In other words, the gas fees your users pay for simple tasks on the blockchain, like minting an NFT, swapping tokens, or transferring ETH to your friends, etc.
In this article, I will shortly discuss different memory types and Ethereum Opcodes, which are crucial to optimizing gas usage and building efficient and cost-effective smart contracts on the Ethereum blockchain.
Understanding Gas Mechanism in Ethereum Virtual Machine ⛽️
EVM is the virtual machine that all smart contracts work in Ethereum. A simple system, yet powerful. It’s based on 256-bit words and it’s Turing Complete. It’s important to understand, all SCs are sets of bytecode instructions, that are executed in sequence. But the bytecode allows jumps, which allows Turning Complete behavior.
In Solidity, when a smart contract is compiled, it is converted into a sequence of “operational codes”, also known as OpCodes. Abbreviations identify these Opcodes. E.g. ADD for addition, MUL for multiplication & so on. You can look at the complete list of Opcodes in the ethereum Yellow paper.
Opcodes have a predetermined amount of Gas assigned to them, which is a measurement unit for the cost of processing power smart contract is incurring on the EVM. This operational measurement is the building block for every transaction fee we all pay on the network. Another thing to note is that the EVM executes bytecodes, which are similar to opcodes but are represented in hexadecimal numbers.
In the world of Ethereum, gas plays a critical role in facilitating operations within the Ethereum Virtual Machine (EVM). When you initiate an operation that impacts the EVM’s state, by default, the smallest amount of gas you need is 21000 units of gas in reserve, e.g. for transferring Ethers between two accounts. Additionally, if you want to execute a function on a smart contract, that same 21000 units of gas is a prerequisite, along with any additional fuel that may be required to ensure the function operates smoothly. Essentially, gas is the “fuel” that enables the EVM to work, allowing complex transactions to occur on the Ethereum network. In other words, executing a smart contract function would require 21000 gas plus any additional gas required to perform each necessary opcode.
Now, there is an exception to the gas consumption rule when it comes to read-only and straightforward functions, which we refer to as “view” functions. These functions do not alter the state of the EVM, and thus their execution is considered free and immediate. In essence, calling a view function within a “Call” on a local node won’t require any gas. But, if you attempt to call the same function from a deployed smart contract during a “Transaction,” then gas consumption will be a factor to consider.
It’s critical to keep in mind that if the gas necessary for operations exceeds the gas limit, the operation will fail, and any changes you made will be reversed. But the real bummer is that you still lose the gas you’ve used, making it a costly mistake. If you set a higher gas limit than needed, the operation will still be carried out, but only the necessary amount of gas will be spent. Given that it’s challenging to estimate, beforehand, how much gas a transaction needs exactly, it’s wise to be cautious when setting the gas limit. i.e not to set the gas limit too high – if there is a bug or error in the smart contract, exceeding the gas limit could result in significant resource losses, and it could end up using more gas than planned. For example, imagine putting too much water in a glass – the same thing could happen if you set your gas limit too high. Just like how the glass can overflow and spill water everywhere, exceeding the gas limit could cause you to lose gas and resources.
The total gas fee that you’ll eventually pay is determined by multiplying total gas units used
it by gas price
. And here’s the kicker: the gas price
isn’t fixed – it’s determined by a systematic procedure laid out in theEIP-1559
. Understanding how gas prices work is essential to managing your transaction fees effectively too. I will not go deeper into it in this article, but I recommend you check theEIP-1559
which directly determines how a gas unit is priced in ethereum and major EVM-based blockchains today. You can simply get the gas price and limit information from Etherscan or Eth Gas Station websites. EIP-1559
‘s proposed changes to transaction fees could affect the amount of demand and congestion on the network, and thus indirectly influence the determination of the block’s gas limit.
There is also a gas limit for every block to prevent spam attacks and ensure the network runs smoothly. This means while the EVM is technically Turing-complete, in practice, there are restrictions on what can be computed due to the gas limit. Essentially, the gas limit acts as a kind of safeguard that prevents the misuse of the EVM and helps keep the Ethereum network secure and stable. In the new PoS Ethereum chain, validators will vote on the size of the block gas limit, depending on network demand.
Ethereum memory types and best practices for reducing gas costs
When developing smart contracts on the Ethereum blockchain, developers have access to different types of memory to store and manipulate data. These include the stack
, memory
, storage
, calldata
, and the event log
. Each type of memory has its own specific functions and limitations. In this post, we’ll dive deeper into the different types of memory available in Ethereum and explain how memory usage affects the gas cost of smart contract execution.
The Stack
The stack
is used to store small local variables and is almost free to use. However, it has a limited storage capacity compared to other memory types. All operations used to manipulate the stack, including PUSH
, POP
, COPY
, and SWAP
, incur a gas cost, which increases based on the size of the data being manipulated.
The stack
can be volatile, meaning that its storage is not persistent and is erased when the function execution completes. This makes it a useful tool for temporary variables that do not need to be stored long-term.
Memory
Memory
is used to store temporary values generated during execution, such as function call parameters. It is erased at the beginning of every function call and can be accessed using the MLOAD, MSTORE, and MSTORE8 instructions.
All operations used to manipulate memory come with a gas cost, similar to the stack
. However, memory
usage tends to be less expensive than storage
. This is because the data stored in memory
is not permanent and does not need to be replicated across the network to maintain consistency.
Storage
Storage
, also known as persistent memory, is more expensive to use than both the stack
and memory
. This is because the data stored in the storage
is permanently recorded in a database that is replicated across tens of thousands of nodes, making it much more expensive to write or read data from the disk.
Each contract has its own persistent storage, and operations used to read from or write to the storage incur a higher gas cost than other memory types. Storage should only be used for data that needs to be stored long-term, such as smart contract state variables, rather than temporary data.
Calldata
Calldata
is a special type of memory that contains function arguments and is only available for external function call parameters. Calldata
is read-only and has a limited size, meaning that it can only be accessed using certain instructions, such as CALLDATALOAD
.
Calldata
operations have a lower gas cost than storage operations, similar to memory. However, the limited size of calldata
means that it is not suitable for storing data that needs to persist beyond a single transaction.
Event Log
The event log
is a type of memory where data related to events raised by smart contracts are stored. It allows smart contracts to communicate with external applications and other smart contracts by broadcasting events to the network.
The event log
is not accessible by smart contracts directly and can only be accessed by external applications. As a result, event log
operations do not affect the gas cost of smart contract execution.
Optimizing Smart Contract Efficiency and Cost-Effectiveness
All operations used to manipulate memory, including those affecting memory usage, come with a gas cost. However, the gas cost associated with each type of memory varies significantly based on its persistence, size, and usage frequency. For example, storage operations have a much higher gas cost than stack or memory operations due to the permanent nature of stored data.
Developers must carefully balance memory usage in their smart contracts to optimize gas costs and minimize execution times. This includes choosing the appropriate type of memory based on the specific requirements of the smart contract, minimizing the amount of data stored in storage, and using memory and calldata
where possible to reduce gas costs.
Developers seeking to build smart contracts on the Ethereum blockchain must take into account the various types of memory available and their impact on gas costs. Having knowledge of memory usage in Ethereum is necessary to build cost-effective and efficient smart contracts. Optimizing memory usage can provide significant advantages in both performance and cost-effectiveness. Although memory usage may seem complicated, it is worth investing time to understand and optimize it for the best results.
Lessons Learned
The optimization of smart contracts to save gas on transactions is vital to reduce costs in blockchain transactions. Developers must understand the gas mechanism in Ethereum Virtual Machine (EVM) and different memory types to minimize storage
usage and use memory
and calldata
to reduce gas costs. Optimizing memory usage can lead to significant advantages in performance and cost-effectiveness, making it essential for developers to learn and implement best practices to build efficient and cost-effective smart contracts on the Ethereum blockchain.
In addition to understanding memory types, developers must learn about the Ethereum Opcodes used during smart contract development. The Ethereum Opcodes have a predetermined gas cost that increases depending on the size of the data being manipulated. Optimizing the use of Opcodes is essential in reducing gas costs for smart contract execution. Therefore, developers must become knowledgeable in the gas mechanism in EVM and understand the different types of memory available to create effective and cost-efficient smart contracts on the Ethereum blockchain.
In my next post, I will dive deeper into specific Solidity Design Patterns that help with saving gas costs in your smart contracts.