This document maps the syntax history in
vyper-syntax-history.md to vyupgrade behavior.
Each source-visible entry is classified as an automated rewrite, a diagnostic,
an explicit no-op when the historical change only introduced newly accepted
syntax, or validation-only when surviving obsolete source is left for compiler
validation. Alpha targets are opt-in; the default target remains the latest
supported final release.
Rules are version-gated. Unless noted as a target-floor rule, a rule runs only when the inferred source version is older than the listed change and the target version is at or after it. Target-floor rules cover legacy source syntax whenever the requested target is in the supported range.
0.1.0b* source compilers are validated through a typed-ast compatibility
wrapper. This preserves source compilation for legacy compilers that expected
pre-Python-3.8 AST node classes while still allowing vyupgrade to run under a
modern Python interpreter.
- Custom errors added: no-op. This is newly accepted revert declaration and raising syntax; existing string revert reasons remain valid.
- Docstring-only function bodies rejected:
VY131inserts an explicitpassafter the docstring. - Wildcard interface lengths and unbounded length spellings added: no-op. This is newly accepted source syntax.
isqrtmoved intomath:VY101.- Multi-name interface imports added: no-op. This is newly accepted import syntax.
- Multi-interface
implementsadded and duplicateimplementsrejected:VY121merges repeated declarations and collapses duplicate names. ...interface default parameter values added: no-op. This is newly accepted interface syntax.VY122replaces concrete interface default values with....- Numeric literal underscores added: no-op. This is newly accepted literal syntax.
- Abstract module methods added: no-op. This is new opt-in module syntax.
- Event fields cannot be module types: validation-only.
- Absolute relative imports disallowed:
VYD015.
module.__at__()casts added: no-op. Existing interface cast syntax is not mechanically equivalent in the general case.
manacall kwarg alias added: no-op. Existinggas=spelling remains valid.@externalbecame optional in.vyifiles: no-op. Existing explicit decorators remain valid.- Event instantiation keyword arguments added:
VY112. - Native hex string literals added: no-op. Existing byte literals remain valid.
block.prevrandaosignature changed tobytes32:VYD001.
- Bytestring downcasts added: no-op. This is newly accepted source syntax.
- External calls require keywords:
VY040,VY041,VY042,VY057, andVYD003.
- Module syntax and imports added: no-op for new opt-in syntax. Module import
rewrites and diagnostics are otherwise covered by
VY120andVYD015. - Named reentrancy locks removed:
VY090andVYD002. enumdeclarations replaced byflag:VY030.- Loop variables require type annotations:
VY070. - Struct instantiation uses keyword arguments:
VY060. - Integer division uses
//:VY050andVYD004. - Builtin constants removed:
VY012. - Two-argument
rangecan includebound=:VY071andVYD011. - Builtin ERC interface imports moved and gained an
Iprefix:VY020.
@raw_returnadded: no-op. This is new opt-in syntax, not a source form that older contracts must rewrite to compile.
- Decimal
sqrtmoved intomath:VY100rewritessqrt(x)tomath.sqrt(x)and insertsimport math. - Deprecated bitwise builtins removed:
VY110rewritesbitwise_and,bitwise_or,bitwise_xor, andbitwise_notto operators.VY111rewrites literalshift(x, N)andshift(x, -N).VYD012flags non-literal shift amounts for manual<<or>>review. raw_create()added: no-op. This is new deployment syntax, not a required migration.- File-level nonreentrancy pragma,
@reentrant, andpublic(reentrant(...))added: no-op. These are new opt-in forms.
@externalbecame optional in.vyifiles: no-op. Existing explicit decorators remain valid.module.__at__()casts added: no-op. Existing interface cast syntax is not mechanically equivalent in the general case.- Event instantiation keyword arguments added:
VY112rewrites positional event logs to keyword arguments when the event declaration is locally known. - Native hex string literals added: no-op. Existing byte literals remain valid.
manacall kwarg alias added: no-op. Existinggas=spelling remains valid.- Absolute relative imports disallowed:
VYD015flags nested modules with bare sibling-style imports for manualfrom . import ...review.
- Constructor visibility changed to
@deploy:VY002removes invalid constructor visibility decorators and inserts@deploy. - Named reentrancy locks removed:
VY090removes the single-lock case, reserves legacy lock storage slots, and emits a review diagnostic.VYD002flags multiple named locks because global-lock behavior may change callback assumptions. - Storage arrays bounded by
max_value(uint256)or the max-uint256 literal:VY091lowers top-level declarations toHashMap[uint256, T]while preserving public getter shape. - Unreachable code validation is stricter:
VY092removes code in a block after unconditional terminators and after exhaustive terminating if-chains. _abi_encodeand_abi_decoderenamed:VY010andVY011.- Memory
DynArrayallocations cannot use effectively unboundedmax_value(int128)lengths:VY094caps that legacy idiom atmax_value(uint32)and applies the same cap to matching range loops. @internalbecame optional: no-op. Existing@internalsource remains valid.- External calls require keywords:
VY040addsextcall;VY041addsstaticcall.VY042parenthesizes keyworded calls before subscripting.VY057assigns ignoredstaticcallresults to a generated local variable when the interface return type is known.VYD003flags calls whose mutability cannot be inferred. - Integer division uses
//:VY050rewrites proven integer division.VYD004flags ambiguous/expressions. - Redundant integer
convert(...)calls rejected by modern Vyper:VY051removes converts when source facts prove the value already has the target integer type, and also handles legacyuint256converts after division and in constant initializers. - Fixed-size array equality remains unsupported for some element types:
VY213expands comparisons againstempty(T[N])into elementwise checks. - Struct equality remains unsupported:
VY214expands comparisons againstempty(Struct)into field-wise checks. - Signed constants in unsigned arithmetic:
VY052converts known signed global constants, such as oldN_COINS: constant(int128)values, insideuint256arithmetic expressions. It also casts signed operands ofunsafe_sub(...)when the call is used as an unsigned array index. - Dynamic
Bytes[N]declarations and call arguments initialized from hex byte literals:VY053rewrites the literal to a byte string form accepted by modern Vyper. - Exponentiation typing became stricter:
VY054folds known integer constants used as operands in unsigned exponent expressions, andVY055rewrites dynamicuint256 ** uint256expressions topow_mod256(...).VY054also rewrites signed integer boundary literals behind signed annotations tomin_value(...)ormax_value(...), and folds exponent max literals insidebytes32conversions. - Range bounds are type-checked against annotated loop variables:
VY056converts signed integer constants insiderange(...)when the loop variable has an unsigned integer annotation, and adds a literalbound=when the original constant expression makes the iteration count provable. - Struct literals require keyword arguments:
VY060. - Loop variables require type annotations:
VY070. enumreplaced byflag:VY030diagnoses by default and rewrites only with--aggressive.- Builtin constants removed:
VY012rewritesMAX_UINT256, integer min/max constants,ZERO_ADDRESS, andEMPTY_BYTES32. - Immutable variables now collide with explicit same-name accessors:
VY013renames the immutable backing variable and preserves the external getter name. - Constant variables now collide with explicit same-name accessors:
VY016renames the constant backing variable and preserves the external getter name. - NatSpec validation is stricter:
VY058removes stale@paramlines whose names do not exist in the function signature or have no description, strips Solidity-style colons from valid@param name:tags, and rewrites unknown@forktags to@custom:fork. It also rewrites duplicate singleton fields such as@noticeand@authorto@custom:<field>. - String literal validation is stricter:
VY224replaces non-ASCII characters in string literals with ASCII placeholders so migrated source remains compiler-accepted. - Local interface mutability is checked more strictly:
VY014changesnonpayableinterface entries toviewwhen the implementation is a view function orpublic(...)getter, and changes@pureimplementations to@viewwhen an implemented interface requires a view method. - Pure functions may no longer read immutable state:
VY015changes@purefunctions to@viewwhen source facts show the function body references a top-levelimmutable(...)binding. - View functions may not emit events:
VY017removes@viewfrom functions whose body contains alogstatement. - Interface-typed storage assignments are checked more strictly:
VY019rewrites mismatched constructor casts to the declared storage interface type. - Dynamic
rangebounds:VY071adds inferredbound=for two-argument ranges. In aggressive mode,VY071also collapses leadingif/breaksentinel loops into bounded single-argument ranges when the removed block is behavior-preserving.VYD011flags two-argument ranges where the bound is not inferable.VYD017flags sentinel loops that can be collapsed only under--aggressive. - Builtin ERC interface import path changed:
VY020rewrites known imports and interface type names. Legacy built-in interfaces used inimplementsare preserved as local interfaces when modernethereum.ercsdefinitions are stricter than the old source-era built-ins.VYD003flags unknownvyper.interfacesimports. - Interface default functions are rejected:
VY123removesdef __default__entries from local interface declarations. - Known dependency import paths changed:
VY018rewrites the old snekmatecreate2_addresshelper module tocreate2. - Module import and ownership declarations added: no-op. This is new module syntax, not a required rewrite.
- Module exports added: no-op. This is new opt-in syntax.
- Imported events auto-exported: no-op. This changes module composition rather than legacy source spelling.
- Decimal feature flag required:
VYD001. block.prevrandaotype changed:VYD010.
#pragmadirectives added and version pragma parsing relaxed:VY001rewrites or adds#pragma versionwith the target version.- Dynamic single-argument
rangebounds:VYD014flagsrange(stop)whenstopis not literal and the target crosses0.3.10.
- No source syntax changes identified.
transient(...)added: no-op. This is new opt-in storage syntax.- Ternary operator added: no-op. Existing
if/returnsource remains valid. - Shift operators added: no-op for
0.3.8targets;VY111handles later removal ofshift()at0.4.2. raw_revert()added: no-op. Existingraisesyntax remains valid.send(..., gas=...)added: no-op. Existing two-argumentsendremains valid.custom:NatSpec tags added: no-op.- Unary plus disabled:
VY230. - Numeric boolean negation blocked:
VY231rewrites integernot xtox == 0;VYD013flags unknown types. - Enum values became valid mapping keys: no-op.
isqrt()added: no-op. This is a new builtin, not a required migration.epsilon()added: no-op. This is a new builtin.block.prevrandaoalias added:VY220rewritesblock.difficultytoblock.prevrandao.- Public constants and immutables added: no-op. Existing declarations remain valid.
- No source syntax changes identified.
create_from_blueprintaccepts arbitrary data: no-op for source migration;VY080handles the later0.4.0defaultcode_offsetbehavior change.empty()accepted in constants/default arguments: no-op. This only accepts a form previously rejected.
enumcustom type added: no-op for migrations into0.3.4;VY030handles the later0.4.0enumtoflagmigration.flagbecame a reserved declaration keyword:VY093renames a legacy public storage variable namedflagand adds a getter preservingflag()._abi_decode()added: no-op for0.3.4;VY011handles the later0.4.0rename toabi_decode.create_from_blueprint()andcreate_copy_of()added: no-op for0.3.4;VY080handles the later0.4.0review point.default_return_value=added: no-op. This is new optional syntax.min_value()andmax_value()added: no-op for0.3.4;VY012uses these forms for the later builtin constant migration.uint2str()added: no-op. This is a new builtin.msg.dataaccepted directly inraw_call: no-op.shift()supports signed integers: no-op for0.3.4;VY111handles the later0.4.2removal.- Dynamic arrays of strings enabled: no-op.
print()debug builtin added: no-op.
convert()semantics generalized: no-op.- Hex and bytes literals restricted:
VYD210flags mismatchedBytesandStringliteral forms when migrating legacy code. DynArray[T, N]added: no-op. The syntax history entry is a newly accepted type form, not a reliable array rewrite.- Full ABI v2 integer and bytes types added: no-op.
<address>.codeadded: no-op.tx.gaspriceadded: no-op.- Struct constants accepted: no-op.
skip_contract_check=added: no-op.unsafe_*builtins added: no-op.- Lists of any type can be loop variables: no-op.
immutable(T)added: no-op.uint8added: no-op.block.gaslimitandblock.basefeeadded: no-op.- Checkable
raw_call()added: no-op. - Non-constant revert strings accepted: no-op.
- Slices of complex expressions accepted: no-op.
- Lists of structs can be function arguments: no-op.
- ABI-encodable function argument and return types expanded: no-op.
create_minimal_proxy_to(..., salt=...)added: no-op.
_abi_encode()exposed: no-op for0.2.16;VY010handles the later0.4.0rename.- Event arguments can be any ABI-encodable type: no-op.
- Interfaces can appear in lists, structs, and maps: no-op.
@nonreentranton constructors disallowed:VY210.
- No source syntax changes identified.
- No source syntax changes identified.
abs()added: no-op.
int256added: no-op.msg.dataadded: no-op.
- No source syntax changes identified.
- No source syntax changes identified.
- Reserved keyword checks updated:
VYD211covers the concrete legacy parameter name case from0.2.1, includingvalue.
not incomparator added:VY211.empty(...)accepted as a function-call argument: no-op.- Empty static arrays accepted in
log: no-op. Bytesvariables can be mapping keys: no-op.
- No source syntax changes identified.
uint256implicit range-loop iterator type: no-op. The source spelling did not change; laterVY070handles explicit loop-variable annotations for0.4.0.
- Local-variable scoping restrictions removed: no-op.
- No source syntax changes identified.
- No source syntax changes identified.
- No source syntax changes identified.
@publicand@privaterenamed:VY201.@constantrenamed:VY201.- Type units removed, and the legacy
timestamptype becameuint256:VY202. - Event declaration syntax changed:
VY203. logbecame a statement:VY204.- Mapping declarations changed to
HashMap:VY205handles bothmap(key, value)and oldervalue[key]mapping syntax. - Interfaces use
interface; legacy signature mutability keywordsconstantandmodifyingbecomeviewandnonpayable:VY206. It also handles legacycontract Foo():headers,address(Interface)annotations, interface-typed storage variables lowered toaddresswith call-site casts, and interface methods that must becomepayablebecause calls passvalue=. - Public fixed-array getters used
int128indexes in pre-0.2.1 ABIs:VY223adds explicit compatibility getters and renames backing storage. - Dynamic byte and string type names capitalized:
VY207. - Byte and string literals are no longer interchangeable:
VYD210. assert_modifiable()andas_unitless_number()removed:VY208.create_with_code_of()renamed:VY208rewrites it tocreate_copy_of().- Function input name
valuereserved:VY212renames legacy inputs and updates local references.VYD211remains for cases the fixer cannot handle. - Builtin names
min_valueandmax_valuereserved:VY222renames colliding function-local variables and updates local references. slice()start and length must beuint256:VYD212.len()returnsuint256:VYD213.- External-call
value=andgas=kwargs must beuint256:VYD214. raw_callkwargoutsizerenamed:VY208.raw_calldelegate calls cannot also passvalue=:VY208removes the value kwarg whenis_delegate_call=True.raw_callcalldata must be dynamic bytes:VY208rewritesempty(bytes32)calldata tob"".raw_callmax_outsize=must beuint256:VY208foldsmax_value(uintN)bounds to integer literals.extract32kwargtyperenamed:VY208.- Public array getter indexes use
uint256: no-op. This is ABI shape, not a source rewrite. - Public struct getters return all values: no-op. This is ABI shape, not a source rewrite.
RLPListremoved:VYD215.empty()added: no-op.@pureadded: no-op.raisecan omit a reason string: no-op.method_id()type argument made optional:VY209.raw_callcan performSTATICCALL: no-op.- Interfaces can be split into generated
.vyifiles:VY120.
- Required
raw_callandslicearguments became positional:VY221rewritesslice(data, start=..., len=...)to positional arguments. Thev0.2.1coverage covers the laterraw_calloutsizetomax_outsizespelling andslice()integer-width diagnostics. - NatSpec comments added: no-op for beta targets.
VY058handles a later0.4.0NatSpec tag syntax cleanup.
chain.idadded: no-op. This is new opt-in environment syntax.address.codehashadded: no-op. This is new opt-in environment syntax.- Scientific notation for numeric literals accepted: no-op. This is newly accepted literal syntax.
bytes[32]implicitly rewrites tobytes32:VY207handles the later dynamic byte and string spelling cleanup for supported targets.- Scientific notation rejected after previously parsing incorrectly: no-op.
v0.1.0-beta.15accepts it again. for ... elsedisallowed: no-op. This is rejected source, not a migration target.
- Environment variables and constants as default parameter values: no-op. This is newly accepted source syntax.
- Relative imports added: no-op for beta targets.
VYD015handles the later0.4.1import-resolution restriction.
sha3()removed:VY217rewrites it tokeccak256().- String and dynamic bytes equality added: no-op. This is newly accepted expression syntax.
- Unreachable assertions added: no-op. This is new opt-in assertion syntax.
- List constants added: no-op. This is newly accepted constant syntax.
sha256()added: no-op. This is new opt-in builtin syntax.create_with_code_of()renamed tocreate_forwarder_to():VY208handles the moderncreate_copy_of()spelling used by supported targets.@nonreentrantadded: no-op for beta targets. Later reentrancy syntax migrations are covered byVY090,VY210, andVYD002.
string[N]type support added:VY207handles the laterstring[N]toString[N]rename.- String support in builtins and expressions added: no-op. This is newly accepted source syntax.
- Source interfaces added:
VY206handles the latercontracttointerfacespelling change.
- Constants in function and event signatures added: no-op. This is newly accepted source syntax.
- Implicit assignment conversions disallowed: validation-only.
- Side effects inside
assertdisallowed: validation-only.
- Subscript mapping syntax changed to
map(...):VY205rewrites both this form andmap(...)to modernHashMap[...]. - Struct definitions and constructors added: no-op for beta targets. Later
struct literal syntax is covered by
VY060. clear()replacedreset()anddelwas disallowed:VY219rewritesreset(...)and simpledel xstatements toclear(...).EMPTY_BYTES32added:VY012handles the later builtin-constant removal.
- Unit annotations in signatures added:
VY202handles later type-unit removal. - Additional
convert()target types added: no-op. This is newly accepted builtin syntax.
convert(x, "T")string type arguments changed toconvert(x, T):VY218.- Custom constants added: no-op for beta targets. Later constant accessor
collisions are covered by
VY016. ifandassertbecame stricter about boolean expressions: validation-only.
- Default function arguments added: no-op. This is newly accepted source syntax.
assertreason strings added: no-op. This is newly accepted assertion syntax.notrestricted to boolean values:VY231andVYD013handle later numericnotcleanup.num128replaced byint128:VY216.
- Function docblocks added: no-op for beta targets. Later docstring-only
function bodies are covered by the
v0.5.0a2syntax history entry. - Builtin constants added:
VY012handles later builtin-constant removal.
- Initial beta source forms are validation-only where they predate later
supported rewrite rules. Later target-floor rules cover major surviving forms:
VY201,VY202,VY203,VY204,VY206,VY207,VY208,VY209,VY216, andVY221.
VYD005: source has no version pragma and no--source-version.VYD006: source compilation failed under the declared or inferred source compiler.VYD007: ABI or method identifiers changed after migration.VYD008: storage layout changed after migration.VYD009: target compiler default EVM version differs from source-era default.VYD016: source version resolves to a compiler newer than the requested target.VYD018: source version matches no compiler supported by thisvyupgraderelease.