What Is Gas Golfing?
Gas golfing is the practice of making small, highly focused changes to smart contract code to reduce its gas consumption.
The term is inspired by code golf, a programming challenge in which developers try to solve a problem with the smallest possible amount of source code.
In cryptocurrency development, the goal is not necessarily to write the fewest characters.
The goal is to produce bytecode that consumes fewer blockchain resources while preserving the contract’s required behavior.
Gas golfing is most commonly associated with Ethereum and other networks that execute smart contracts through the Ethereum Virtual Machine.
Developers may gas golf a contract by reducing storage operations, simplifying calculations, shortening revert data, avoiding unnecessary memory copies, or selecting lower-cost EVM instructions.
Gas golfing usually focuses on micro-optimizations rather than a complete redesign of the application.
It is therefore narrower than general gas optimization, which can include contract architecture, transaction batching, layer-2 deployment, application design, and off-chain computation.
A successful gas-golfing change must preserve security, correctness, readability, and compatibility.
Saving a small amount of gas is not worthwhile when the change creates a vulnerability or makes the contract impossible to maintain safely.
Why Is It Called Gas Golfing?
The word golfing refers to the goal of achieving a lower score.
In traditional golf, a lower number of strokes is better.
In smart contract gas golfing, a lower amount of gas is generally considered better when the optimized code performs the same task safely.
Developers may compare two implementations by measuring deployment gas, runtime gas, bytecode size, or the total cost across the contract’s expected lifetime.
A gas-golfing challenge may ask participants to implement a function using the smallest possible amount of gas.
Real production development is more complicated because the lowest-gas solution may not be the safest or easiest solution to audit.
The term is informal and does not describe an Ethereum protocol, token, transaction type, or official programming standard.
How Gas Golfing Works
Ethereum assigns a gas cost to every operation performed by the Ethereum Virtual Machine.
The official Ethereum gas documentation explains that gas measures the computational effort required to execute transactions and smart contract operations.
Arithmetic, memory use, persistent storage, event logs, contract calls, contract creation, and transaction data all contribute to gas consumption.
Gas golfing looks for a less expensive sequence of operations that produces the same required result.
For example, a developer may replace several storage reads with one storage read and reuse the loaded value from a local variable.
Another developer may replace a long revert string with a compact custom error.
A developer working at a lower level may replace a manually constructed memory-copying loop with an EVM instruction designed specifically for memory copying.
The final improvement must be measured on the compiled bytecode because visually shorter Solidity code does not always produce cheaper EVM execution.
Gas Golfing vs. Gas Optimization
Gas optimization is the broad process of reducing the cost of smart contract deployment and execution.
Gas golfing is a narrower form of optimization that usually emphasizes small code-level savings.
A complete gas optimization project may redesign the application’s storage model, move suitable computation off-chain, use a layer-2 network, or reduce the number of transactions required from each user.
Gas golfing may instead compare two loop structures, two error-handling methods, or two methods for loading the same value.
Architectural optimization usually provides larger savings than micro-optimization.
However, a small recurring saving can become significant when a function is executed millions of times.
Professional developers should first remove unnecessary work at the architectural level and then gas golf the important remaining execution paths.
Gas Golfing vs. Code Golf
Code golf attempts to minimize source-code length, often without prioritizing readability or long-term maintenance.
Gas golfing attempts to minimize blockchain execution cost.
The shortest Solidity expression may compile into more instructions than a longer and clearer expression.
Compiler optimization may also transform several different source-code styles into identical bytecode.
Developers should therefore compare compiled output and measured gas rather than counting source characters.
A code-golf solution may be entertaining but unsuitable for a contract that controls valuable cryptocurrency.
Production gas golfing should always include security tests, documentation, and review.
Gas Golfing vs. Lower Gas Prices
Gas golfing reduces the number of gas units consumed by a transaction.
It does not directly reduce the market price paid for each gas unit.
The transaction fee can be represented as Gas Charged × Effective Gas Price.
A gas-golfing change targets the gas-charged part of this formula.
Network demand, the protocol base fee, and the user’s priority fee affect the effective gas price.
A contract can be highly optimized and still be expensive to use during severe network congestion.
A poorly optimized contract may also remain wasteful even when the gas price is temporarily low.
Why Developers Practice Gas Golfing
Gas golfing can reduce the cost paid by every user who interacts with a frequently called smart contract function.
Lower transaction costs can make decentralized finance, token transfers, blockchain games, NFT operations, and governance systems more accessible.
Gas golfing can also reduce the cost of deploying a contract when the optimization decreases initialization work or runtime bytecode size.
Automated cryptocurrency strategies may depend on small gas savings because transaction fees directly reduce their expected returns.
Protocols that perform many repeated internal operations may save substantial amounts even when each individual improvement is small.
Lower gas usage also leaves more block capacity available for other transactions.
However, optimization should be based on expected usage rather than the desire to produce the lowest possible benchmark for an unrealistic test case.
Measure Before Gas Golfing
Developers should measure gas usage before attempting a micro-optimization.
The existing compiler may already remove the apparently unnecessary operation.
A modification that reduced gas in an older Solidity version may provide no benefit in a current compiler.
Another modification may reduce runtime gas while increasing contract deployment cost.
Gas tests should cover the functions that users execute most frequently.
They should also cover minimum inputs, maximum supported inputs, successful execution, and failure paths.
The Solidity compiler documentation describes compiler output options and gas estimates.
Compiler estimates may be incomplete when loops, external calls, or dynamic blockchain state affect execution.
Developers should therefore combine compiler output with actual transaction tests and execution traces.
Use a Current Solidity Compiler
Solidity compiler releases regularly add optimizations, EVM support, language features, and security fixes.
The official Solidity 0.8.36 release announcement identifies version 0.8.36 as the current release in July 2026.
That release includes security fixes and further work on an experimental SSA-form code-generation pipeline.
A gas-golfing result produced by one compiler version may not match the result produced by another version.
Developers should pin the compiler version, optimizer configuration, EVM target, and dependency versions used for production builds.
They should also review the official Solidity compiler bug list before deploying valuable cryptocurrency contracts.
Updating a compiler only for lower gas usage without retesting the full application can introduce unexpected behavior or bytecode differences.
Use the Solidity Optimizer Before Manual Golfing
The Solidity optimizer can simplify expressions, remove redundant operations, combine calculations, and reduce bytecode size.
The official Solidity optimizer documentation explains that optimization can reduce both deployment size and execution cost.
Manual gas golfing should account for what the optimizer already does.
Two visibly different Solidity functions may compile into the same optimized bytecode.
The optimizer’s runs setting influences the tradeoff between smaller deployment code and lower recurring execution costs.
A low runs value generally gives greater weight to deployment size.
A higher runs value generally gives greater weight to repeated runtime execution.
The best setting depends on how often the contract will be deployed and how often each function will be called.
Developers should compare several tested configurations instead of using one traditional value without measurement.
Cache Repeated Storage Reads
Persistent storage access is often more expensive than using a value already available on the EVM stack or in memory.
A frequently used gas-golfing technique is to load a storage value once into a local variable and reuse it.
Ethereum applies cold and warm access costs under EIP-2929.
The first access to a storage slot in a transaction is generally more expensive than later access to the same slot.
Even warm storage reads can be avoided when the contract already has a correct local copy.
A developer may also calculate a final result locally and perform one storage write instead of writing each intermediate value.
Caching is unsafe when an external call can change the relevant state before the cached value is used again.
Reentrancy, callbacks, delegate calls, and inherited behavior must be considered before applying this technique.
Reduce Storage Writes
Writing persistent state is one of the most expensive common smart contract operations.
A contract should avoid writing a value when the requested value is already stored.
It should avoid recording information that can be derived safely from existing state.
Several related values may sometimes be represented by one accumulated index or accounting checkpoint.
A function may also perform calculations locally and commit only the final result to storage.
These changes can produce much larger savings than rewriting a small arithmetic expression.
Developers must confirm that the simplified state model still supports correct balances, permissions, historical accounting, and upgrades.
Pack Storage Variables
Ethereum divides contract storage into 32-byte slots.
Solidity can pack several smaller value-type variables into one slot when their order and combined size allow it.
The Solidity storage-layout documentation explains how variables are assigned and packed.
Reducing the number of required storage slots can lower deployment and runtime gas in suitable cases.
Smaller integer types do not automatically save gas when they are stored separately.
The EVM normally performs arithmetic with 256-bit words, so smaller types may require extra masking or conversion.
Packing is most helpful when the packed values are commonly accessed or changed together.
Storage variables must not be reordered in an already deployed upgradeable contract because the new layout may interpret existing data incorrectly.
Use Constants and Immutable Values
A normal state variable creates storage costs when the value must be read from persistent state.
A value known at compile time may be declared
constant
.
A value selected during construction and fixed after deployment may be declared
immutable
.
The Solidity contract documentation explains that these values do not use ordinary storage slots in the same way as mutable state variables.
Permanent addresses, mathematical values, and fixed configuration limits are common candidates.
A value should not be made immutable when the application genuinely requires an authorized update process.
Saving gas by removing necessary configuration flexibility can create a costly or dangerous operational limitation.
External function inputs that do not need to be modified can often remain in
calldata
.
Using calldata can avoid copying a large string, byte sequence, array, or struct into memory.
The Solidity data-location documentation explains the differences among calldata, memory, storage, and transient storage.
This technique is most useful for dynamic external inputs that the function only reads.
Memory remains necessary when the contract must modify the value or construct new in-memory data.
Developers should also remove unnecessary transaction input because calldata bytes contribute to intrinsic gas cost.
Encoding a value more compactly can save calldata gas, but the decoding computation must be included in the comparison.
Use Custom Errors
Custom errors can reduce contract bytecode and revert-data costs compared with long error strings.
A custom error uses a compact four-byte selector and can include structured parameters.
The official Solidity custom-error documentation describes custom errors as a gas-efficient method for reporting failures.
For example, an error can include the caller’s address and the required balance without embedding a long sentence into the runtime bytecode.
A custom error does not make the successful execution path free because the contract must still evaluate the condition.
Errors should remain understandable enough for wallets, interfaces, auditors, and developers to diagnose failed cryptocurrency transactions.
Order Conditions for Short-Circuit Evaluation
Solidity Boolean expressions can stop early when the final result is already known.
In an expression using logical AND, evaluation can stop after the first false condition.
In an expression using logical OR, evaluation can stop after the first true condition.
Placing a cheap condition before an expensive condition may reduce average gas when the cheap condition often determines the result.
This technique should preserve the intended logical behavior and any assumptions about functions that may revert or have side effects.
Conditions should not be reordered blindly when the order is relevant to safety or error reporting.
Optimize Loops Carefully
A loop can consume large amounts of gas when it processes many elements.
Developers may cache a repeatedly accessed array length when the collection cannot change during the loop.
They may also cache storage values used by every iteration.
A loop counter may use an
unchecked
increment when overflow is mathematically impossible.
Modern compilers already optimize some common increment patterns, so the saving must be measured with the selected compiler.
The common claim that prefix increment is always cheaper than postfix increment is not a reliable universal rule for current optimized Solidity code.
An unbounded loop over a growing storage collection is an architectural problem rather than a minor gas-golfing opportunity.
Large workloads should be divided into bounded batches or redesigned so that users process their own independent state.
Use Unchecked Arithmetic Only With Proof
Solidity 0.8 and later normally checks integer arithmetic for overflow and underflow.
These checks consume some gas but prevent important classes of programming errors.
An
unchecked
block removes the automatic check for the operations inside it.
This can save gas in situations where mathematical bounds already prove that overflow cannot occur.
A bounded loop counter is a common example, although the exact safety argument depends on the loop design.
Unchecked arithmetic should not be used merely because the expected input usually remains small.
The code should include tests and clear documentation showing why every reachable input remains safe.
Use Transient Storage for Temporary State
Transient storage provides transaction-scoped state that is automatically cleared when the transaction ends.
Ethereum introduced the
TLOAD
and
TSTORE
operations through
EIP-1153.
Transient storage can be cheaper than persistent storage when data is needed across calls but not across transactions.
A reentrancy lock is a common example of transaction-scoped information.
Transient storage cannot replace persistent balances, ownership, debt, or configuration needed in later transactions.
Developers must understand how transient state behaves across calls, delegate calls, and reverts.
Replacing a proven security control with a lower-cost transient implementation requires complete testing and review.
Use Modern EVM Instructions
Ethereum upgrades can introduce instructions that replace more expensive sequences of older operations.
EIP-3855 introduced
PUSH0
, which places zero on the stack with a compact instruction.
EIP-5656 introduced
MCOPY
, which provides a dedicated operation for copying memory.
A current Solidity compiler can use supported EVM instructions automatically when the correct EVM version is selected.
Developers usually should not replace compiler-generated code with handwritten assembly merely to force one instruction.
A contract compiled for a new EVM target may fail on a network that has not activated the required instructions.
Gas-golfing results must therefore identify the exact compiler and EVM target used in the measurement.
Reduce External Calls
External contract calls create costs for account access, argument encoding, return-data processing, and the called contract’s execution.
A contract may save gas by avoiding repeated calls that return the same value during one transaction.
Several related reads may sometimes be combined into one call that returns a structured result.
However, changing call structure can affect reentrancy, error handling, composability, and contract boundaries.
Return values and success conditions must still be checked correctly.
A cheap call that produces an unsafe assumption is not a valid optimization.
Use Events Instead of Storage When Appropriate
Event logs are often less expensive than persistent storage for information used only by off-chain applications.
Events can support transaction histories, analytics, activity feeds, and user-interface notifications.
Future smart contract execution generally cannot search historical event logs.
Balances, permissions, ownership, collateral, and other enforceable state must therefore remain accessible to the contract.
Gas golfing with events is appropriate only when the removed storage value is not needed for future on-chain decisions.
Developers should also consider the cost of indexed event topics and log data when designing the event.
Reduce Deployment Bytecode
Ethereum charges gas when a contract’s runtime bytecode is stored during deployment.
Removing unused functions, duplicated logic, long revert strings, and unnecessary embedded data can lower deployment cost.
Custom errors, internal libraries, shared implementations, and carefully configured compiler optimization may reduce code size.
Ethereum limits normal deployed runtime code under EIP-170.
Initialization code is separately metered and limited under EIP-3860.
A smaller contract is not automatically cheaper across its full lifetime because splitting code among several contracts can add repeated external-call costs.
Developers should evaluate deployment cost and recurring execution cost together.
Understand Gas Refund Limitations
Older Ethereum gas-golfing strategies sometimes depended heavily on creating and later deleting storage.
Current Ethereum rules greatly limit that approach.
EIP-3529 reduced storage-clearing refunds, removed the former
SELFDESTRUCT
refund, and capped applied refunds at 20% of gross gas use.
A contract should not create unnecessary state in the hope of receiving an equal or larger refund later.
Gas refunds are applied after execution and cannot prevent an out-of-gas failure.
SELFDESTRUCT
is also not a modern gas-golfing technique because it provides no refund and its deletion behavior has been restricted.
Calldata Golfing and EIP-7623
Developers sometimes gas golf transaction input by using compact types, bit packing, custom encodings, or shorter representations.
Reducing transaction bytes can lower intrinsic gas, particularly when many repeated values are removed.
However, Pectra activated EIP-7623, which introduced a higher gas floor for data-heavy transactions with relatively little execution.
The decoding operations required by a compact format also consume gas.
A custom encoding may reduce cost for large repeated workloads but provide no benefit for small transactions.
Nonstandard encoding can make wallets, audits, integrations, and debugging more difficult.
Developers should benchmark the full encoding and decoding process under current protocol rules.
When Inline Assembly Is Appropriate
Inline assembly gives developers direct control over EVM instructions, memory, storage, calls, and return data.
It can provide gas savings when high-level Solidity cannot express a specialized operation efficiently.
Assembly is commonly considered for cryptographic routines, compact data parsing, unusual memory operations, and heavily repeated low-level functions.
It also bypasses many type, memory, and safety protections provided by Solidity.
An assembly error can corrupt memory, encode data incorrectly, mishandle return values, or expose cryptocurrency to theft.
Every assembly implementation should be compared with a clear high-level reference implementation.
Tests should confirm identical behavior across normal inputs, boundary inputs, malicious inputs, and reverts.
When Gas Golfing Becomes Dangerous
Gas golfing becomes dangerous when gas cost receives greater priority than contract security and clarity.
Removing access-control checks to save gas can allow unauthorized users to control the contract.
Removing a reentrancy guard can expose balances to repeated external calls.
Removing slippage limits or deadlines can expose users to unfavorable cryptocurrency execution.
Combining many values into one packed word can introduce bit-masking and conversion errors.
Replacing standard encoding with a custom format can create signature, replay, or parsing vulnerabilities.
An optimization that saves 100 gas but creates a chance of losing user funds has negative practical value.
Outdated Gas Golfing Advice
Gas-golfing advice can become outdated when Solidity and the EVM change.
A compiler may begin optimizing a pattern that previously required a manual rewrite.
A network upgrade may change the price of an opcode or add a more efficient instruction.
An old recommendation to use
SELFDESTRUCT
for refunds is no longer valid on current Ethereum.
A claim that one increment style is always cheaper may not apply to modern optimized bytecode.
A recommendation to use a very small integer may fail to save gas unless storage packing occurs.
Developers should require current benchmarks and reproducible compiler settings before adopting any gas-golfing tip.
How to Evaluate a Gas-Golfing Change
The optimized implementation must first produce the same required behavior as the original implementation.
Developers should compare deployment gas, successful runtime gas, failure-path gas, and total expected lifecycle cost.
They should identify which compiler, optimizer settings, EVM version, and blockchain state were used in testing.
Unit tests should verify normal function behavior.
Fuzz testing should explore unexpected inputs and boundary conditions.
Invariant testing should confirm that essential accounting and security properties remain true.
Execution traces should confirm that the saving comes from the expected operations rather than an accidentally skipped requirement.
Human reviewers should determine whether the change remains understandable and maintainable.
Gas Golfing in Production Contracts
Production gas golfing should focus on frequently used functions and well-measured bottlenecks.
A minor saving in a function executed millions of times may justify careful implementation work.
A similar saving in a one-time administrative function may not justify increased complexity.
Public interfaces and expected behavior should remain stable unless the optimization is part of a planned protocol upgrade.
Upgradeable contracts must preserve their storage layout and authorization model.
High-value contracts should receive an independent security review after substantial low-level optimization.
The deployed bytecode should be reproducible from the published source code and build configuration.
Common Gas Golfing Mistakes
A common mistake is comparing source-code length instead of compiled gas usage.
Another mistake is testing without enabling the same optimizer settings used for production.
Developers may measure only successful transactions and ignore an unusually expensive revert path.
They may optimize a function that is rarely used while ignoring a repeated storage write in every transaction.
They may use smaller integer types without obtaining any storage-packing benefit.
They may replace clear Solidity with assembly before confirming that the compiler-generated code is actually expensive.
They may rely on an old gas schedule that no longer reflects the current EVM.
The most serious mistake is accepting a lower gas result without proving that the optimized version has identical secure behavior.
FAQ
What is gas golfing in simple terms?
Gas golfing means making small code-level changes that reduce the gas consumed by a smart contract without changing its intended behavior.
Is gas golfing the same as gas optimization?
No, gas golfing is usually a narrow form of micro-optimization, while gas optimization also includes architecture, storage design, off-chain computation, batching, and network selection.
Is gas golfing an Ethereum protocol feature?
No, it is an informal developer term rather than an official opcode, transaction type, or Ethereum standard.
Does shorter Solidity code always use less gas?
No, source-code length does not reliably predict the size or execution cost of the compiled EVM bytecode.
The optimizer performs many similar transformations, but developers must still design efficient storage, data flow, and contract architecture.
What is the best gas-golfing technique?
The highest-value technique often depends on the contract, although reducing repeated storage access usually provides more benefit than changing minor arithmetic expressions.
Are smaller integers always cheaper?
No, smaller integers are most useful when they enable several values to share one storage slot.
Is calldata always cheaper than memory?
Calldata is often cheaper for read-only external inputs because it avoids a copy, but the correct location depends on how the data must be used.
Why are custom errors useful for gas golfing?
Custom errors use compact selectors and parameters instead of embedding and returning long revert strings.
Does caching a storage value always save gas?
It can save gas when the value remains valid, but caching may be unsafe if an external call can change the state.
Is unchecked arithmetic a safe optimization?
It is safe only when developers can prove that overflow or underflow is impossible for every reachable input.
Should gas golfers use inline assembly?
Inline assembly should be limited to measured bottlenecks because it can introduce serious memory, encoding, and security errors.
Does prefix increment always cost less than postfix increment?
No, current compiler optimization may generate equivalent code, so the exact result must be measured.
Can events replace contract storage?
Events can replace storage only for information that future smart contract execution does not need to read or enforce.
Can gas golfing make a transaction free?
No, every transaction still pays for required execution, data, and state use under the network’s fee rules.
Does gas golfing reduce gas price?
No, it reduces gas usage, while gas price changes with network demand and transaction fee settings.
Are gas refunds a gas-golfing method?
Eligible storage clearing can provide a limited refund, but current rules cap refunds and no longer support older refund-heavy strategies.
Can gas golfing create security risks?
Yes, aggressive compression, unchecked arithmetic, assembly, and removed validation can create vulnerabilities if they are not carefully reviewed.
How should gas-golfing results be tested?
They should be tested with fixed compiler settings, realistic inputs, execution traces, fuzz tests, invariants, and security review.
When is gas golfing worthwhile?
It is most worthwhile when a safe change reduces the cost of a function that users or automated systems execute frequently.
Conclusion
Gas golfing is the practice of making focused smart contract changes that reduce deployment or execution gas.
It is related to gas optimization but usually concentrates on smaller code-level improvements rather than complete application redesign.
Common gas-golfing methods include caching storage reads, reducing storage writes, packing variables, using calldata, selecting custom errors, simplifying loops, and using modern EVM features.
The effect of each method depends on the compiler version, optimizer settings, EVM target, input values, and blockchain state.
Advice that produced savings in an older Ethereum environment may no longer work under current compiler and protocol rules.
Developers should measure compiled bytecode rather than judging efficiency by the appearance or length of Solidity source code.
Architectural improvements should normally be considered before low-level micro-optimization.
Inline assembly and unchecked operations should be limited to situations where their savings are measurable and their safety can be proven.
Every gas-golfing change must preserve contract behavior, security, readability, and compatibility.
The best gas-golfing result is not simply the smallest gas number but the lowest safe cost for delivering the required cryptocurrency functionality.