⚠️ This document was initially generated with the assistance of a Large Language Model (LLM) and has been reviewed by the engineering team.
This document defines the versioning strategy used across:
- Flow Yield Vaults (FYV)
- Flow ALP
- DeFiActions
The goals are to:
- Safely manage non-upgradable smart contract changes
- Maintain mainnet stability
- Enable parallel development
- Ensure cross-repository consistency
A new version is required when a change:
- Breaks backward compatibility
- Modifies resource/storage layout (e.g., adding fields)
- Requires redeployment to a new name or address
These changes are non-upgradable and define version boundaries.
All changes must be:
- Backward-compatible
- Deployable to the same contract address with the same name
- Safe for existing integrations
Each version is represented by a Git branch.
| Branch | Purpose |
|---|---|
main |
Active development (not deployed) |
v0 |
Current deployed mainnet version |
mainis free to introduce breaking changesv0is stable and represents the exact deployed contract set
All repositories (FYV, Flow ALP, DeFiActions) must maintain aligned version branches.
The main branch is never deployed to a persistent network.
It is validated using:
- Forked environments
- Local emulator
- Temporary/test deployments
This enables rapid iteration without mainnet constraints.
Persistent deployments must come from a version branch (e.g., v0).
The FYV repository acts as the deployment source of truth:
- Pins dependency commits (submodules or equivalent)
- Defines the full contract set
- Ensures reproducibility
- Develop on
main - Breaking changes are allowed
When a non-upgradable change is introduced:
- Continue development on
main - Introduce new contracts (new names/addresses if required)
- Create/update a version branch (e.g.,
v1) - Align all repositories to compatible commits
- Maintenance mode only
- Allowed changes:
- Bug fixes
- Backward-compatible improvements
- Apply fixes to
main - Backport to
v0only if compatible
- Checkout version branch (e.g.,
v0) - Use pinned dependencies
- Deploy to network
Clear and consistent contract naming is required to reinforce version boundaries and avoid ambiguity.
- Contract names must remain stable
- Contracts must be deployable to the same address with the same name
- Renaming or adding suffixes (e.g.,
V2,New) is not allowed
When introducing a new version due to non-upgradeable changes:
- Contracts must be redeployed under new names or addresses
- Naming must clearly indicate version differences
- Suffix-based versioning:
FlowVault→FlowVaultV1AutoBalancer→AutoBalancerV1
- Use explicit version identifiers (
V1,V2, ...) - Avoid ambiguous names such as:
NewUpdated
- Keep naming consistent across FYV, Flow ALP, and DeFiActions
Once a version is deployed and superseded:
- Contracts should be treated as immutable
- No further modifications should be made
An optional pattern is to include a contract-level AnyStruct field that can act as an extensible container for temporary, upgrade-compatible patches to already deployed versions.
⚠️ This pattern introduces globally mutable, non-type-safe state. It should be used sparingly and only when strictly necessary.
- Primarily for version branches (e.g.,
v0) to ship missing behavior without breaking upgradeability - As an escape hatch when a deployed contract cannot be changed safely otherwise
- The container may exist on
main, but should be:- Empty
- Not referenced in logic
- Do not rely on this pattern for normal feature development on
main - Prefer introducing properly typed state in the next version (e.g.,
v1)
If used:
- Store a structured value inside the
AnyStruct - Use mapping-style substructures for scoped additions
- Isolate it from core storage and public interfaces
- Clearly document any data written to it
- Reduced type safety
- Harder reasoning about state and invariants
- Increased likelihood of bugs
- Treat this as a temporary compatibility mechanism, not a design default
- When creating a new version, replace usages with properly typed fields and resources
- Versions are defined by non-upgradable changes
- Branches represent versions (
v0,v1, ...) mainis development-only and not deployed- Version branches are the only deployment source
- All repositories must stay aligned per version
This model enables safe contract evolution while maintaining mainnet stability.