Using Vyper Immutables for Gas‑Efficient, Unchangeable Contract Parameters
Vyper’s immutable variables let you store constants on‑chain without the cost of regular storage reads. This blog explains how they work, shows a concrete example, compares gas usage, and discusses when immutables are the right choice.
19 Feb 2026, 10:26 UTC

Concrete Problem: Storage Reads Cost Gas
Every time a Solidity or Vyper contract reads a value stored in the EVM’s state, it pays a SLOAD opcode cost of 800 gas (plus a 200‑gas base). For contracts that expose a public getter or perform frequent checks, these costs add up quickly. If the value never changes, you’re paying for a mutable slot that is effectively constant.
Thesis: Immutable Variables Turn State Into Bytecode
Vyper’s immutable keyword lets you declare a variable that is assigned only once in the constructor. After deployment, the value is baked into the contract’s bytecode, so future reads are a cheap PUSH of a literal, not a storage read. This saves gas and guarantees the value can never be altered accidentally.
How Immutables Work in Vyper
- Declaration:
owner: immutable(address)– the type is declared as immutable. - Assignment: In the constructor you set it once:
owner = msg.sender. - Storage slot: No slot is allocated; the value is a constant in the bytecode.
- Read access: The compiler generates a literal
PUSHopcode when the getter is called.
Because the value is fixed at deployment, you cannot use runtime data (e.g., block.timestamp) for an immutable.
Worked Example: Token Decimals and Protocol Fee
# @version 0.3.10
name: immutable(String[64])
symbol: immutable(String[32])
decimals: immutable(uint256)
protocol_fee: immutable(uint256)
@external
def __init__(
_name: String[64],
_symbol: String[32],
_decimals: uint256,
_protocol_fee: uint256
):
name = _name
symbol = _symbol
decimals = _decimals
protocol_fee = _protocol_fee
# Public getters are auto‑generated by Vyper
Compile with:
vyper --version 0.3.10 token.vy
After deployment, the constructor bytecode contains the literal values for name, symbol, decimals, and protocol_fee. No SSTORE opcodes appear.
Gas Cost Comparison
- Deploy a contract with a normal storage variable:
- Constructor:
SSTORE(20000 gas). - Getter call:
SLOAD(800 gas). - Deploy the same contract using
immutable: - Constructor:
PUSH+CALLDATACOPY(≈ 200 gas). - Getter call:
PUSH(≈ 3 gas).
In practice, you’ll see a 97% reduction in read cost. Tools like foundry’s gas reporter or etherscan gas tracker can confirm this difference by measuring gasleft() before and after the getter call.
Trade‑Offs and Limitations
- No Post‑Deployment Change: Once set, an immutable cannot be updated. If you need to adjust a fee or address, you must deploy a new contract or use a proxy pattern.
- Construction Cost: The constructor must include the value, so you can’t set it from an external source after deployment.
- Runtime Constraints: Immutables cannot depend on
block.timestamp,msg.sender, or other dynamic data. - Upgrade Path Complexity: For contracts that may evolve, consider a proxy with mutable state or a configuration contract.
Actionable Takeaway
Use Vyper immutables for constants that are truly constant: token decimals, fixed fee percentages, or addresses of trusted contracts that will never change. They give you:
- Substantial gas savings on read operations.
- Built‑in protection against accidental state changes.
- Clear intent that the value is a contract‑wide constant.
If your design requires upgradability or runtime configuration, pair immutables with a proxy or a separate configuration contract. Always document the reason for choosing immutables so future maintainers understand the constraints.
Next Steps
- Try the example contract on a local testnet and compare bytecode with
evm bytecodetools. - Measure gas usage of the getter with
cast tx --gas-limit 0 --rpc-url $RPCto see the difference. - Plan upgrade strategies: consider using a proxy if you anticipate changing the immutable value later.
By baking constants into bytecode, Vyper immutables let you write cheaper, more trustworthy contracts while keeping the flexibility to upgrade when needed.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.