Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FLIP: Allow adding new fields to existing types #295

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
100 changes: 100 additions & 0 deletions cadence/20220817-add-fields-to-existing-definitions.md
SupunS marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
---
status: proposed
flip: TBD
authors: Deniz Mert Edincik ([email protected]), Austin Kline ([email protected])
sponsor: Bastian Mueller ([email protected])
updated: 2022-08-17
---

# FLIP: Allow adding new fields to existing types

## Objective

This proposed change will allow updating existing types (contracts) with new fields.

## Motivation

One major challenge in smart contract design in Cadence is the inability to add new fields to already deployed types.
The lack of this functionality means that developers have to resort to brittle workarounds.
For example, developers may choose to deploy entirely new contracts,
that are essentially reprints of the original, except with the newly added fields.
Developers may also choose to
- Manually storing fields as dictionaries to accommodate future new fields
- Manually storing new fields in a new, different contract
- Manually storing new fields in storage

Each of these workarounds come with their downsides.
- New contracts lead to complex migrations for applications and sunsetting existing contracts.
- Storing new data manually is brittle, and leads to harder-to-follow code and added complexity.
- Factory patterns increase compute since objects must be built at runtime
and also lose the benefits of type-checking, since the underlying structure is not truly typed.

## User Benefit

Allowing developers to add new fields to existing types as they need them
will make contract development more focused on the needs of the current version
as opposed to undue complexity to take future plans into account.
It will also allow more maintainable contract code with less complex logic when existing contracts get updated.

## Design Proposal

The [contract updatability checking](https://cadence-lang.org/docs/language/contract-updatability)
is extended to allow new fields to be added to existing types,
such as contracts, structs, resources, and attachments.
These new fields must be optional.

When the added field of an existing stored value is accessed, the result is `nil`.

For example, assume the following struct type is currently deployed as part of a contract:

```cadence
access(all)
struct Message {
access(all)
let content: String

init(content: String) {
self.content = content
}
}
```

We can now add a new field to this struct:

```cadence
access(all)
struct Message {
access(all)
let content: String

init(content: String) {
self.content = content
}

// An optional new field. Existing instances of Message will have timestamp set to nil when accessed
// unless they are set at a later date
access(all)
let timestamp: UInt64?
}
```

### Limitations

- This will not allow existing fields to be altered. That is, it is invalid to alter a field's type.
- This will not allow new fields to be derived from existing ones.

### Compatibility

This should be backwards compatible

### User Impact

- Cadence developers will be able to modify their contract more to their needs
instead of over-designing with the first launch of their contract(s).
- If new unforeseen features or fixes require new fields,
those additions can be kept in the original contract,
instead of being silo'd off into their own contract.

## Prior Art

N/A