Skip to content

Commit f60d342

Browse files
j1010001claude
andcommitted
docs: clarify ContractUpdateValidator scope and threat model
Add a 'Threat model and scope' section at the top of the contract updatability page to make explicit that the validator's purpose is storage compatibility only — not a general-purpose interface freeze. Access modifiers and let/var mutability are intentionally out of scope because they do not affect storage serialization. Mirrors the clarification added to stdlib/contract_update_validation.go in onflow/cadence#4465. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 3669d04 commit f60d342

1 file changed

Lines changed: 15 additions & 0 deletions

File tree

docs/language/contract-updatability.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,21 @@ A [contract] is a collection of data (its state) and code (its functions) that l
77

88
Cadence maintains this state consistency by validating the contracts and all their components before an update.
99

10+
## Threat model and scope
11+
12+
The contract update validator has a **narrow, deliberate scope: storage compatibility**. Its purpose is to ensure that already-stored on-chain data remains deserializable after an update. It is a storage compatibility check, not a general-purpose interface freeze.
13+
14+
**What the validator enforces** (storage compatibility):
15+
- Field types cannot change — serialized data is type-bound; a mismatch corrupts storage.
16+
- Nested composite/interface declarations cannot be removed — orphaned stored data would have no matching type at deserialization time.
17+
- Interface conformances cannot be removed — removing a conformance would invalidate type assumptions baked into stored collections (e.g. `[{I}]` containing `{T: I}` values).
18+
- Enum cases cannot be removed or reordered — enum values are stored as ordinals; any reordering silently changes their meaning.
19+
20+
**What the validator intentionally does NOT enforce** (deployer discretion):
21+
- Access modifiers on fields (e.g. `access(self)``access(all)`) — access control is not a storage property. The runtime enforces the access rules present in the current chain-state code at execution time. If a deployer chooses to widen access, that is a deliberate decision they make as the contract owner. Users who rely on a contract's access guarantees must trust the deployer, as they would on any upgradeable platform.
22+
- Field mutability (`let``var`) — the `let`/`var` distinction is a Cadence semantic constraint enforced at compile time against the current code; it is not encoded in the storage layout and does not affect deserialization.
23+
- Function signatures, event definitions, code logic — none of these affect storage layout.
24+
1025
## Validation goals
1126

1227
The contract update validation ensures that:

0 commit comments

Comments
 (0)