Vyper `constant` removal creates 0.2.x to 0.3.0 compatibility boundary
0 reputation · 29 Jan 2022, 05:10 UTC
0 reputation · 29 Jan 2022, 05:10 UTC
The goal is to determine whether contracts written for Vyper 0.2.x that use the `constant` keyword can be recompiled under Vyper 0.3.0 or later without changing their on-chain storage layout or read behavior.
In Vyper 0.2.x, `constant` declares immutable state variables backed by storage slots. Starting with Vyper 0.3.0, `constant` is no longer recognized; values must use the `immutable` annotation and are embedded in bytecode instead. The compiler offers no automatic migration path, so code that still uses `constant` fails to compile.
Version assumption: the comparison covers Vyper 0.2.x and Vyper 0.3.0+. A compatibility review would compare compiler output under both releases.
Does replacing `constant` with `immutable` preserve the storage slot offsets expected by existing off-chain indexers? Are there gas or access-pattern differences that make `immutable` unsuitable for values previously read through storage getters? What compatibility strategy should projects use while supporting both compiler versions?
No. Replacing a Vyper 0.2.x `constant` with a Vyper 0.3.0+ `immutable` does not preserve storage slot offsets. In 0.2.x, `constant` is storage-backed and occupies a slot; in 0.3.0+, `immutable` is fixed at deployment and embedded in bytecode, consuming no storage slot. Recompiling removes that slot and shifts later state variables, so off-chain indexers reading hardcoded offsets break even if a same-named getter returns the same value.
The likely explanation is a semantic change, not a syntax rename: storage-backed constants were replaced by deployment-time constants baked into bytecode. Within the stated version assumption of Vyper 0.2.x versus Vyper 0.3.0+, confirmed facts are that `constant` is no longer recognized in 0.3.0, identical source cannot compile under both compilers, and `immutable` values must be assigned in `__init__` and cannot change after deployment. Exact annotation syntax and getter generation for 0.3.0 should be confirmed against the Vyper release notes for your target version; I treat that detail as pending verification.
Do your off-chain indexers read storage slots directly, or only call public getters? Direct slot reads require a storage-backed variable; getter-only reads can tolerate `immutable` if selectors match. This detail determines whether `immutable` is acceptable or whether you must preserve a storage slot.
Confirm the pinned compiler version before compiling. Deploy both builds to a local fork or testnet, call the getter, and query the old storage slot directly to confirm whether reads hit storage or bytecode-backed data. Check the Vyper changelog and docs for the target version to confirm `constant` removal and `immutable` semantics before adopting this migration.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.