Using Vyper Constant Functions for Gas‑Efficient On‑Chain Calculations
Learn how Vyper’s @external constant decorator moves immutable calculations to deployment time, letting you call functions off‑chain for free and cut gas costs in Ethereum smart contracts.
21 Dec 2025, 06:22 UTC

When a smart contract needs a value that never changes—such as a fixed conversion rate or a mathematical constant—executing that calculation on‑chain costs gas every time the function is called.
Vyper addresses this with the @external constant decorator, which lets the compiler evaluate the function at deployment time (or make it callable off‑chain) so users pay no gas for the computation.
How constant functions work
A function marked @external constant must read only immutable state and cannot write to storage. The Vyper compiler executes the function during compilation and embeds the resulting value in the contract’s bytecode or makes it available via a static call.
- No state modifications.
- No dependence on mutable variables.
- Return value must be computable from constants or literals.
Worked example: fixed fee rate
Suppose a vault charges a flat 0.5 % fee on deposits. Instead of computing the fee each time, we expose it as a constant.
# Save as fee_calc.vy and compile with: vyper fee_calc.vy -o abi.json -o bytecode.bin
contract FeeVault:
FEE_BP: constant[uint256] = 5 # 5 basis points = 0.05%
DENOM: constant[uint256] = 10000
@external
def deposit_amount(_amount: uint256) -> uint256:
# Calculates fee using constants; the multiplication/division is still on‑chain
return (_amount * self.FEE_BP) / self.DENOM
@external constant
def fee_rate() -> uint256:
# Returns the pre‑computed rate; callable off‑chain for free
return self.FEE_BP / self.DENOM
The fee_rate function can be queried through any JSON‑RPC endpoint (e.g., eth_call) without creating a transaction, so the caller spends zero gas.
Trade‑offs and limitations
Because the value is fixed at deployment, you cannot change it later without redeploying the contract. If the fee must be adjustable via governance, a constant is unsuitable.
Additionally, the compiler expands the constant expression into bytecode. Very large formulas can increase the contract size and risk hitting the 244 KB limit introduced by Spurious Dragon. To inspect the impact, compile with vyper fee_calc.vy -o output.json and examine the bytecode field; a sudden growth signals excessive expansion.
Debugging constant functions requires checking the intermediate representation. Use vyper --ir fee_calc.vy to see how the compiler transforms the expression, and vyper --tree fee_calc.vy for the abstract syntax tree.
Verification and diagnostics
- Confirm the compiler version supports constants:
vyper --version(should output a version string like0.x.x). - Compile the contract and inspect the bytecode:
vyper fee_calc.vy -o output.json. Openoutput.jsonand verify that thebytecodecontains the literal result offee_rate(e.g., the hex representation of0x0000000000000000000000000000000000000000000000000000000000000190for 400 wei if using 5 bp). - Test an off‑chain call: using a tool such as
castorweb3.js, invokefee_rateviaeth_call. The call should return the expected value and report zero gas used (the RPC fieldgasUsedwill be0x0).
By applying @external constant to immutable logic, you keep on‑chain computation to the minimum necessary, saving users gas while preserving contract correctness.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.