Skip to content

Commit

Permalink
Merge pull request #53 from onflow/sainati/upgrade-guide
Browse files Browse the repository at this point in the history
Upgrade guide for types
  • Loading branch information
dsainati1 authored Mar 6, 2024
2 parents 35fd8d8 + 095bb29 commit 2052b5c
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/cadence_migration_guide/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ For assistance with the most common updates developers will face, explore these
- Migration Guide for [Fungible Tokens](./ft-guide.mdx)
- Migration Guide for [NFTs](./nft-guide.mdx)
- Migration Guide for [Core Contracts](./core-contracts-guide.mdx)
- Migration Guide for [Type Annotations](./type-annotations-guide.mdx)

**Helper Tools**

Expand Down
79 changes: 79 additions & 0 deletions docs/cadence_migration_guide/type-annotations-guide.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
title: Cadence Type Annotations 1.0 Migration Guide
sidebar_position: 5
sidebar_label: Cadence Type Annotations 1.0 Guide
---

# Type Annotations in Cadence 1.0

In addition to updating your contracts in reaction to the Core Contract changes in Cadence 1.0,
certain language changes in Cadence 1.0 will also require changes to type annotations in your contracts,
in particular type annotations on resource and struct fields.
These type updates are required to accurately reflect the way that the Cadence 1.0 data migrations will change
the types of these fields' values, and the Cadence 1.0 upgrade validator will enforce that these upgrades are accurate.

## Restricted Types

In Cadence 1.0, support for restricted types was dropped, and replaced with [intersection types](https://cadence-lang.org/docs/1.0/language/intersection-types).
As such, any existing restricted types must be replaced with a different type.
During the automated state migration for the Cadence 1.0 upgrade, restricted typed-values will be migrated according to a specific set of rules, and all developers must update the types in their contracts to mirror this.

* `AnyStruct{I}` and `AnyResource{I}` should be migrated to just `{I}`, as these types have identical behavior
* For any other type `T`, `T{I}` should be migrated to `T`, as this is the most specific possible type that can go here
* For any type `T`, `T{}` should be migrated to just `T`, as there is no support for empty intersection types

So, for example, a value of type `FlowToken.Vault{FungibleToken.Receiver}` should be migrated to just a `FlowToken.Vault` type,
while a value of type `AnyResource{Provider, Receiver}` should be migrated to a `{Provider, Receiver}` intersection.

## Reference Types

Reference types (whether on their own like `&FlowToken.Vault` or within a capability type like `Capability<&FlowToken.Vault{FungibleToken.Provider}>`)
from contracts written in Cadence v0.42 will need to be given
[entitlements](https://cadence-lang.org/docs/1.0/language/access-control#entitlements) in order to retain the same functionality
in Cadence 1.0.
The Cadence 1.0 automated data migration will automatically grant the appropriate entitlements to stored values,
but any reference types that appear in your contracts will need to be manually updated.

The update you will need to perform involves changing each reference type to have the appropriate entitlements necessary to perform
the same operations in Cadence 1.0 that it previously could in Cadence v0.42.
The Cadence 1.0 upgrade validator will enforce that these upgrades are accurate, and will suggest the correct type in case of an error.
However, if you'd like to understand how the validator computes this type, the next section has a technical explanation of what the validator is computing.

### How the Validator Computes Entitlements

The first basic concept necessary to understand the upgrade is the "entitlements function";
i.e. a hypothetical function that computes the set of entitlements that are valid for some composite or interface type `T`.
This is just the complete set of entitlements that appear in that type's definition.

E.g., for a resource type `R` defined as:

```cadence
access(all) resource R {
access(E) fun foo() { ... }
access(G | H) fun bar() { ... }
}
```

`Entitlements(I)` would be equal to `{E, G, H}`, i.e. all the entitlements that appear in `I`'s definition.
The idea here is that any reference that was previously typed as `&R` was originally able to call all
the `pub` functions in `R` (here both `foo` and `bar`), and after the Cadence 1.0 migration we want that to still be the case.
In order to make that true, we need to give the `&R` all the entitlements it might need to do that, which is exactly `Entitlements(R)`.

All of which is to say, any `&R` reference types that appear in your contract must be updated to `auth(E1, E2, ...) &R`, where `E1, E2, ...` are all
the entitlements in `Entitlements(R)`.

One important note is that reference to restricted types (`&T{I}`) behave slightly differently; instead of being given entitlements to `T`, they
are instead granted only entitlements based on the interfaces in the restriction set (here `{I}`). So for some interface and composite defined like so:

```cadence
access(all) resource interface I {
access(E) fun foo()
}
access(all) resource R: I {
access(E) fun foo() { ... }
access(F) fun bar() { ... }
}
```

A type `&R{I}` should be updated to `auth(E) &R`, since the entitlements it is given is only those in `I`. It does not receive an entitlement to `F`, since
the old `&R{I}` was not able to call `bar`.

0 comments on commit 2052b5c

Please sign in to comment.