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

add migration guide to version 1.0 as well as current version #70

Merged
merged 1 commit into from Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1,3 @@
{
"position": 5
}
@@ -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!
@@ -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.
211 changes: 211 additions & 0 deletions 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<auth(FungibleToken.Withdraw) &ExampleToken.Vault>(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<FungibleTokenMetadataViews.FTVaultData>():
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!