Using Solidity's immutable Keyword for Gas‑Efficient Constructor‑Only Variables
Learn how to declare Solidity immutable variables to store constructor‑only values in bytecode, reduce gas costs, and avoid accidental modification after deployment.
02 Jun 2026, 15:57 UTC

Desired outcome
Declare a state variable that can be set only once during contract construction, store its value in the contract’s bytecode, and read it later with lower gas cost than a regular storage variable.
Prerequisites
- Solidity compiler version 0.6.5 or newer (the
immutablekeyword was introduced in 0.6.5). - A development environment that can compile Solidity contracts (e.g., Hardhat, Foundry, Remix).
- Basic understanding of constructors, state variables, and gas measurement.
Focused procedure
1. Declare the immutable variable
Choose a type that Solidity allows for immutables (uint, int, bool, address, fixed‑size bytes, or a struct whose members are all elementary types). Add the immutable after the type and optionally a visibility modifier.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract Token {
// immutable variable that will hold the token's name
string public immutable tokenName;
uint256 public immutable totalSupply;
constructor(string memory _name, uint256 _supply) {
tokenName = _name;
totalSupply = _supply;
}
function name() external view returns (string memory) {
return tokenName;
}
function supply() external view returns (uint256) {
return totalSupply;
}
}
2. Assign the value in the constructor
The only place where an immutable can be written is inside the contract’s constructor (or a constructor of a base contract that is executed during deployment). The assignment must happen before the constructor ends; otherwise the transaction reverts.
3. Read the immutable variable
Access the variable exactly as you would a normal state variable. The compiler replaces the read with a constant load from the bytecode, which avoids a storage read (SLOAD) and instead uses a cheap constant operation.
4. Compile and inspect the bytecode (optional verification step)
After compiling with solc, examine the generated bytecode. The immutable’s value appears as a pushed constant in the constructor code and as a PUSH opcode in the getter.
# Example using solc from the command line
solc --bin Token.sol
Look for sequences like 608060405234801561001057600080fd5b5060008054 followed by a PUSH that holds the string length and characters of tokenName.
5. Deploy and test on a local testnet
Deploy the contract using your preferred framework, passing the constructor arguments. Then call a view function that returns the immutable.
# Hardhat example (run in a terminal with Hardhat initialized)
npx hardhat run scripts/deploy.js --network localhost
The deployment transaction will include the constructor arguments in its calldata. After deployment, a call to name() should return the exact string supplied in the constructor.
Expected checks
- The contract compiles without warnings about immutable usage.
- Bytecode inspection shows the immutable’s value as a constant, not a storage slot.
- Calling a view function that reads the immutable returns the value set in the constructor.
- Gas measurement (e.g., using
hardhat gas-reporterorforge snapshot) shows a reduction of roughly 3–5 k gas per read compared to a regularuint256state variable. - Attempting to write to the immutable outside the constructor results in a compile‑time error.
Relevant recovery options
Because immutables cannot be changed after deployment, the only recovery path is to redeploy the contract with a corrected value if the constructor fails or the wrong arguments are supplied. Ensure that constructor arguments are validated (e.g., non‑empty strings, non‑zero supplies) before sending the deployment transaction.
Limitations
- Immutables cannot be used in libraries that are linked after deployment; their value is baked into the deploying contract’s bytecode only.
- Only elementary types or structs containing exclusively elementary types are allowed; dynamic arrays, mappings, or nested structs are not supported.
- If a proxy upgrade pattern is used, the immutable’s value remains tied to the original implementation’s bytecode and cannot be altered by the proxy.
- Debugging tools that inspect storage may not show the immutable’s value until the contract is deployed to a live chain; rely on bytecode inspection or view function calls for verification.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.