From 056577f85f4f4521124ebfc5d88f73d1763e5265 Mon Sep 17 00:00:00 2001 From: Tom Haile Date: Fri, 15 Mar 2024 08:07:30 -0500 Subject: [PATCH] add migration guide to version 1.0 as well as current version --- .../cadence_migration_guide/_category_.json | 3 + .../core-contracts-guide.mdx | 67 ++ .../emulator-state-migration-guide.mdx | 104 +++ .../cadence_migration_guide/ft-guide.mdx | 211 ++++++ .../cadence_migration_guide/index.md | 74 ++ .../cadence_migration_guide/nft-guide.mdx | 636 ++++++++++++++++++ .../cadence_migration_guide/staging-guide.mdx | 36 + .../type-annotations-guide.mdx | 79 +++ 8 files changed, 1210 insertions(+) create mode 100644 versioned_docs/version-1.0/cadence_migration_guide/_category_.json create mode 100644 versioned_docs/version-1.0/cadence_migration_guide/core-contracts-guide.mdx create mode 100644 versioned_docs/version-1.0/cadence_migration_guide/emulator-state-migration-guide.mdx create mode 100644 versioned_docs/version-1.0/cadence_migration_guide/ft-guide.mdx create mode 100644 versioned_docs/version-1.0/cadence_migration_guide/index.md create mode 100644 versioned_docs/version-1.0/cadence_migration_guide/nft-guide.mdx create mode 100644 versioned_docs/version-1.0/cadence_migration_guide/staging-guide.mdx create mode 100644 versioned_docs/version-1.0/cadence_migration_guide/type-annotations-guide.mdx diff --git a/versioned_docs/version-1.0/cadence_migration_guide/_category_.json b/versioned_docs/version-1.0/cadence_migration_guide/_category_.json new file mode 100644 index 0000000..6af9d91 --- /dev/null +++ b/versioned_docs/version-1.0/cadence_migration_guide/_category_.json @@ -0,0 +1,3 @@ +{ + "position": 5 +} diff --git a/versioned_docs/version-1.0/cadence_migration_guide/core-contracts-guide.mdx b/versioned_docs/version-1.0/cadence_migration_guide/core-contracts-guide.mdx new file mode 100644 index 0000000..177a44d --- /dev/null +++ b/versioned_docs/version-1.0/cadence_migration_guide/core-contracts-guide.mdx @@ -0,0 +1,67 @@ +--- +title: Protocol Smart Contracts 1.0 Changes Guide +sidebar_position: 4 +sidebar_label: Core Contracts Guide +--- + +## Protocol Smart Contracts in Cadence 1.0 + +In 2024, the network will be upgrading to Cadence 1.0. +In addition to many changes to the Cadence programming language and +the Cadence token standards, the Flow Protocol smart contracts +are also being updated to be compatible with the changes. + +All applications and smart contracts that interact with these contracts +will need to update their transactions and scripts in order to be compatible with the changes. + +## Important Info + +This document assumes you have a basic understanding of the [Cadence 1.0 updates](https://forum.flow.com/t/update-on-cadence-1-0/5197) and modifications to the Fungible Token Standard. We encourage you to consult those guides for more details on these changes if you are interested. + +The updated code for the Cadence 1.0 versions of the protocol smart contracts +is located in the [`stable-cadence` branch of the flow-core-contracts repo](https://github.com/onflow/flow-core-contracts/pull/319). +Please look at the changes there to understand how the contracts have changed. +Every contract in the repo is changing. + +Please see the latest post in [this forum thread](https://forum.flow.com/t/update-on-cadence-1-0/5197/8) +to find the latest version of the CLI and emulator that you should be testing with. + +It is also important to remember that after you've made your changes to your contracts, +you will have to stage the upgrades on testnet and mainnet in order for them +to be upgraded and migrated properly. You can find informaion about how to do that +here: https://github.com/onflow/contract-updater + +Additionally, here are the import addresses +for all of the important contracts related to the protocol: + +| Contract | Emulator Import Address | +| --------------------------- | ----------------------- | +| `FungibleToken` | `0xee82856bf20e2aa6` | +| `ViewResolver` | `0xf8d6e0586b0a20c7` | +| `Burner` | `0xf8d6e0586b0a20c7` | +| `MetadataViews` | `0xf8d6e0586b0a20c7` | +| `FungibleTokenMetadataViews`| `0xee82856bf20e2aa6` | +| `FlowToken` | `0x0ae53cb6e3f42a79` | +| `FlowFees` | `0xe5a8b7f23e8b548f` | +| `FlowStorageFees` | `0xf8d6e0586b0a20c7` | +| `FlowServiceAccount` | `0xf8d6e0586b0a20c7` | +| `NodeVersionBeacon` | `0xf8d6e0586b0a20c7` | +| `RandomBeaconHistory` | `0xf8d6e0586b0a20c7` | +| `LockedTokens` | `0xf8d6e0586b0a20c7` | +| `StakingProxy` | `0xf8d6e0586b0a20c7` | +| `FlowIDTableStaking` | `0xf8d6e0586b0a20c7` | +| `FlowClusterQC` | `0xf8d6e0586b0a20c7` | +| `FlowDKG` | `0xf8d6e0586b0a20c7` | +| `FlowEpoch` | `0xf8d6e0586b0a20c7` | +| `FlowStakingCollection` | `0xf8d6e0586b0a20c7` | + +See the other guides in this section of the docs for the import +addresses of other important contracts in the emulator. + +## Upgrade Guide + +The NFT guide covers a lot of common changes that are required for NFT contracts, +but many of these changes will also apply to any contract on Flow, so it is still +useful to read even if you don't have an NFT contract. + +More detailed information about how the core contracts are changing will come soon! diff --git a/versioned_docs/version-1.0/cadence_migration_guide/emulator-state-migration-guide.mdx b/versioned_docs/version-1.0/cadence_migration_guide/emulator-state-migration-guide.mdx new file mode 100644 index 0000000..7894903 --- /dev/null +++ b/versioned_docs/version-1.0/cadence_migration_guide/emulator-state-migration-guide.mdx @@ -0,0 +1,104 @@ +--- +title: Migrate Emulator State To Cadence 1.0 +sidebar_label: Emulator State Migration Guide +description: How to locally test storage migration and staged contract upgrades on Emulator +sidebar_position: 7 +--- + +Flow CLI provides a command `flow migrate state` to migrate your local emulator +state to Cadence 1.0, and to deploy upgraded contracts to the emulator. +This is useful for locally testing the staged contract upgrades, and to see how the +new network and the upgraded contracts would behave with the migrated data. + +## Migration Guide + +To test the migration, first you would need an emulator state, created with an emulator/CLI release +that uses a pre-1.0 Cadence version. + +### Getting the old state + +It is recommended to use the latest pre-1.0 CLI version (e.g: `v1.14.*`) for creating the old state. +This is because the emulator shipped with older CLI versions may not include some of the system contracts +(e.g: `RandomBeaconHistory` contract) that are included by default in the newer versions of the emulator/CLI. +Such contracts are required for the migration. + +**To get an emulator state with Flow CLI `1.14.0`:** + +- Start the emulator with the `--persist` flag. + + ```shell + flow emulator --persist + ``` + +- Deploy the pre-1.0 project/contracts to the emulator +- Run transactions if there are any. +- Stop the emulator (Ctrl-C on \*nix platforms, and Ctrl-Break or Ctrl-Pause on Windows). + **It is important to make sure the emulator is stopped before taking the snapshot, + so that any pending in-memory data would be written to the persisted state properly.** +- Locate the persisted state `./flowdb/emulator.sqlite` file, from the project root. + +### Migrating the state + +#### Download and install CLI + +Download and install the latest CLI, that runs Cadence 1.0, by running the below command. + + - Linux/macOS + ```shell + sudo sh -ci "$(curl -fsSL https://raw.githubusercontent.com/onflow/flow-cli/feature/stable-cadence/install.sh)" + ``` + + - Windows (in PowerShell): + ```shell + iex "& { $(irm 'https://raw.githubusercontent.com/onflow/flow-cli/feature/stable-cadence/install.ps1') }" + ``` + +The Cadence 1.0 CLI will now be available on your system as `flow-c1`. +You can interact with this CLI using this command, i.e. + +```shell +flow-c1 help +``` + +_Note: Any existing previous Flow CLI installation will still remain available via the `flow` command._ + +#### Run migration + +- Run `flow-c1 migrate` against the previously created state. + +- The state file (`emulator.sqlite`) can be provided using the `--db-path` flag. + +- If there are any contracts that also need to be upgraded, those can be specified using the `--contracts` flag. + **Note that, the paths to these updated contracts and their deployed addresses must be specified in the `flow.json` file.** + For example, assuming the contract was deployed in the `test` account in the emulator, + and assuming the updated contract is in the `./updated_test_contract.cdc` file, the `flow.json` should include: + + ```json + { + "contracts": { + "Test": "./updated_test_contract.cdc" + }, + "deployments": { + "emulator": { + "test": ["Test"] + } + } + } + ``` + +- The migration will produce a report consisting of the migration status. + This can be enabled by setting the `--save-report` flag. + +A sample `migrate` command would look like: + +```shell +flow-c1 migrate state --db-path=/path/to/emulator.sqlite --save-report=./reports --contracts="Test" +``` + +### Testing the migrated state + +Once the migration completes successfully, the emulator can be started with the migrated state. +For that, ensure the emulator is started again using the new CLI version (that runs Cadence 1.0), +with the `--persist` flag. +Now the emulator should be up and running using the migrated state and the updated contracts. +Run any transactions to verify the correctness of the existing data. diff --git a/versioned_docs/version-1.0/cadence_migration_guide/ft-guide.mdx b/versioned_docs/version-1.0/cadence_migration_guide/ft-guide.mdx new file mode 100644 index 0000000..9c9db5e --- /dev/null +++ b/versioned_docs/version-1.0/cadence_migration_guide/ft-guide.mdx @@ -0,0 +1,211 @@ +--- +title: Fungible Token Cadence 1.0 Migration Guide +sidebar_position: 3 +sidebar_label: FT Cadence 1.0 Guide +--- + +# Fungible Tokens in Cadence 1.0 + +In 2024, the network will be upgrading to Cadence 1.0. +In addition to many changes to the Cadence programming language, +the Cadence token standards are also being streamlined and improved. +All applications will need to prepare and migrate their existing +Cadence smart contracts, scripts, and transactions for the update. +If you do not update your code, your applications will become non-functional +after the network upgrade. + +This document describes the changes to the Cadence Fungible Token (FT) standard and +gives a step-by-step guide for how to upgrade your FT contract from Cadence 0.42 +to Cadence 1.0. + +We'll be using the [`ExampleToken` contract](https://github.com/onflow/flow-ft/blob/v2-standard/contracts/ExampleToken.cdc) +as an example. Many projects have used `ExampleToken` as a starting point for their projects, +so it is widely applicable to most NFT developers on Flow. +The upgrades required for `ExampleToken` will cover 90%+ of what you'll +need to do to update your contract. Each project most likely has +additional logic or features that aren't included in `ExampleToken`, +but hopefully after reading this guide, you'll understand Cadence 1.0 +well enough that you can easily make any other changes that are necessary. + +As always, there are plenty of people on the Flow team and in the community +who are happy to help answer any questions you may have, so please reach out +in Discord if you need any help. + +# Important Info + +Please read [the FLIP](https://github.com/onflow/flips/pull/55) +that describes the changes to the `FungibleToken` standard first. + +The updated code for the V2 Fungible Token standard is located in the +[`v2-standard` branch of the flow-ft repo](https://github.com/onflow/flow-ft/pull/131). +Please look at the changes there to understand how the standard and examples have changed. +This branch also includes the updated versions of `FungibleTokenMetadataViews`, +`Burner`, `FungibleTokenSwitchboard`, and `TokenForwarding`. + +Please see the latest post in [this forum thread](https://forum.flow.com/t/update-on-cadence-1-0/5197/8) +to find the latest version of the CLI and emulator that you should be testing with. + +It is also important to remember that after you've made your changes to your contracts, +you will have to stage the upgrades on testnet and mainnet in order for them +to be upgraded and migrated properly. You can find informaion about how to do that +here: https://github.com/onflow/contract-updater + +Additionally, here are the import addresses +for all of the important contracts related to fungible tokens: + +| Contract | Emulator Import Address | +| --------------------------- | ----------------------- | +| `FungibleToken` | `0xee82856bf20e2aa6` | +| `ViewResolver` | `0xf8d6e0586b0a20c7` | +| `Burner` | `0xf8d6e0586b0a20c7` | +| `MetadataViews` | `0xf8d6e0586b0a20c7` | +| `FungibleTokenMetadataViews`| `0xee82856bf20e2aa6` | +| `FungibleTokenSwitchboard` | `0xee82856bf20e2aa6` | + +See the other guides in this section of the docs for the import +addresses of other important contracts in the emulator. + +As for contracts that are important for NFT developers but aren't "core contracts", +here is information about where to find the Cadence 1.0 Versions of Each: + +**USDC:** The USDC contract is still being updated for Cadence 1.0 and is currently not available. + +**Account Linking and Hybrid Custody:** The account linking and hybrid custody contracts +are still being updated for Cadence 1.0 and are currently not available. + +For any other contracts, search for their github repo and there will likely be +a PR or feature branch with the Cadence 1.0 changes. If there isn't, please +create an issue in the repo or reach out to that team directly via their support +or Discord channel to ask them about their plans to update their contracts. + +# Migration Guide + +Please see the [NFT Cadence 1.0 migration guide](./nft-guide). While +the contracts aren't exactly the same, they share a huge amount of functionality, +and the changes described in that guide will cover 90% of the changes +that are needed for fungible tokens, so if you just follow those instructions +for your fungible token contract, you'll be most of the way there. + +Here, we will only describe the changes that are specific to the fungible token standard. + +## `Vault` implements `FungibleToken.Vault` + +`FungibleToken.Vault` is no longer a resource type specification. +It is now an interface that inherits from `Provider`, `Receiver`, `Balance`, +`ViewResolver.Resolver`, and `Burner.Burnable`. + +To ensure compatibility, [update your `Vault` interface conformance list to only +implement `FungibleToken.Vault`](https://github.com/onflow/flow-ft/pull/131/files#diff-dcb2cd49f7f399806400b83a9695278b867b9937d195d6f45063bc000d146223R82): +```cadence +access(all) resource Vault: FungibleToken.Vault { +``` +In addition, since `Vault` is an interface, you will need to update every instance in your code +that refers to `@FungibleToken.Vault` or `&FungibleToken.Vault` to +`@{FungibleToken.Vault}` or `&{FungibleToken.Vault}` respectively to show +that it is now an interface specification instead of a concrete type specification. +Example in `deposit()`: +```cadence +/// deposit now accepts a resource that implements the `FungibleToken.Vault` interface type +access(all) fun deposit(from: @{FungibleToken.Vault}) +``` + +**Note for Custom Migrations:** All stored objects that currently use the concrete type +`FungibleToken.Vault` will be automatically migrated to use the interface type `{NonFungibleToken.Vault}` +as part of the Flow team's custom state migrations. + +## Add `Withdraw` entitlements to `withdraw()` + +Now that unrestricted casting is possible in Cadence, it is necessary to use +[entitlements](https://cadence-lang.org/docs/1.0/language/access-control#entitlements) +to restrict access to privledged functions in any composite type. + +The only default method that needs to be restricted is the `withdraw` method: +```cadence +access(FungibleToken.Withdraw) fun withdraw(amount: UFix64): @ExampleToken.Vault { +``` +This means that you can only call the `withdraw` method if you control the actual object +or if you have an `auth(FungibleToken.Withdraw)` entitled reference to it. + +So in a typical transfer transaction when you need to withdraw from a vault, +you would get the reference like this: +```cadence +// Get a reference to the signer's stored vault +let vaultRef = signer.storage.borrow(from: self.vaultData.storagePath) + ?? panic("Could not borrow reference to the owner's Vault!") +``` +From the [flow-ft `transfer_tokens.cdc` transaction](https://github.com/onflow/flow-ft/blob/v2-standard/transactions/transfer_tokens.cdc). + +## Use the new `Burner` contract if desired + +Custom destructors were removed as part of Cadence 1.0, so `destroy` blocks +in resource definitions are no longer allowed. If you were using the `destroy` +block to emit a custom event or subtract the destroyed tokens' supply from your +token's total supply and still want that functionality, you'll need to +[use the `burnCallback()` method from the `Burner` smart contract](https://github.com/onflow/flow-ft/pull/131/files#diff-dcb2cd49f7f399806400b83a9695278b867b9937d195d6f45063bc000d146223R100-R106): + +``` +/// Called when a fungible token is burned via the `Burner.burn()` method +access(contract) fun burnCallback() { + if self.balance > 0.0 { + ExampleToken.totalSupply = ExampleToken.totalSupply - self.balance + } + self.balance = 0.0 +} +``` + +This will automatically be executed if a Vault is destroyed +via the `Burner.burn()` method. It will emit a standard event to indicate the destruction, +so no need to include one yourself unless you need +to emit other information besides the balance and type. + +As shown above, this is also where you can subtract the destroyed tokens from the +total supply. This function requires you to set the balance of the vault to zero +before the function execution completes though. This is to prevent spam. + +## Add `isAvailableToWithdraw` method + +Some more complex types that implement `Provider` may want a more efficient way +to describe if a desired amount of tokens can be withdrawn. +`isAvailableToWithdraw` allows that. + +[The `Vault` implementation is simple though](https://github.com/onflow/flow-ft/pull/131/files#diff-dcb2cd49f7f399806400b83a9695278b867b9937d195d6f45063bc000d146223R127-R130): +```cadence +/// In `ExampleToken.Vault` +/// Asks if the amount can be withdrawn from this vault +access(all) view fun isAvailableToWithdraw(amount: UFix64): Bool { + return amount <= self.balance +} +``` + +## Remove Private Path and Type fields + +Since private paths were removed in Cadence 1.0, these fields are no longer needed, +so remove the code that returns them in your `resolveView` method for `FTVaultData`: +```cadence +/// In `ExampleToken.resolveContractView()` +/// +case Type(): + return FungibleTokenMetadataViews.FTVaultData( + storagePath: /storage/exampleTokenVault, + receiverPath: /public/exampleTokenReceiver, + metadataPath: /public/exampleTokenVault, + /// REMOVED: providerPath + receiverLinkedType: Type<&ExampleToken.Vault>(), + metadataLinkedType: Type<&ExampleToken.Vault>(), + /// REMOVED: providerLinkedType + createEmptyVaultFunction: (fun(): @{FungibleToken.Vault} { + return <-ExampleToken.createEmptyVault(vaultType: Type<@ExampleToken.Vault>()) + }) + ) +``` + +Private paths are no longer able to be used in Cadence across the board, +so you'll need to find other ways to do what you were doing with them before. +This will likely involve [Capability Controllers](https://github.com/onflow/flips/blob/main/cadence/20220203-capability-controllers.md). + +## Conclusion + +This guide briefly covered the Cadence 1.0 changes that are specific to Fungible Tokens. +If you have any more questions or would like additional sections to be added to the guide, +please create an issue in [the cadence-lang.org repo](https://github.com/onflow/cadence-lang.org) +or ask in discord and the flow team will be happy to assist! diff --git a/versioned_docs/version-1.0/cadence_migration_guide/index.md b/versioned_docs/version-1.0/cadence_migration_guide/index.md new file mode 100644 index 0000000..89d620d --- /dev/null +++ b/versioned_docs/version-1.0/cadence_migration_guide/index.md @@ -0,0 +1,74 @@ +--- +title: Cadence 1.0 Migration Guide +sidebar_position: 1 +sidebar_label: Cadence 1.0 Migration Guide +--- + +# Cadence 1.0 Migration Guide + +Coming in 2024, the network will be upgrading to [Cadence 1.0](https://flow.com/upgrade/cadence-1). This means that all applications will need to prepare and migrate their existing Cadence smart contracts, scripts, and transactions for compatibility with the update. If you do not update your contracts, your applications will become non-functional after the network upgrade. Read more about the roadmap [here](https://flow.com/upgrade/cadence-1). + +### Upgrading Contracts + +To ensure your contracts are fully operational with Cadence 1.0, follow these essential steps: + +1. **Understand the Changes:** Start by familiarizing yourself with the [changes](https://forum.flow.com/t/update-on-cadence-1-0/5197) to identify how they might affect your code. +2. **Modify Your Code:** Update your contracts, transactions, and scripts in accordance with the new changes. +3. **Test Your Code:** The latest emulator release includes all updated standards and core contracts. Check out this [video](https://www.loom.com/share/4467610b7beb4ebbaabed6b430dc25c4?sid=14ecb3e7-e933-409c-a6a4-add40c6971d0) from the Flow team on how to install and use the Cadence 1.0 emulator. + + Run the following command: + + - Linux/macOS + + ```bash + sudo sh -ci "$(curl -fsSL https://raw.githubusercontent.com/onflow/flow-cli/feature/stable-cadence/install.sh)" + ``` + + - Windows (in PowerShell): + + ```powershell + iex "& { $(irm 'https://raw.githubusercontent.com/onflow/flow-cli/feature/stable-cadence/install.ps1') }" + ``` + + The Cadence 1.0 CLI will now be installed on your machine and can be accessed via the `flow-c1` command. + To verify the installation, run: + + ```bash + flow-c1 version + ``` + +5. **Stage**: A new **_Staging process_** will be released in the coming weeks that checks if your updated code is compatible with Cadence 1.0. Complete this [form](https://docs.google.com/forms/d/e/1FAIpQLSfprZJLPSEAS6H7_oL0j6bzetDzkHPmDZHYAGgqAAOAdLDKqw/viewform) to stay informed about updates and receive recommendations tailored to your code. + +### Resources + +**Guides & Docs** + +For assistance with the most common updates developers will face, explore these resources: + +- Cadence 1.0 [Beginner Course](https://academy.ecdao.org/en/catalog/courses/learn-cadence-beginner-1.0) +- Upgrading [Capabilities](https://academy.ecdao.org/en/catalog/tutorials/capability-controllers) +- Upgrading [Entitlements](https://academy.ecdao.org/en/catalog/tutorials/entitlements) +- 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** + +- **Cadence 1.0 Migration Helper CustomGPT:** An experimental tool currently exclusive to ChatGPT Pro users. [Try it here](https://chat.openai.com/g/g-wMnnHS2Md-flow-cadence-1-0-migration-helper). + +**In-Person Support** + +- Attend the weekly live [Cadence 1.0 Developer Office hours](https://calendar.google.com/calendar/ical/c_47978f5cd9da636cadc6b8473102b5092c1a865dd010558393ecb7f9fd0c9ad0%40group.calendar.google.com/public/basic.ics) happening every Thursday to ask questions you’re stuck on +- Shoot a message in the [developer Discord](https://discord.com/channels/613813861610684416/621847426201944074) channel. Please use “C1.0 upgrade” at the beginning of the message to help us categorize questions related to Cadence 1.0 +- Send us a request in the Developer [Help Center](https://support.flow.com/hc/en-us/requests/new) + +### Dive Deeper + +Enhance your understanding of the network upgrade and its possible implications on your app: + +- [Learn how Cadence will be changing for 1.0](https://forum.flow.com/t/update-on-cadence-1-0/5197) +- [Understand the upgrade, the timeline, and how it affects you](https://forum.flow.com/t/cadence-1-0-upgrade-plan/5477) +- [Learn how to update your Flow CLI to test against Cadence 1.0](https://forum.flow.com/t/update-on-cadence-1-0/5197/7) +- [Check out the Cadence language 1.0 docs](https://cadencelang.dev/docs/1.0/) +- [Learn about Contract Staging](https://forum.flow.com/t/updates-to-cadence-1-0-contract-staging/5642) diff --git a/versioned_docs/version-1.0/cadence_migration_guide/nft-guide.mdx b/versioned_docs/version-1.0/cadence_migration_guide/nft-guide.mdx new file mode 100644 index 0000000..5fc80f5 --- /dev/null +++ b/versioned_docs/version-1.0/cadence_migration_guide/nft-guide.mdx @@ -0,0 +1,636 @@ +--- +title: Non-Fungible Token Cadence 1.0 Migration Guide +sidebar_position: 2 +sidebar_label: NFT Cadence 1.0 Guide +--- + +# Non-Fungible Tokens in Cadence 1.0 + +In 2024, the network will be upgrading to Cadence 1.0. +In addition to many changes to the Cadence programming language, +the Cadence token standards are also being streamlined and improved. +All applications will need to prepare and migrate their existing +Cadence smart contracts, scripts, and transactions for the update. +If you do not update your code, your applications will become non-functional +after the network upgrade. + +This document describes the changes to the Cadence Non-Fungible Token (NFT) standard and +gives a step-by-step guide for how to upgrade your NFT contract from Cadence 0.42 +to Cadence 1.0. + +We'll be using the [`ExampleNFT` contract](https://github.com/onflow/flow-nft/blob/standard-v2/contracts/ExampleNFT.cdc) +as an example. Many projects have used `ExampleNFT` as a starting point for their projects, +so it is widely applicable to most NFT developers on Flow. +The upgrades required for `ExampleNFT` will cover 90%+ of what you'll +need to do to update your contract. Each project most likely has +additional logic or features that aren't included in `ExampleNFT`, +but hopefully after reading this guide, you'll understand Cadence 1.0 +well enough that you can easily make any other changes that are necessary. + +Additionally, most of the changes described here also apply to anyone +who is updating a Fungible Token contract or interacting with one, +so keep that in mind while reading if that applies to you. + +As always, there are plenty of people on the Flow team and in the community +who are happy to help answer any questions you may have, so please reach out +in Discord if you need any help. + +# Important Info + +Please read [the FLIP](https://github.com/onflow/flips/pull/56) +that describes the changes to the `NonFungibleToken` standard first. + +The updated code for the V2 Non-Fungible Token standard is located in the +[`standard-v2` branch of the flow-nft repo](https://github.com/onflow/flow-nft/pull/126). +Please look at the changes there to understand how the standard and examples have changed. +This branch includes the updated versions of `NonFungibleToken`, `MetadataViews`, `ViewResolver`, +and `NFTForwarding`. + +Please see the latest post in [this forum thread](https://forum.flow.com/t/update-on-cadence-1-0/5197/8) +to find the latest version of the CLI and emulator that you should be testing with. + +It is also important to remember that after you've made your changes to your contracts, +you will have to stage the upgrades on testnet and mainnet in order for them +to be upgraded and migrated properly. You can find informaion about how to do that +here: https://github.com/onflow/contract-updater + +Additionally, here are the import addresses +for all of the important contracts related to non-fungible tokens: + +| Contract | Emulator Import Address | +| ------------------ | ----------------------- | +| `NonFungibleToken` | `0xf8d6e0586b0a20c7` | +| `FungibleToken` | `0xee82856bf20e2aa6` | +| `ViewResolver` | `0xf8d6e0586b0a20c7` | +| `Burner` | `0xf8d6e0586b0a20c7` | +| `MetadataViews` | `0xf8d6e0586b0a20c7` | + +See the other guides in this section of the docs for the import +addresses of other important contracts in the emulator. + +As for contracts that are important for NFT developers but aren't "core contracts", +here is information about where to find the Cadence 1.0 Versions of Each: + +**NFT Catalog:** See [the `feature/cadence-1.0` branch of the NFT Catalog Repo](https://github.com/onflow/nft-catalog/tree/feature/cadence-1.0/cadence/contracts) +for the updated versions of NFT Catalog contracts. + +**NFT Storefront:** See [the `cadence-1.0` branch in the NFT Storefront Repo](https://github.com/onflow/nft-storefront/tree/cadence-1.0/contracts) +for the updated versions of the `NFTStorefront` and `NFTStorefrontV2` contracts. + +**USDC:** The USDC contract is still being updated for Cadence 1.0 and is currently not available. + +**Account Linking and Hybrid Custody:** The account linking and hybrid custody contracts +are still being updated for Cadence 1.0 and are currently not available. + +For any other contracts, search for their github repo and there will likely be +a PR or feature branch with the Cadence 1.0 changes. If there isn't, please +create an issue in the repo or reach out to that team directly via their support +or Discord channel to ask them about their plans to update their contracts. + +## A note for newcomers + +This guide is primarily for developers who have existing contracts +deployed to Flow mainnet that they need to update for Cadence 1.0. +If you don't have any contracts deployed yet, it is recommended that +you start an NFT contract from scratch by either copying the `ExampleNFT` +contract or the [`BasicNFT` contract](https://github.com/onflow/flow-nft/blob/standard-v2/contracts/BasicNFT.cdc) +from the `standard-v2` branch of the flow-nft +github repo and wait to deploy it until Flow has been upgraded for Cadence 1.0. + +## BasicNFT and UniversalCollection + +As part of the improvements to the NFT standard, there is now a new NFT contract +example in the `flow-nft` github repo: [`BasicNFT`](https://github.com/onflow/flow-nft/blob/standard-v2/contracts/BasicNFT.cdc). + +`BasicNFT` defines a Cadence NFT in as few lines of code as possible, 137 at the moment! +This is possible because the contract basically only defines the NFT resource, +the essential metadata views, and a minter resource. +It doesn't have to define a collection! Most collection resources are 99% boilerplate +code, so it really doesn't make sense for most projects to have to define their own +collection. + +Instead, `BasicNFT` uses [`UniversalCollection`](https://github.com/onflow/flow-nft/blob/standard-v2/contracts/UniversalCollection.cdc), +a contract that defines a collection resource +that has all of the standard functionality that a collection needs and nothing else. +From now on, any project that doesn't want to do anything unique with their collection +can just import `UniversalCollection` and call it from their `createEmptyCollection` +function: + +```cadence +access(all) fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection} { + return <- UniversalCollection.createEmptyCollection(identifier: "flowBasicNFTCollection", type: Type<@BasicNFT.NFT>()) +} +``` + +All they have to provide is a type and an identifier for the collection. +`UniversalCollection.Collection` will enforce that only NFTs of the given type +can be accepted by the collection: + +```cadence +access(all) fun deposit(token: @{NonFungibleToken.NFT}) { + if self.supportedType != token.getType() { + panic("Cannot deposit an NFT of the given type") + } +``` + +It also constructs standard paths based on the identifier provided. + +`UniversalCollection` will be deployed to all the networks soon after the Cadence 1.0 upgrade, +so developers will be able to import from it after that point. + +We'll be putting out more information and guides for `BasicNFT` and `UniversalCollection` +in the near future, but keep it in mind if you are thinking about deploying +any new NFT contracts in the future! + +# Migration Guide + +This guide will cover changes that are required because of upgrades to +the Cadence Language as well as the token standard. +The improvements will be described here as they apply to specific changes +that projects need to make in order to be ready for the upgrade, +but it is good to read all sources to fully understand the changes. + +Please read the motivation section of the NFT-V2 FLIP to learn about +why most of the changes to the standard were needed or desired. + +First, we will cover the changes that come from the new token standards and then +we will cover the changes that come from Cadence. + +### Previous Non-Permitted Changes + +Until now, there were a lot of restrictions on what changes are allowed +in upgrades to Cadence smart contracts, like not being allowed to change the type of fields, +not being able to change interface conformance, and more. +Many of the Cadence 1.0 changes require updates that break some of these rules, +but the upgrade checker will be relaxed in order to allow these changes to be possible. +All of these changes have already been tested with the Cadence 1.0 upgrades +for all of the token standards and all of the protocol smart contracts which cover +a huge amount of changes that contracts can go through, so the Flow team is confident +that the restrictions have been relaxed enough to allow the upgrades. + +### Automatic State Migrations + +Some of these changes require that types for stored values are updated to more or less restrictive types. +The work for updating the code that refers to these types is up to the developer, +but the work for migrating the stored state to reflect these two types will be handled +automatically by the Flow teams custom state migrations. These migrations only +expect a restricted subset of type changes, but it is important to make sure +that you don't introduce any new business logic as part of your Cadence 1.0 upgrades because +the migrations will only understand how to migrate state for existing code. +More information will be given about this in the sections of this doc that will +be affected by the custom migrations, such as with entitlements +and the removal of nested type requirements and restricted types. + +## Token Standard Changes + +### Continue to implement NonFungibleToken + +Make sure your contract still implements the `NonFungibleToken` interface: + +```cadence +access(all) contract YourContract: NonFungibleToken { +``` + +This won't be a change for most contracts because this is how tokens are implemented +currently, but there was a period of time when the new standards defined `NonFungibleToken` +as a contract instead of an interface, so anyone who was testing with those early versions +should make sure that their contract still implements `NonFungibleToken`. +This will ensure that the correct metadata view methods are enforced from `ViewResolver` +and that your contract has the correct `createEmptyCollection()` method defined. + +It is important to understand that the new `NonFungibleToken` no longer specifies types +that you need to define like `NFT` and `Collection`. These were changed to interfaces +because now the token standards support defining multiple token types in a single contract. +Most projects won't utilize this, but it is important to understand in relation +to some of the other changes that are needed, like the next one for example. + +### Add type argument to contract.createEmptyCollection() + +Because contracts can now define multiple token types, all `contract.createEmptyCollection()` +functions now have a `nftType` argument: + +```cadence +/// createEmptyCollection creates an empty Collection for the specified NFT type +/// and returns it to the caller so that they can own NFTs +access(all) fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection} { + return <- create Collection() +} +``` + +As is shown here, if you only have a single collection type defined in your contract, +you can just return that collection type regardless of what the type argument is, +but you could also make sure that the caller provides the correct type +before returning the collection. + +### Your NFT implements NonFungibleToken.NFT + +`NonFungibleToken.NFT` used to be a nested type specification, but now it is an interface! +This means that in your contract, your `NFT` resource needs to implement it +in order to be considered compatible with the standard! + +```cadence +access(all) contract ExampleNFT: NonFungibleToken { + /// We choose the name NFT here, but this type can have any name now + /// because the interface does not require it to have a specific name any more + access(all) resource NFT: NonFungibleToken.NFT { +``` + +This will ensure that your `NFT` resource has all the correct fields and functions. + +**Note for Custom Migrations:** All stored objects that currently use the concrete type +`NonFungibleToken.NFT` will be automatically migrated to use the interface type `{NonFungibleToken.NFT}` +as part of the Flow team's custom state migrations. + +### Your Collection implements NonFungibleToken.Collection + +Similar to `NFT`, `NonFungibleToken.Collection` is now an interface, +so your `Collection` resource type needs to implement it in order to be conformant. + +```cadence +/// In the `ExampleToken` smart contract +access(all) resource Collection: NonFungibleToken.Collection { +``` + +**Note for Custom Migrations:** All stored objects that currently use the concrete type +`NonFungibleToken.Collection` will be automatically migrated to use the interface type `{NonFungibleToken.Collection}` +as part of the Flow team's custom state migrations. + +### Remove Project-Specific Events + +Standard events are being added to the token standards! These are events +that are defined in the contract interface and are emitted during pre +and post-conditions every time an important event happens like a Deposit or a Withdrawal. +The events include all the important information and metadata about the action, +are emitted automatically from the interface, and are unable to be spoofed! + +This means that you can get rid of the Deposit and Withdraw events in your +contracts completely! You don't have to obviously, but the standard events will +be much more reliable and will be emitted anyway, so your custom events are redundant +unless they contain some information that is not included in the standard events. + +The [definitions](https://github.com/onflow/flow-nft/blob/standard-v2/contracts/NonFungibleToken.cdc#L72-L86) +and [emissions](https://github.com/onflow/flow-nft/blob/standard-v2/contracts/NonFungibleToken.cdc#L193) +for these standard events is in the new `NonFungibleToken` standard. + +```cadence +/// Event that is emitted when a token is withdrawn, +/// indicating the type, id, uuid, the owner of the collection that it was withdrawn from, +/// and the UUID of the resource it was withdrawn from, usually a collection. +/// +/// If the collection is not in an account's storage, `from` will be `nil`. +/// +access(all) event Withdrawn(type: String, id: UInt64, uuid: UInt64, from: Address?, providerUUID: UInt64) + +/// Event that emitted when a token is deposited to a collection. +/// Indicates the type, id, uuid, the owner of the collection that it was deposited to, +/// and the UUID of the collection it was deposited to +/// +/// If the collection is not in an account's storage, `from`, will be `nil`. +/// +access(all) event Deposited(type: String, id: UInt64, uuid: UInt64, to: Address?, collectionUUID: UInt64) +``` + +As you can see [in the `ExampleNFT` diff](https://github.com/onflow/flow-nft/pull/126/files#diff-0f42f974b7e6311f474d087fea60fbd57b5fda90294853811e492f965da21d36L25-L28), +the events have been removed completely. + +For event listeners, the events will have this format: + +```cadence +A.f8d6e0586b0a20c7.NonFungibleToken.Deposited(...) +``` + +Where the address is whatever address the `NonFungibleToken` contract is deployed to. + +### Implement ViewResolver + +The new standard enforces that implementations also implement +[the `ViewResolver` functions](https://github.com/onflow/flow-nft/blob/standard-v2/contracts/ViewResolver.cdc), +which are standard functions for returning metadata about a given +token or smart contract. + +If you were using these contract-level functions before, you will need to update them +to have the correct names and arguments. They were changed because now that contracts +can define multiple token types, the metadata getter functions need +to be able to return information about any of the token types. +Therefore, [here are the new definitions](https://github.com/onflow/flow-nft/blob/standard-v2/contracts/ViewResolver.cdc#L8-L32). +(The comments explain the design and some suggestions for how to implement them, +so it is recommend that you read them.) + +```cadence + /// Function that returns all the Metadata Views implemented by the resolving contract. + /// Some contracts may have multiple resource types that support metadata views + /// so there there is an optional parameter for specify which resource type the caller + /// is looking for views for. + /// Some contract-level views may be type-agnostic. In that case, the contract + /// should return the same views regardless of what type is passed in. + /// + /// @param resourceType: An optional resource type to return views for + /// @return An array of Types defining the implemented views. This value will be used by + /// developers to know which parameter to pass to the resolveView() method. + /// + access(all) view fun getContractViews(resourceType: Type?): [Type] + + /// Function that resolves a metadata view for this token. + /// Some contracts may have multiple resource types that support metadata views + /// so there there is an optional parameter for specify which resource type the caller + /// is looking for views for. + /// Some contract-level views may be type-agnostic. In that case, the contract + /// should return the same views regardless of what type is passed in. + /// + /// @param resourceType: An optional resource type to return views for + /// @param view: The Type of the desired view. + /// @return A structure representing the requested view. + /// + access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? +``` + +You can see how `ExampleNFT` implements them [here](https://github.com/onflow/flow-nft/blob/standard-v2/contracts/ExampleNFT.cdc#L219-L231). + +### Keep NFT ID Usage Consistent + +In the new standard examples, we often use UUID for NFT IDs. Many early Flow projects +used a project-specific ID system for their NFTs. It is important that you stick with +whatever ID system your project used from the beginning so NFT IDs don't get mixed up. + +### AddcreateEmptyCollection() to NFT and Collection. + +These function requirements were added to [`NFT`](https://github.com/onflow/flow-nft/pull/126/files#diff-0f42f974b7e6311f474d087fea60fbd57b5fda90294853811e492f965da21d36R58-R60) +and [`Collection`](https://github.com/onflow/flow-nft/pull/126/files#diff-0f42f974b7e6311f474d087fea60fbd57b5fda90294853811e492f965da21d36R203-R206) +so that holders of any of those objects could create a new collection of the correct type, +no matter if they imported the contract or knew the type ahead of time. + +### Make Collection.ownedNFTs access(contract) + +`ownedNFTs` was removed as a requirement for Collections, so this change is completely optional, +but it is recommended to make fields and functions as restrictive as possible, +so `ownedNFTs` should be `access(contract)` + +### Add getSupportedNFTTypes() and isSupportedNFTType() + +All resources that implement `NonFungibleToken.Receiver` now have to include these +two functions that indicate which types they are able to receive in their `deposit()` calls. +Since `Collection` implements `Receiver`, your `Collection` will need implementations +for both of these functions. + +As is done [in the `ExampleNFT.Collection`](https://github.com/onflow/flow-nft/pull/126/files#diff-0f42f974b7e6311f474d087fea60fbd57b5fda90294853811e492f965da21d36R142-R157), +if your `Collection` can only accept a single NFT type, then the implementation is simple. + +### Add getLength() + +Add [a `getLength()` function](https://github.com/onflow/flow-nft/pull/126/files#diff-0f42f974b7e6311f474d087fea60fbd57b5fda90294853811e492f965da21d36R183-R185) +to your `Collection` resource so that callers can quickly +get an idea of the size of your collection. + +```cadence +/// Gets the amount of NFTs stored in the collection + access(all) view fun getLength(): Int { + return self.ownedNFTs.keys.length + } +``` + +### Update borrowNFT() to Return an Optional + +The `borrowNFT()` method is used to get a reference to any NFT in the collection. +It is a common best practice in Cadence smart contracts for getter functions +(functions that only return a piece of informaion instead of modifying state) +to never panic or revert if the request is invalid. Getter functions should just +return `nil` if the request is invalid. + +Therefore. The [`borrowNFT` method should be modified](https://github.com/onflow/flow-nft/pull/126/files#diff-0f42f974b7e6311f474d087fea60fbd57b5fda90294853811e492f965da21d36R188-R189) +to return an optional reference and return `nil` if the NFT ID doesn't exist in the collection. + +```cadence +/// In the Collection resource +access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? { + return (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?) +} +``` + +Additionally, any projects that have `borrowNFTSafe` or a project-specific borrow +like `borrowMoment()` in NBA Top Shot can safely remove those and also remove +any usage of them from transactions and scripts. + +### Remove Private Path and Type fields + +Since private paths were removed in Cadence 1.0, these fields are no longer needed, +so remove the code that returns them in your `resolveView` method for `NFTCollectionData`: + +```cadence +case Type(): + let collectionData = MetadataViews.NFTCollectionData( + storagePath: /storage/cadenceExampleNFTCollection, + publicPath: /public/cadenceExampleNFTCollection, + // REMOVED: providerPath + publicCollection: Type<&ExampleNFT.Collection>(), + publicLinkedType: Type<&ExampleNFT.Collection>(), + // REMOVED: providerLinkedType + createEmptyCollectionFunction: (fun(): @{NonFungibleToken.Collection} { + return <-ExampleNFT.createEmptyCollection(nftType: Type<@ExampleNFT.NFT>()) + }) + ) + return collectionData +``` + +Private paths are no longer able to be used in Cadence across the board, +so you'll need to find other ways to do what you were doing with them before. +This will likely involve [Capability Controllers](https://github.com/onflow/flips/blob/main/cadence/20220203-capability-controllers.md). + +### Use the NonFungibleToken.emitNFTUpdated() function + +This is an optional change and only applies to projects that have functionality +that updates the metadata of NFTs periodically. It allows those projects to emit +[the standard `Updated` event](https://github.com/onflow/flow-nft/blob/standard-v2/contracts/NonFungibleToken.cdc#L55-L69) +so that event listeners can know when NFTs have been updated +so they can query collections to get the updated metadata to show in their user interfaces. + +```cadence + access(all) event Updated(type: String, id: UInt64, uuid: UInt64, owner: Address?) + access(contract) view fun emitNFTUpdated(_ nftRef: auth(Update | Owner) &{NonFungibleToken.NFT}) + { + emit Updated(type: nftRef.getType().identifier, id: nftRef.id, uuid: nftRef.uuid, owner: nftRef.owner?.address) + } +``` + +As you can see, it requires an authorized reference to an NFT, so only the owner of +and NFT can call this to emit an event. This could be called from within a `Collection` +resource when a piece of metadata on an owned NFT is updated. For example, +if a developer wanted to track the time of the latest transfer for each NFT, +they could do it in the `deposit()` function: + +```cadence +access(all) resource Collection: NonFungibleToken.Collection { + + access(contract) var ownedNFTs: @{UInt64: ExampleNFT.NFT} + + ... + + /// deposit takes a NFT and adds it to the collections dictionary + /// and adds the ID to the id array + access(all) fun deposit(token: @{NonFungibleToken.NFT}) { + let token <- token as! @ExampleNFT.NFT + + let id = token.id + + // add the new token to the dictionary which removes the old one + let oldToken <- self.ownedNFTs[token.id] <- token + destroy oldToken + + // Get an authorized reference to the NFT so that + // the update transfer date function can be called + // and the emitNFTUpdated function can be called + let authTokenRef = (&self.ownedNFTs[id] as auth(Update | Owner) &{NonFungibleToken.NFT}?)! + authTokenRef.updateTransferDate(date: getCurrentBlock().timestamp) + NonFungibleToken.emitNFTUpdated(authTokenRef) + } + + ... +} +``` + +## Cadence Changes + +### Update all pub access modfiers + +The `pub` access modifier was removed from the language to better support unified +representation of access control, especially now that entitlements exist. + +Please familiarize yourself with [the new entitlements feature](https://cadence-lang.org/docs/1.0/language/access-control#entitlements) +because it is extremely important for you to understand in order to build safe smart contracts. + +Most contracts can update and `pub` access modifiers to **access(all)**, +but there are some functions, such as `withdraw`, that need to have entitled access. + +A good rule to follow is that if there is a resource that will ever have a reference +created for it (such as for a public or private capability), any functions that +you don't want everyone in the network to be able to have access to should be +restricted by an entitlement so that people cannot downcast the reference to access +these privledged functions. + +### Add Withdraw and Owner Entitlements to withdraw() + +Now that unrestricted casting is possible in Cadence, it is necessary to use +[entitlements](https://cadence-lang.org/docs/1.0/language/access-control#entitlements) +to restrict access to privledged functions in any composite type. + +The only default method that needs to be restricted is the `withdraw` method: + +```cadence +access(NonFungibleToken.Withdraw) fun withdraw(withdrawID: UInt64): @ExampleNFT.NFT { +``` + +This means that you can only call the `withdraw` method if you control the actual object +or if you have an `auth(NonFungibleToken.Withdraw)` entitled reference to it. + +So in a typical transfer transaction when you need to withdraw from a vault, +you would get the reference like this: + +```cadence +// borrow a reference to the signer's NFT collection +self.withdrawRef = signer.storage.borrow( + from: collectionData.storagePath + ) ?? panic("Account does not store an object at the specified path") +``` + +From the [flow-nft `transfer_nft.cdc` transaction](https://github.com/onflow/flow-nft/blob/standard-v2/transactions/transfer_nft.cdc). + +In addition, since `Collection` is an interface, you will need to update every instance in your code +that refers to `@NonFungibleToken.Collection` or `&NonFungibleToken.Collection` to +`@{NonFungibleToken.Collection}` or `&{NonFungibleToken.Collection}` respectively to show +that it is now an interface specification instead of a concrete type specification. + +This also applies to `NonFungibleToken.NFT`. Any instance that refers +to `@NonFungibleToken.NFT` or `&NonFungibleToken.NFT` need to be updated to +`@{NonFungibleToken.NFT}` or `&{NonFungibleToken.NFT}` respectively. + +Example in `deposit()`: + +```cadence +/// deposit now accepts a resource that implements the `NonFungibleToken.NFT` interface type +access(all) fun deposit(token: @{NonFungibleToken.NFT}) +``` + +**Note on Custom State Migrations:** You may be wondering +how you can get these entitlements onto capabilities +that already exist in a contract or in an account. As part of the automatic +migrations, all existing capabilities will be automatically migrated to +use a type that offers the same level of access. In the case of Capabilities +that provide access to entitled functions, the relevant entitlements will be added. + +### Update all getter functions to view + +Cadence 1.0 introduces [view functions](https://cadence-lang.org/docs/1.0/language/functions#view-functions) +which enforce that a function does not modify any state. + +The default view functions will be enforced by the token standard, +but if your project has any other getter functions that aren't in the standard +and don't modify any state, then you should add `view` to these functions. + +### Remove Restricted Types + +Cadence 1.0 makes it so restricted types +(for example: `@ExampleNFT.Collection{NonFungibleToken.Receiver}` instead of +`@ExampleNFT.Collection` or `{NonFungibleToken.Receiver}`) are no longer permitted. + +See [the FLIP](https://github.com/onflow/flips/blob/main/cadence/20230505-remove-restricted-types.md) +to get more context on why these were removed. + +**Note on Custom State Migrations:** Developers are required to update +any code that refers to a restricted type to either refer to the resource type +OR the interface type, but the migration of any stored values that use a restricted +type will be handled by the Flow team's custom migrations. Restricted types +will be migrated to be the unrestricted type. For example, a capability with the type +`&ExampleNFT.Collection{NonFungibleToken.Receiver}` will be changed to have the type +`&ExampleNFT.Collection`. + +### Use Correct Capability Syntax + +Cadence 1.0 introduces [Capability Controllers](https://github.com/onflow/flips/blob/main/cadence/20220203-capability-controllers.md) +a more sophisticated and easy to use way of handling capabilities. +It is important to understand how these work in order to use them properly. + +As part of these changes, projects need to update the syntax for how they +manage capabilities. You can see [the `setup_account.cdc` transaction](https://github.com/onflow/flow-nft/pull/126/files#diff-ea00cafde5a0c7662422d9d0f9f99455faa924444a9012cb9bbe604271126daaR26-R29) +for the proper syntax for creating public capabilities for example. + +```cadence +// create a public capability for the collection +signer.capabilities.unpublish(collectionData.publicPath) +let collectionCap = signer.capabilities.storage.issue<&ExampleNFT.Collection>(collectionData.storagePath) +signer.capabilities.publish(collectionCap, at: collectionData.publicPath) +``` + +Additionally, private paths have been removed, so any code +that references private paths needs to be changed to use capability controllers instead. + +### Use Proper Entitlements for Accounts + +`AuthAccount` objects are not referred to as `Account` +and there are now more restrictions on how accounts can be used. + +See the [Cadence 1.0 Account documentation](https://cadence-lang.org/docs/1.0/language/accounts/) for more information. + +Most of the functionality on `Account` objects is now hidden by entitlements, +so a transaction has to declare what `Account` functionality the transaction will access +in the `prepare` block. + +For example, in [the `transfer_nft` transaction](https://github.com/onflow/flow-nft/blob/standard-v2/transactions/transfer_nft.cdc), +these are the entitlements that are required: + +```cadence +prepare(signer: auth(BorrowValue) &Account) { +``` + +The transaction needs to borrow a value from storage to withdraw the NFT, +so the `BorrowValue` entitlement is required. + +Each transaction is different, so different entitlements will be required depending on what is happening. +It is important for developers to make sure that only the minimum set of entitlements +that are required for the transaction are given. This allows wallets to more accurately +show users what the transactions they are signing will have acccess to, +which helps users have more confidence and safety about what transactions they sign. + +## Conclusion + +This guide covered the most important changes that are required for the Cadence 1.0 +upgrades to NFT contracts. Please ask any questions about the migrations +in the #developer-questions channel in discord and good luck with your upgrades! diff --git a/versioned_docs/version-1.0/cadence_migration_guide/staging-guide.mdx b/versioned_docs/version-1.0/cadence_migration_guide/staging-guide.mdx new file mode 100644 index 0000000..853cb96 --- /dev/null +++ b/versioned_docs/version-1.0/cadence_migration_guide/staging-guide.mdx @@ -0,0 +1,36 @@ +--- +title: Cadence Migrate Smart Contracts To Cadence 1.0 +sidebar_label: Smart Contract Migration Guide +description: Guide to migrating your cadence 1.0 compatible smart contracts +sidebar_position: 6 +--- + +:::info +Encountering problems along the way? Visit the `migrate` section in the Flow CLI documentation for additional tools designed to help your migration to Cadence 1.0. +::: + +This guide aims to simplify the migration process to Cadence 1.0, making it accessible and straightforward for developers at all skill levels. + +## What is Cadence 1.0? + +[Cadence 1.0](https://flow.com/upgrade/crescendo/cadence-1) is the latest version of the Cadence smart contract programming language. The stable release of Cadence 1.0 represents a significant milestone in the language’s maturity, delivering a comprehensive suite of improvements that increase speed, security and efficiency. With Cadence 1.0, developers gain access to over 20 new features and enhancements. Each change is thoughtfully designed to streamline workflows, reduce duplication and improve code readability, making writing and understanding smart contracts much easier. + +## Staging a contract + +In order to migrate your updated smart contract to Cadence 1.0, it's crucial to stage it on the Testnet network. This preliminary step not only verifies the contract's compatibility and syntactical correctness but also ensures a seamless transition to the new environment. + +```bash +flow migrate stage-contract HelloWorld --network=testnet +``` + +Ensure that HelloWorld accurately reflects the name of your contract as specified in your flow.json configuration file. + +### Confirm the contract has been staged + +To confirm that your contract is ready for migration and has been successfully staged, execute the following command: + +```bash +flow migrate is-staged HelloWorld --network=testnet +``` + +A response of true indicates that your contract has been approved by the Flow Blockchain Testnet network and is ready for the migration process. diff --git a/versioned_docs/version-1.0/cadence_migration_guide/type-annotations-guide.mdx b/versioned_docs/version-1.0/cadence_migration_guide/type-annotations-guide.mdx new file mode 100644 index 0000000..488d259 --- /dev/null +++ b/versioned_docs/version-1.0/cadence_migration_guide/type-annotations-guide.mdx @@ -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`. \ No newline at end of file