
SolidityBlockchainSmart Contracts
Gas-Jitsu: Mastering Solidity Optimization
Gas-Jitsu: Mastering Solidity Optimization
In the world of Ethereum development, gas is money. Literally. Every computation, every storage update, and every byte of code costs real ETH (or Matic, or AVAX). writing gas-efficient Smart Contracts isn’t just best practice—it’s an economic necessity.
Welcome to Gas-Jitsu, the art of squeezing every ounce of efficiency from the Ethereum Virtual Machine (EVM).
1. Storage Packing: The Tetris of Solidity
The EVM works in 32-byte slots. When you define variables, Solidity tries to pack them into these slots. If you arrange them poorly, you pay for extra slots.
Bad Packing:
solidity
1uint128 a; // Slot 0 (16 bytes)
2uint256 b; // Slot 1 (32 bytes - doesn't fit in Slot 0)
3uint128 c; // Slot 2 (16 bytes)
4// Total slots uses: 3Good Packing:
solidity
1uint128 a; // Slot 0
2uint128 c; // Slot 0 (Both fit in 32 bytes!)
3uint256 b; // Slot 1
4// Total slots uses: 2Savings: ~20,000 gas per saved slot on deployment and writes.
2. Memory vs. Calldata
When passing arrays or strings to functions, the keyword copies the data. For functions, using reads directly from the transaction input, avoiding an expensive copy.
text
1memorytext
1externaltext
1calldataExpensive:
solidity
1function process(uint[] memory data) external {
2 // Copies data to memory
3}Cheap:
solidity
1function process(uint[] calldata data) external {
2 // Reads directly from calldata
3}Savings: Significant reductions for large arrays.
3. Custom Errors vs. Strings
Prior to Solidity 0.8.4, we used detailed string messages in . These strings take up storage and cost gas to emit. Custom errors were introduced to solve this.
text
1requireBefore:
solidity
1require(balance >= amount, "Insufficient balance for transfer");After:
solidity
1error InsufficientBalance();
2
3if (balance < amount) {
4 revert InsufficientBalance();
5}Savings: Custom errors are much cheaper to deploy and execute because they are just a 4-byte selector, not a long string.
4. Unchecked Arithmetic
Solidity 0.8.0+ includes built-in overflow protection. This is great for security but adds overhead. If you are 100% sure a calculation won't overflow (like incrementing a counter in a bounded loop), use .
text
1uncheckedStandard Loop:
solidity
1for (uint i = 0; i < length; i++) {
2 // Hidden standard check: i++ checks for overflow
3}Gas-Jitsu Loop:
solidity
1for (uint i = 0; i < length;) {
2 // do work
3 unchecked { i++; } // No overflow check
4}Savings: ~30-40 gas per iteration. It adds up in long loops!
5. Short-Circuiting
The EVM stops evaluating boolean expressions as soon as the result is determined. Order your conditions by cost!
Inefficient:
solidity
1// heavyOperation() runs even if condition is false
2if (heavyOperation() && condition) Efficient:
solidity
1// heavyOperation() never runs if condition is false
2if (condition && heavyOperation())Put cheap checks (like boolean flags or simple comparisons) before expensive checks (like external calls or hashing).
Conclusion
Gas optimization is a balancing act between readability, security, and efficiency. Never sacrifice security for gas—saving $5 isn't worth a $5M hack. But with these Gas-Jitsu techniques, you can write contracts that are lean, mean, and cheap to execute.
Go forth and optimize!
Discussion
Powered by Giscus