# Cadence Anti-Patterns (/docs/anti-patterns) This is an opinionated list of issues that can be improved if they are found in Cadence code intended for production. ## Avoid using fully authorized account references as a function parameter ### Problem A developer may choose to authenticate or perform operations for their users by using the users' account reference or addresses. In order to do this, they might add a parameter to a function which has an authorized account reference type (`auth(...) &Account`), as an authorized account reference can only be obtained by signing a transaction. If it is a fully authorized account reference, this is problematic, as the fully-authorized account reference allows access to some sensitive operations on the account, for example, to write to storage, which provides the opportunity for bad actors to take advantage of. ### Example: ```cadence ... // BAD CODE // DO NOT COPY // Imagine this code is in a contract that uses a `auth(Storage) &Account` parameter // to authenticate users to transfer NFTs // They could deploy the contract with an Ethereum-style access control list functionality access(all) fun transferNFT(id: UInt64, owner: auth(Storage) &Account) { assert(owner(id) == owner.address) transfer(id) } // But they could upgrade the function to have the same signature // so it looks like it is doing the same thing, but they could also drain a little bit // of FLOW from the user's vault, a totally separate piece of the account that // should not be accessible in this function // BAD access(all) fun transferNFT(id: UInt64, owner: auth(Storage) &Account) { assert(owner(id) == owner.address) transfer(id) // Sneakily borrow a reference to the user's Flow Token Vault // and withdraw a bit of FLOW // BAD let vaultRef = owner.borrow<&FlowToken.Vault>(/storage/flowTokenVault)! let stolenTokens <- vaultRef.withdraw(amount: 0.1) // deposit the stolen funds in the contract owners vault // BAD contractVault.deposit(from: <-stolenTokens) } ... ``` ### Solution Projects should find other ways to authenticate users, such as using resources and capabilities as authentication objects. They should also expect to perform most storage and linking operations within transaction bodies rather than inside contract utility functions. There are some scenarios where using an authorized account reference (`auth(...) &Account`) is necessary, such as a cold storage multi-sig, but those cases are rare and should only be used if it is a very restricted subset of account functionality that is required. ## Public functions and fields should be avoided ### Problem Be sure to keep track of access modifiers when structuring your code, and make public only what should be public. Accidentally exposed fields can be a security hole. ### Solution When writing your smart contract, look at every field and function and make sure that any functions that you don't want every user to be able to access require access through an [entitlement](/docs/language/access-control#entitlements) (`access(E)`), or use a non-public [access modifier](/docs/language/access-control) like `access(self)`, `access(contract)`, or `access(account)`. Declaring a function as `access(all)` is a deliberate design decision to allow completely open and unrestricted access to read that field or call that function and should not be taken lightly. The only functions that should be `access(all)` are `view` functions and functions the everyone should be able to access and the only fields that should be `access(all)` are basic types like numbers or addresses. Complex fields like arrays, dictionaries, structs, resources, or capabilities should always be `access(self)`. ## Capability-Typed public fields are a security hole This is a specific case of "Public Functions And Fields Should Be Avoided", above. ### Problem The values of public fields can be copied. Capabilities are value types, so if they are used as a public field, anyone can copy it from the field and call the functions that it exposes. This almost certainly is not what you want if a capability has been stored as a field on a contract or resource in this way. ### Solution For public access to a capability, place it in an accounts public area so this expectation is explicit. ## Public admin resource creation functions are unsafe This is a specific case of "Public Functions And Fields Should Be Avoided", above. ### Problem A public function on a contract that creates a resource can be called by any account. If that resource provides access to admin functions then the creation function should not be public. ### Solution To fix this, a single instance of that resource should be created in the contract's initializer, and then a new creation function can be potentially included within the admin resource, if necessary. ### Example ```cadence // Pseudo-code // BAD access(all) contract Currency { access(all) resource Admin { access(all) fun mintTokens() } // Anyone in the network can call this function // And use the Admin resource to mint tokens access(all) fun createAdmin(): @Admin { return <-create Admin() } } // This contract makes the admin creation private and in the initializer // so that only the one who controls the account can mint tokens // GOOD access(all) contract Currency { access(all) resource Admin { access(all) fun mintTokens() // Only an admin can create new Admins access(all) fun createAdmin(): @Admin { return <-create Admin() } } init() { // Create a single admin resource let firstAdmin <- create Admin() // Store it in private account storage, so only the admin can use it self.account.storage.save(<-firstAdmin, to: /storage/currencyAdmin) } } ``` ## Do not modify smart contract state or emit events in public struct initializers This is another example of the risks of having publicly accessible parts to your smart contract. ### Problem Data structure definitions in Cadence currently must be declared as public so that they can be used by anyone. Structs do not have the same restrictions that resources have on them, which means that anyone can create a new instance of a struct without going through any authorization. ### Solution Any contract state-modifying operations related to the creation of structs should be contained in resources instead of the initializers of structs. ### Example This used to be a bug in the NBA Top Shot smart contract, so we'll use that as an example. Before, when it created a new play, [it would initialize the play record with a struct,](https://github.com/dapperlabs/nba-smart-contracts/blob/55645478594858a6830e4ab095034068ef9753e9/contracts/TopShot.cdc#L155-L158) which increments the number that tracks the play IDs and emits an event: ```cadence // Simplified Code // BAD // access(all) contract TopShot { // The Record that is used to track every unique play ID access(all) var nextPlayID: UInt32 access(all) struct Play { access(all) let playID: UInt32 init() { self.playID = TopShot.nextPlayID // Increment the ID so that it isn't used again TopShot.nextPlayID = TopShot.nextPlayID + 1 emit PlayCreated(id: self.playID, metadata: metadata) } } } ``` This is a risk because anyone can create the `Play` struct as many times as they want, which could increment the `nextPlayID` field to the max `UInt32` value, effectively preventing new plays from being created. It also would emit bogus events. This bug was fixed by [instead updating the contract state in the admin function](https://github.com/dapperlabs/nba-smart-contracts/blob/master/contracts/TopShot.cdc#L682-L685) that creates the plays. ```cadence // Update contract state in admin resource functions // GOOD // access(all) contract TopShot { // The Record that is used to track every unique play ID access(all) var nextPlayID: UInt32 access(all) struct Play { access(all) let playID: UInt32 init() { self.playID = TopShot.nextPlayID } } access(all) resource Admin { // Protected within the private admin resource access(all) fun createPlay() { // Create the new Play var newPlay = Play() // Increment the ID so that it isn't used again TopShot.nextPlayID = TopShot.nextPlayID + UInt32(1) emit PlayCreated(id: newPlay.playID, metadata: metadata) // Store it in the contract storage TopShot.playDatas[newPlay.playID] = newPlay } } } ``` --- # Protocol Smart Contracts 1.0 Changes Guide (/docs/cadence-migration-guide/core-contracts-guide) # Protocol Smart Contracts in Cadence 1.0 :::important On September 4th, 2024, the Flow Mainnet upgraded to Cadence 1.0. In addition to many changes to the Cadence programming language and the Cadence token standards, the Flow Protocol smart contracts were also updated to be compatible with the changes. All applications that interact with these contracts need to update their transactions and scripts in order to be compatible with these changes. ::: ## Important info This document assumes you have a basic understanding of the [Cadence 1.0 improvements] 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 [`master` branch of the flow-core-contracts repo]. Please look at the [PR that made the changes] to understand how the contracts have changed. Every contract in the repo changed. Additionally, here are the import addresses for all of the important contracts related to the protocol: | Contract | Emulator import address | Testing framework | | --------------------------- | ----------------------- | -------------------- | | `FungibleToken` | `0xee82856bf20e2aa6` | `0x0000000000000002` | | `ViewResolver` | `0xf8d6e0586b0a20c7` | `0x0000000000000001` | | `Burner` | `0xf8d6e0586b0a20c7` | `0x0000000000000001` | | `MetadataViews` | `0xf8d6e0586b0a20c7` | `0x0000000000000001` | | `FungibleTokenMetadataViews`| `0xee82856bf20e2aa6` | `0x0000000000000002` | | `FlowToken` | `0x0ae53cb6e3f42a79` | `0x0000000000000003` | | `FlowFees` | `0xe5a8b7f23e8b548f` | `0x0000000000000004` | | `FlowStorageFees` | `0xf8d6e0586b0a20c7` | `0x0000000000000001` | | `FlowServiceAccount` | `0xf8d6e0586b0a20c7` | `0x0000000000000001` | | `NodeVersionBeacon` | `0xf8d6e0586b0a20c7` | `0x0000000000000001` | | `RandomBeaconHistory` | `0xf8d6e0586b0a20c7` | `0x0000000000000001` | | `LockedTokens` | `0xf8d6e0586b0a20c7` | `0x0000000000000001` | | `StakingProxy` | `0xf8d6e0586b0a20c7` | `0x0000000000000001` | | `FlowIDTableStaking` | `0xf8d6e0586b0a20c7` | `0x0000000000000001` | | `FlowClusterQC` | `0xf8d6e0586b0a20c7` | `0x0000000000000001` | | `FlowDKG` | `0xf8d6e0586b0a20c7` | `0x0000000000000001` | | `FlowEpoch` | `0xf8d6e0586b0a20c7` | `0x0000000000000001` | | `FlowStakingCollection` | `0xf8d6e0586b0a20c7` | `0x0000000000000001` | 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. The core contracts do not have any meaningful changes outside of what is required to be compatible with Cadence 1.0 and the token standard changes. If you have questions about the core contracts changes for Cadence 1.0, please reach out to the Flow team in Discord and we will be happy to help. {/* Relative links. Will not render on the page */} [Cadence 1.0 improvements]: ./improvements [`master` branch of the flow-core-contracts repo]: https://github.com/onflow/flow-core-contracts [PR that made the changes]: https://github.com/onflow/flow-core-contracts/pull/319 --- # Fungible Token Cadence 1.0 Migration Guide (/docs/cadence-migration-guide/ft-guide) # Fungible Tokens in Cadence 1.0 :::important On September 4th, 2024, the Flow Mainnet upgraded to Cadence 1.0. In addition to many changes to the Cadence programming language, the Cadence token standards also got streamlined and improved. All applications need to migrate their existing Cadence scripts and transactions for the update. If you do not update your code, your application will not function. ::: This document describes the changes to the Cadence Fungible Token (FT) standard. We'll be using the [`ExampleToken` contract] 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] that describes the changes to the `FungibleToken` standard first. The updated code for the V2 Fungible Token standard is located in the [`master` branch of the flow-ft repo]. Please look at the [PR that made the changes] to understand how the standard and examples have changed. Note the changes to the `FungibleTokenMetadataViews`, `Burner`, `FungibleTokenSwitchboard`, and `TokenForwarding` contracts. Additionally, here are the import addresses for all of the important contracts related to fungible tokens. The second column is the import address if you are testing with a basic version of the emulator. The third column contains the import addresses if you are using the Cadence testing framework: | Contract | Emulator import address | Testing framework | | --------------------------- | ----------------------- | -------------------- | | `FungibleToken` | `0xee82856bf20e2aa6` | `0x0000000000000002` | | `ViewResolver` | `0xf8d6e0586b0a20c7` | `0x0000000000000001` | | `Burner` | `0xf8d6e0586b0a20c7` | `0x0000000000000001` | | `MetadataViews` | `0xf8d6e0586b0a20c7` | `0x0000000000000001` | | `FungibleTokenMetadataViews`| `0xee82856bf20e2aa6` | `0x0000000000000002` | | `FungibleTokenSwitchboard` | `0xee82856bf20e2aa6` | `0x0000000000000002` | 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** β€” USDC was migrated to standard bridged USDC on Flow. See the [repo] for the latest version of the USDC contract. - **Account Linking and Hybrid Custody** β€” See [this PR in the hybrid custody repo] for updated hybrid custody contracts. [This Discord announcement] also contains versions of a lot of important contracts. Use the [Flow Contract Browser] to find the 1.0 code of other contracts. ## Migration guide Please see the [NFT Cadence 1.0 migration guide]. While the contracts aren't exactly the same, they share a large 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`. 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. Here's an example in `deposit()`: ```cadence /// deposit now accepts a resource that implements the `FungibleToken.Vault` interface type access(all) fun deposit(from: @{FungibleToken.Vault}) ``` If you have any more questions, please ask in discord and the Flow team will be happy to assist! {/* Relative links. Will not render on the page */} [`ExampleToken` contract]: https://github.com/onflow/flow-ft/blob/master/contracts/ExampleToken.cdc [FLIP]: https://github.com/onflow/flips/pull/55 [`master` branch of the flow-ft repo]: https://github.com/onflow/flow-ft [PR that made the changes]: https://github.com/onflow/flow-ft/pull/131 [repo]: https://github.com/onflow/bridged-usdc [this PR in the hybrid custody repo]: https://github.com/onflow/hybrid-custody/pull/164 [This Discord announcement]: https://discord.com/channels/613813861610684416/811693600403357706/1225909248429527140 [Flow Contract Browser]: https://contractbrowser.com/ [NFT Cadence 1.0 migration guide]: ./nft-guide --- # Cadence 1.0 Improvements & New Features (/docs/cadence-migration-guide/improvements) ## πŸ’« New features Cadence 1.0 was released in October of 2024. This page provides a historical reference of changes.
View Functions added ([FLIP 1056]) #### πŸ’‘ Motivation View functions enable developers to enhance the reliability and safety of their programs, facilitating a clearer understanding of the impacts of their own code and that of others. Developers can mark their functions as `view`, which disallows the function from performing state changes. That also makes the intent of functions clear to other programmers, as it allows them to distinguish between functions that change state and ones that do not. #### ℹ️ Description Cadence has added support for annotating functions with the `view` keyword, which enforces that no _mutating_ operations occur inside the body of the function. The `view` keyword is placed before the `fun` keyword in a function declaration or function expression. If a function has no `view` annotation, it is considered _non-view_, and users should encounter no difference in behavior in these functions from what they are used to. If a function does have a `view` annotation, then the following mutating operations are not allowed: - Writing to, modifying, or destroying any resources - Writing to or modifying any references - Assigning to or modifying any variables that cannot be determined to have been created locally inside of the `view` function in question. In particular, this means that captured and global variables cannot be written in these functions - Calling a non-`view` function This feature was proposed in [FLIP 1056]. To learn more, please consult the FLIP and documentation. #### πŸ”„ Adoption You can adopt view functions by adding the `view` modifier to all functions that do not perform mutating operations. #### ✨ Example Before: The function `getCount` of a hypothetical NFT collection returns the number of NFTs in the collection. ```cadence access(all) resource Collection { access(all) var ownedNFTs: @{UInt64: NonFungibleToken.NFT} init () { self.ownedNFTs <- {} } access(all) fun getCount(): Int { returnself.ownedNFTs.length } /* ... rest of implementation ... */ } ``` After: The function `getCount` does not perform any state changes, it only reads the length of the collection and returns it. Therefore it can be marked as `view.` ```cadence access(all) view fun getCount(): Int { // ^^^^ addedreturnself.ownedNFTs.length } ```
Interface Inheritance Added ([FLIP 40]) #### πŸ’‘ Motivation Previously, interfaces could not inherit from other interfaces, which required developers to repeat code. Interface inheritance allows code abstraction and code reuse. #### ℹ️ Description and ✨ Example Interfaces can now inherit from other interfaces of the same kind. This makes it easier for developers to structure their conformances and reduces a lot of redundant code. For example, suppose there are two resource interfaces, `Receiver` and `Vault`, and suppose all implementations of the `Vault` would also need to conform to the interface `Receiver`. Previously, there was no way to enforce this. Anyone who implements the `Vault` would have to explicitly specify that their concrete type also implements the `Receiver`. But it was not always guaranteed that all implementations would follow this informal agreement. With interface inheritance, the `Vault` interface can now inherit/conform to the `Receiver` interface. ```cadence access(all) resource interface Receiver { access(all) fun deposit(_ something:@AnyResource) } access(all) resource interface Vault: Receiver { access(all) fun withdraw(_ amount: Int):@Vault } ``` Thus, anyone implementing the `Vault` interface would also have to implement the `Receiver` interface as well. ```cadence access(all) resource MyVault: Vault { // Required! access(all) fun withdraw(_ amount: Int):@Vault {} // Required! access(all) fun deposit(_ something:@AnyResource) {} } ``` This feature was proposed in [FLIP 40]. To learn more, please consult the FLIP and documentation.
## ⚑ Breaking improvements Many of the improvements of Cadence 1.0 are fundamentally changing how Cadence works and how it is used. However, that also means it is necessary to break existing code to release this version, which will guarantee stability (no more planned breaking changes) going forward. Once Cadence 1.0 is live, breaking changes will simply not be acceptable. So we have, and need to use, this last chance to fix and improve Cadence, so it can deliver on its promise of being a language that provides security and safety, while also providing composability and simplicity. We fully recognize the frustration developers feel when updates break their code, necessitating revisions. Nonetheless, we are convinced that this inconvenience is justified by the substantial enhancements to Cadence development. These improvements not only make development more effective and enjoyable but also empower developers to write and deploy immutable contracts. The improvements were intentionally bundled into one release to avoid breaking Cadence programs multiple times.
**2024-04-24** Public Capability Acquisition No Longer Returns Optional Capabilities ([FLIP 242]) **Note** This is a recent change that may not be reflected in emulated migrations or all tools yet. Likewise, this may affect existing staged contracts which do not conform to this new requirement. Please ensure your contracts are updated and re-staged, if necessary, to match this new requirement. #### πŸ’‘ Motivation In the initial implementation of the new Capability Controller API (a change that is new in Cadence 1.0, proposed in [FLIP 798]), `capabilities.get` would return an optional capability, `Capability?`. When the no capability was published under the requested path, or when type argument `T` was not a subtype of the runtime type of the capability published under the requested path, the capability would be `nil`. This was a source of confusion among developers, as previously `account.getCapability` did not return an optional capability, but rather one that would simply fail `capability.borrow` if the capability was invalid. It was concluded that this new behavior was not ideal, and that there a benefit to an invalid Capability not being `nil`, even if it is not borrowable. A `nil` capability lacked information that was previously available with an invalid capability - primarily the type and address of the capability. Developers may have wanted to make use of this information, and react to the capability being invalid, as opposed to an uninformative `nil` value and encountering a panic scenario. #### ℹ️ Description The `capabilities.get` function now returns an invalid capability when no capability is published under the requested path, or when the type argument `T` is not a subtype of the runtime type of the capability published under the requested path. This capability has the following properties: - Always return `false` when `Capability.check` is called. - Always return `nil` when `Capability.borrow` is called. - Have an ID of `0`. - Have a runtime type that is the same as the type requested in the type argument of `capabilities.get`.
#### πŸ”„ Adoption If you have not updated your code to Cadence 1.0 yet, you will need to follow the same guidelines for updating to the Capability Controller API as you would have before, but you will need to handle the new invalid capability type instead of an optional capability. If you have already updated your code to use `capabilities.get`, and are handling the capability as an optional type, you may need to update your code to handle the new non-optional invalid capability type instead. #### ✨ Example **Before:** ```cadence let capability = account.capabilities.get<&MyNFT.Collection>(/public/NFTCollection) if capability == nil { // Handle the case where the capability is nil } ``` **After:** ```cadence let capability = account.capabilities.get<&MyNFT.Collection>(/public/NFTCollection) if !capability.check() { // Handle the case where the capability is invalid } ```
**2024-04-23** Matching Access Modifiers for Interface Implementation Members are now Required ([FLIP 262]) **Note** This is a recent change that may not be reflected in emulated migrations or all tools yet. Likewise, this may affect existing staged contracts which do not conform to this new requirement. Please ensure your contracts are updated and re-staged, if necessary, to match this new requirement. #### πŸ’‘ Motivation Previously, the access modifier of a member in a type conforming to / implementing an interface could not be more restrictive than the access modifier of the member in the interface. That meant an implementation may have choosen to use a more permissive access modifier than the interface. This may have been surprising to developers, as they may have assumed that the access modifier of the member in the interface was a _requirement_ / _maximum_, not just a minimum, especially when using a non-public / non-entitled access modifier (e.g., `access(contract)`, `access(account)`). Requiring access modifiers of members in the implementation to match the access modifiers of members given in the interface, helps avoid confusion and potential footguns. #### ℹ️ Description If an interface member has an access modifier, a composite type that conforms to it / implements the interface must use exactly the same access modifier. #### πŸ”„ Adoption Update the access modifiers of members in composite types that conform to / implement interfaces if they do not match the access modifiers of the members in the interface. #### ✨ Example **Before:** ```cadence access(all) resource interface I { access(account) fun foo() } access(all) resource R: I { access(all) fun foo() {} } ``` **After:** ```cadence access(all) resource interface I { access(account) fun foo() } access(all) resource R: I { access(account) fun foo() {} } ```
Conditions No Longer Allow State Changes ([FLIP 1056]) #### πŸ’‘ Motivation In the current version of Cadence, pre-conditions and post-conditions may perform state changes, e.g., by calling a function that performs a mutation. This may result in unexpected behavior, which might lead to bugs. To make conditions predictable, they are no longer allowed to perform state changes. #### ℹ️ Description Pre-conditions and post-conditions are now considered `view` contexts, meaning that any operations that would be prevented inside of a `view` function are also not permitted in a pre-condition or post-condition. This is to prevent underhanded code wherein a user modifies global or contract state inside of a condition, where they are meant to simply be asserting properties of that state. In particular, since only expressions were permitted inside conditions already, this means that if users wish to call any functions in conditions, these functions must now be made `view` functions. This improvement was proposed in [FLIP 1056]. To learn more, please consult the FLIP and documentation. #### πŸ”„ Adoption Conditions that perform mutations will now result in the error _Impure operation performed in view context_. Adjust the code in the condition so it does not perform mutations. The condition may be considered mutating, because it calls a mutating, i.e., non-`view` function. It might be possible to mark the called function as `view`, and the body of the function may need to get updated in turn. #### ✨ Example **Before:** The function `withdraw` of a hypothetical NFT collection interface allows the withdrawal of an NFT with a specific ID. In its post-condition, the function states that at the end of the function, the collection should have exactly one fewer item than at the beginning of the function. ```cadence access(all) resource interface Collection { access(all) fun getCount(): Int access(all) fun withdraw(id: UInt64):@NFT { post { getCount() == before(getCount()) - 1 } } /* ... rest of interface ... */ } ``` **After:** The calls to `getCount` in the post-condition are not allowed and result in the error _Impure operation performed in view context_, because the `getCount` function is considered a mutating function, as it does not have the `view` modifier. Here, as the `getCount` function only performs a read-only operation and does not change any state, it can be marked as `view`. ```cadence access(all) view fun getCount(): Int // ^^^^ ```
Missing or Incorrect Argument Labels Get Reported #### πŸ’‘ Motivation Previously, missing or incorrect argument labels of function calls were not reported. This had the potential to confuse developers or readers of programs, and could potentially lead to bugs. #### ℹ️ Description Function calls with missing argument labels are now reported with the error message _missing argument label_, and function calls with incorrect argument labels are now reported with the error message _incorrect argument label_. #### πŸ”„ Adoption - Function calls with missing argument labels should be updated to include the required argument labels. - Function calls with incorrect argument labels should be fixed by providing the correct argument labels. #### ✨ Example Contract `TestContract` deployed at address `0x1`: ```cadence access(all) contract TestContract { access(all) structTestStruct { access(all) let a: Int access(all) let b: String init(first: Int, second: String) { self.a = first self.b = second } } } ``` **Incorrect program**: The initializer of `TestContract.TestStruct` expects the argument labels `first` and `second`. However, the call of the initializer provides the incorrect argument label `wrong` for the first argument, and is missing the label for the second argument. ```cadence // Script import TestContract from 0x1 access(all) fun main() { TestContract.TestStruct(wrong: 123, "abc") } ``` This now results in the following errors: ``` error: incorrect argument label --> script:4:34 | 4 | TestContract.TestStruct(wrong: 123, "abc") | ^^^^^ expected `first`, got `wrong` error: missing argument label: `second` --> script:4:46 | 4 | TestContract.TestStruct(wrong: 123, "abc") | ^^^^^ ``` **Corrected program**: ```cadence // Script import TestContract from 0x1 access(all) fun main() { TestContract.TestStruct(first: 123, second: "abc") } ``` We would like to thank community member @justjoolz for reporting this bug.
Incorrect Operators In Reference Expressions Get Reported ([FLIP 941]) #### πŸ’‘ Motivation Previously, incorrect operators in reference expressions were not reported. This had the potential to confuse developers or readers of programs, and could potentially lead to bugs. #### ℹ️ Description The syntax for reference expressions is `&v as &T`, which represents taking a reference to value `v` as type `T`. Reference expressions that used other operators, such as `as?` and `as!`, e.g., `&v as! &T`, were incorrect and were previously not reported as an error. The syntax for reference expressions improved to just `&v`. The type of the resulting reference must still be provided explicitly. If the type is not explicitly provided, the error _cannot infer type from reference expression: requires an explicit type annotation_ is reported. For example, existing expressions like `&v as &T` provide an explicit type, as they statically assert the type using `as &T`. Such expressions thus keep working and do *not* have to be changed. Another way to provide the type for the reference is by explicitly typing the target of the expression, for example, in a variable declaration, e.g., via `let ref: &T = &v`. This improvement was proposed in [FLIP 941]. To learn more, please consult the FLIP and documentation. #### πŸ”„ Adoption Reference expressions which use an operator other than `as` need to be changed to use the `as` operator. In cases where the type is already explicit, the static type assertion (`as &T`) can be removed. #### ✨ Example **Incorrect program**: The reference expression uses the incorrect operator `as!`. ```cadence let number = 1 let ref = &number as! &Int ``` This now results in the following error: ```bash error: cannot infer type from reference expression: requires an explicit type annotation --> test:3:17 | 3 |let ref = &number as! &Int | ^ ``` **Corrected program**: ```cadence let number = 1 let ref = &number as &Int ``` Alternatively, the same code can now also be written as follows: ```cadence let number = 1 let ref: &Int = &number ```
Tightening Of Naming Rules #### πŸ’‘ Motivation Previously, Cadence allowed language keywords (e.g., `continue`, `for`, etc.) to be used as names. For example, the following program was allowed: ```cadence fun continue(import: Int, break: String) { ... } ``` This had the potential to confuse developers or readers of programs, and could potentially lead to bugs. #### ℹ️ Description Most language keywords are no longer allowed to be used as names. Some keywords are still allowed to be used as names, as they have limited significance within the language. These allowed keywords are as follows: - `from`: only used in import statements `import foo from ...` - `account`: used in access modifiers `access(account) let ...` - `all`: used in access modifier `access(all) let ...` - `view`: used as a modifier for function declarations and expressions `view fun foo()...`, let `f = view fun () ...` Any other keywords will raise an error during parsing, such as: ```cadence let break: Int = 0 // ^ error: expected identifier after start of variable declaration, got keyword break ``` #### πŸ”„ Adoption Names that use language keywords must be renamed. #### ✨ Example **Before:** A variable is named after a language keyword. ```cadence let contract = signer.borrow<&MyContract>(name: "MyContract") // ^ error: expected identifier after start of variable declaration, got keyword contract ``` **After:** The variable is renamed to avoid the clash with the language keyword. ```cadence let myContract = signer.borrow<&MyContract>(name: "MyContract") ```
Result of `toBigEndianBytes()` for `U?Int(128|256)` Fixed #### πŸ’‘ Motivation Previously, the implementation of `.toBigEndianBytes()` was incorrect for the large integer types `Int128`, `Int256`, `UInt128`, and `UInt256`. This had the potential to confuse developers or readers of programs, and could potentially lead to bugs. #### ℹ️ Description Calling the `toBigEndianBytes` function on smaller sized integer types returns the exact number of bytes that fit into the type, left-padded with zeros. For instance, `Int64(1).toBigEndianBytes()` returns an array of 8 bytes, as the size of `Int64` is 64 bits, 8 bytes. Previously, the `toBigEndianBytes` function erroneously returned variable-length byte arrays without padding for the large integer types `Int128`, `Int256`, `UInt128`, and `UInt256`. This was inconsistent with the smaller fixed-size numeric types, such as `Int8` and `Int32`. To fix this inconsistency, `Int128` and `UInt128` now always return arrays of 16 bytes, while `Int256` and `UInt256` return 32 bytes. #### ✨ Example ```cadence let someNum: UInt128 = 123456789 let someBytes: [UInt8] = someNum.toBigEndianBytes() // OLD behavior; // someBytes = [7, 91, 205, 21] // NEW behavior: // someBytes = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 91, 205, 21] ``` #### πŸ”„ Adoption Programs that use `toBigEndianBytes` directly, or indirectly by depending on other programs, should be checked for how the result of the function is used. It might be necessary to adjust the code to restore existing behavior. If a program relied on the previous behavior of truncating the leading zeros, then the old behavior can be recovered by first converting to a variable-length type, `Int` or `UInt`, as the `toBigEndianBytes` function retains the variable-length byte representations, i.e., the result has no padding bytes. ```cadence let someNum: UInt128 = 123456789 let someBytes: [UInt8] = UInt(someNum).toBigEndianBytes() // someBytes = [7, 91, 205, 21] ```
Syntax for Function Types Improved ([FLIP 43]) #### πŸ’‘ Motivation Previously, function types were expressed using a different syntax from function declarations or expressions. The previous syntax was unintuitive for developers, making it hard to write and read code that used function types. #### ℹ️ Description and ✨ examples Function types are now expressed using the `fun` keyword, just like expressions and declarations. This improves readability and makes function types more obvious. For example, given the following function declaration: ```cadence fun foo(n: Int8, s: String): Int16 { /* ... */ } ``` The function `foo` now has the type `fun(Int8, String): Int16`. The `:` token is right-associative, so functions that return other functions can have their types written without nested parentheses: ```cadence fun curriedAdd(_ x: Int): fun(Int): Int { return fun(_ y: Int): Int { return x+ y } } // function `curriedAdd` has the type `fun(Int): fun(Int): Int` ``` To further bring the syntax for function types closer to the syntax of function declarations expressions, it is now possible to omit the return type, in which case the return type defaults to `Void`. ```cadence fun logTwice(_ value: AnyStruct) {// Return type is implicitly `Void` log(value) log(value) } // The function types of these variables are equivalent let logTwice1: fun(AnyStruct): Void = logTwice let logTwice2: fun(AnyStruct) = logTwice ``` As a bonus consequence, it is now allowed for any type to be parenthesized. This is useful for complex type signatures, or for expressing optional functions: ```cadence // A function that returns an optional Int16 let optFun1: fun (Int8): Int16? = fun (_: Int8): Int? { return nil } // An optional function that returns an Int16 let optFun2: (fun (Int8): Int16)? = nil ``` This improvement was proposed in [FLIP 43]. #### πŸ”„ Adoption Programs that use the old function type syntax need to be updated by replacing the surrounding parentheses of function types with the `fun` keyword. **Before:** ```cadence let baz: ((Int8, String): Int16) = foo // ^ ^ // surrounding parentheses of function type ``` **After:** ```cadence let baz: fun (Int8, String): Int16 = foo ```
Entitlements and Safe Down-casting ([FLIP 54] & [FLIP 94]) #### πŸ’‘ Motivation Previously, Cadence’s main access-control mechanism, restricted reference types, has been a source of confusion and mistakes for contract developers. Developers new to Cadence often were surprised and did not understand why access-restricted functions, like the `withdraw` function of the fungible token `Vault` resource type, were declared as `pub`, making the function publicly accessible β€” access would later be restricted through a restricted type. It was too easy to accidentally give out a `Capability` with a more permissible type than intended, leading to security problems. Additionally, because what fields and functions were available to a reference depended on what the type of the reference was, references could not be downcast, leading to ergonomic issues. #### ℹ️ Description Access control has improved significantly. When giving another user a reference or `Capability` to a value you own, the fields and functions that the user can access is determined by the type of the reference or `Capability`. Previously, access to a value of type `T`, e.g., via a reference `&T`, would give access to all fields and functions of `T`. Access could be restricted, by using a restricted type. For example, a restricted reference `&T{I}` could only access members that were `pub` on `I`. Since references could not be downcast, any members defined on `T` but not on `I` were unavailable to this reference, even if they were `pub`. Access control is now handled using a new feature called Entitlements, as originally proposed across [FLIP 54] and [FLIP 94]. A reference can now be _entitled_ to certain facets of an object. For example, the reference `auth(Withdraw) &Vault` is entitled to access fields and functions of `Vault` which require the `Withdraw` entitlement. Entitlements can be are declared using the new `entitlement` syntax. Members can be made to require entitlements using the access modifier syntax `access(E)`, where `E` is an entitlement that the user must posses. For example: ```cadence entitlement Withdraw access(Withdraw) fun withdraw(amount: UFix64): @Vault ``` References can now always be down-casted, the standalone `auth` modifier is not necessary anymore, and has been removed. For example, the reference `&{Provider}` can now be downcast to `&Vault`, so access control is now handled entirely through entitlements, rather than types. See [Entitlements] for more information. #### πŸ”„ Adoption The access modifiers of fields and functions need to be carefully audited and updated. Fields and functions that have the `pub` access modifier are now callable by anyone with any reference to that type. If access to the member should be restricted, the `pub` access modifier needs to be replaced with an entitlement access modifier. When creating a `Capability` or a reference to a value, **it must be carefully considered which entitlements are provided to the recipient of that `Capability` or reference** β€” only the entitlements which are necessary and not more should be include in the `auth` modifier of the reference type. #### ✨ Example **Before:** The `Vault` resource was originally written like so: ```cadence access(all) resource interface Provider { access(all) funwithdraw(amount:UFix64): @Vault { // ... } } access(all) resource Vault: Provider, Receiver, Balance { access(all) fun withdraw(amount:UFix64): @Vault { // ... } access(all) fun deposit(from: @Vault) { // ... } access(all) var balance: UFix64 } ``` **After:** The `Vault` resource might now be written like this: ```cadence access(all) entitlement Withdraw access(all) resource interface Provider { access(Withdraw) funwithdraw(amount:UFix64): @Vault { // ... } } access(all) resource Vault: Provider, Receiver, Balance { access(Withdraw)// withdrawal requires permission fun withdraw(amount:UFix64): @Vault { // ... } access(all) fun deposit(from: @Vault) { // ... } access(all) var balance: UFix64 } ``` Here, the `access(Withdraw)` syntax means that a reference to `Vault` must possess the `Withdraw` entitlement in order to be allowed to call the `withdraw` function, which can be given when a reference or `Capability` is created by using a new syntax: `auth(Withdraw) &Vault`. This would allow developers to safely downcast `&{Provider}` references to `&Vault` references if they want to access functions like `deposit` and `balance`, without enabling them to call `withdraw`.
Removal of `pub` and `priv` Access Modifiers ([FLIP 84]) #### πŸ’‘ Motivation With the previously mentioned entitlements feature, which uses `access(E)` syntax to denote entitled access, the `pub`, `priv`, and `pub(set)` modifiers became the only access modifiers that did not use the `access` syntax. This made the syntax inconsistent, making it harder to read and understand programs. In addition, `pub` and `priv` already had alternatives/equivalents: `access(all)` and `access(self)`. #### ℹ️ Description The `pub`, `priv` and `pub(set)` access modifiers are being removed from the language, in favor of their more explicit `access(all)` and `access(self)` equivalents (for `pub` and `priv`, respectively). This makes access modifiers more uniform and better match the new entitlements syntax. This improvement was originally proposed in [FLIP 84]. #### πŸ”„ Adoption Users should replace any `pub` modifiers with `access(all)`, and any `priv` modifiers with `access(self)`. Fields that were defined as `pub(set)` will no longer be publicly assignable, and no access modifier now exists that replicates this old behavior. If the field should stay publicly assignable, a `access(all)` setter function that updates the field needs to be added, and users have to switch to using it instead of directly assigning to the field. #### ✨ Example **Before:** Types and members could be declared with `pub` and `priv`: ```cadence pub resource interface Collection { pub fun getCount(): Int priv fun myPrivateFunction() pub(set) let settableInt: Int /* ... rest of interface ... */ } ``` **After:** The same behavior can be achieved with `access(all)` and `access(self)` ```cadence access(all) resource interface Collection { access(all) fun getCount(): Int access(self) fun myPrivateFunction() access(all) let settableInt: Int // Add a public setter method, replacing pub(set) access(all) fun setIntValue(_ i:Int): Int /* ... rest of interface ... */ } ```
Replacement of Restricted Types with Intersection Types ([FLIP 85]) #### πŸ’‘ Motivation With the improvements to access control enabled by entitlements and safe down-casting, the restricted type feature is redundant. #### ℹ️ Description Restricted types have been removed. All types, including references, can now be down-casted, restricted types are no longer used for access control. At the same time intersection types got introduced. Intersection types have the syntax `{I1, I2, ... In}`, where all elements of the set of types (`I1, I2, ... In`) are interface types. A value is part of the intersection type if it conforms to all the interfaces in the intersection type’s interface set. This functionality is equivalent to restricted types that restricted `AnyStruct` and `AnyResource.` This improvement was proposed in [FLIP 85]. To learn more, please consult the FLIP and documentation. #### πŸ”„ Adoption Code that relies on the restriction behavior of restricted types can be safely changed to just use the concrete type directly, as entitlements will make this safe. For example, `&Vault{Balance}` can be replaced with just `&Vault`, as access to `&Vault` only provides access to safe operations, like getting the balance β€” **privileged operations, like withdrawal, need additional entitlements.** Code that uses `AnyStruct` or `AnyResource` explicitly as the restricted type, e.g., in a reference, `&AnyResource{I}`, needs to remove the use of `AnyStruct` / `AnyResource`. Code that already uses the syntax `&{I}` can stay as-is. #### ✨ Example **Before:** This function accepted a reference to a `T` value, but restricted what functions were allowed to be called on it to those defined on the `X`, `Y`, and `Z` interfaces. ```cadence access(all) resource interface X { access(all) fun foo() } access(all) resource interface Y { access(all) fun bar() } access(all) resource interface Z { access(all) fun baz() } access(all) resource T: X, Y, Z { // implement interfaces access(all) fun qux() { // ... } } access(all) fun exampleFun(param: &T{X, Y, Z}) { // `param` cannot call `qux` here, because it is restricted to // `X`, `Y` and `Z`. } ``` **After:** This function can be safely rewritten as: ```cadence access(all) resource interface X { access(all) fun foo() } access(all) resource interface Y { access(all) fun bar() } resource interface Z { access(all) fun baz() } access(all) entitlement Q access(all) resource T: X, Y, Z { // implement interfaces access(Q) fun qux() { // ... } } access(all) fun exampleFun(param: &T) { // `param` still cannot call `qux` here, because it lacks entitlement `Q` } ``` Any functions on `T` that the author of `T` does not want users to be able to call publicly should be defined with entitlements, and thus will not be accessible to the unauthorized `param` reference, like with `qux` above.
Account Access Got Improved ([FLIP 92]) #### πŸ’‘ Motivation Previously, access to accounts was granted wholesale: Users would sign a transaction, authorizing the code of the transaction to perform any kind of operation, for example, write to storage, but also add keys or contracts. Users had to trust that a transaction would only perform supposed access, e.g., storage access to withdraw tokens, but still had to grant full access, which would allow the transaction to perform other operations. Dapp developers who require users to sign transactions should be able to request the minimum amount of access to perform the intended operation, i.e., developers should be able to follow the principle of least privilege (PoLA). This allows users to trust the transaction and Dapp. #### ℹ️ Description Previously, access to accounts was provided through the built-in types `AuthAccount` and `PublicAccount`: `AuthAccount` provided full *write* access to an account, whereas `PublicAccount` only provided *read* access. With the introduction of entitlements, this access is now expressed using entitlements and references, and only a single `Account` type is necessary. In addition, storage related functionality were moved to the field `Account.storage`. Access to administrative account operations, such as writing to storage, adding keys, or adding contracts, is now gated by both coarse grained entitlements (e.g., `Storage`, which grants access to all storage related functions, and `Keys`, which grants access to all key management functions), as well as fine-grained entitlements (e.g., `SaveValue` to save a value to storage, or `AddKey` to add a new key to the account). Transactions can now request the particular entitlements necessary to perform the operations in the transaction. This improvement was proposed in [FLIP 92]. To learn more, consult the FLIP and the documentation. #### πŸ”„ Adoption Code that previously used `PublicAccount` can simply be replaced with an unauthorized account reference, `&Account.` Code that previously used `AuthAccount` must be replaced with an authorized account reference. Depending on what functionality of the account is accessed, the appropriate entitlements have to be specified. For example, if the `save` function of `AuthAccount` was used before, the function call must be replaced with `storage.save`, and the `SaveValue` or `Storage` entitlement is required. #### ✨ Example **Before:** The transactions wants to save a value to storage. It must request access to the whole account, even though it does not need access beyond writing to storage. ```cadence transaction { prepare(signer: AuthAccount) { signer.save("Test", to: /storage/test) } } ``` **After:** The transaction requests the fine-grained account entitlement `SaveValue`, which allows the transaction to call the `save` function. ```cadence transaction { prepare(signer: auth(SaveValue)&Account) { signer.storage.save("Test", to: /storage/test) } } ``` If the transaction attempts to perform other operations, such as adding a new key, it is rejected: ```cadence transaction { prepare(signer: auth(SaveValue)&Account) { signer.storage.save("Test", to: /storage/test) signer.keys.add(/* ... */) // ^^^ Error: Cannot call function, requires `AddKey` or `Keys` entitlement } } ```
Deprecated Key Management API Got Removed #### πŸ’‘ Motivation Cadence provides two key management APIs: - The original, low-level API, which worked with RLP-encoded keys - The improved, high-level API, which works with convenient data types like `PublicKey`, `HashAlgorithm`, and `SignatureAlgorithm` The improved API was introduced, as the original API was difficult to use and error-prone. The original API was deprecated in early 2022. #### ℹ️ Description The original account key management API has been removed. Instead, the improved key management API should be used. To learn more, #### πŸ”„ Adoption Replace uses of the original account key management API functions with equivalents of the improved API: | Removed | Replacement | | --------------------------- | ------------------- | | AuthAccount.addPublicKey | Account.keys.add | | AuthAccount.removePublicKey | Account.keys.revoke | See [Account keys] for more information. #### ✨ Example **Before:** ```cadence transaction(encodedPublicKey: [UInt8]) { prepare(signer: AuthAccount) { signer.addPublicKey(encodedPublicKey) } } ``` **After:** ```cadence transaction(publicKey: [UInt8]) { prepare(signer: auth(Keys) &Account) { signer.keys.add( publicKey: PublicKey( publicKey: publicKey, signatureAlgorithm: SignatureAlgorithm.ECDSA_P256 ), hashAlgorithm: HashAlgorithm.SHA3_256, weight: 100.0 ) } } ```
Resource Tracking for Optional Bindings Improved #### πŸ’‘ Motivation Previously, resource tracking for optional bindings (_if-let statements_) was implemented incorrectly, leading to errors for valid code. This required developers to add workarounds to their code. #### ℹ️ Description Resource tracking for optional bindings (_if-let statements_) was fixed. For example, the following program used to be invalid, reporting a resource loss error for `optR`: ```cadence resource R {} fun asOpt(_ r: @R): @R? { return <-r } fun test() { let r <- create R() let optR <- asOpt(<-r) if let r2 <- optR { destroy r2 } } ``` This program is now considered valid. #### πŸ”„ Adoption New programs do not need workarounds anymore, and can be written naturally. Programs that previously resolved the incorrect resource loss error with a workaround, for example by invalidating the resource also in the else-branch or after the if-statement, are now invalid: ```cadence fun test() { let r <- createR() let optR <-asOpt(<-r) if let r2 <- optR { destroy r2 } else { destroy optR // unnecessary, but added to avoid error } } ``` The unnecessary workaround needs to be removed.
Definite Return Analysis Got Improved #### πŸ’‘ Motivation Definite return analysis determines if a function always exits, in all possible execution paths, e.g., through a `return` statement, or by calling a function that never returns, like `panic`. This analysis was incomplete and required developers to add workarounds to their code. #### ℹ️ Description The definite return analysis got significantly improved. This means that the following program is now accepted: both branches of the if-statement exit, one using a `return` statement, the other using a function that never returns, `panic`: ```cadence resource R {} fun mint(id: UInt64):@R { if id > 100 { return <- create R() } else { panic("bad id") } } ``` The program above was previously rejected with a _missing return statement_ error β€” even though we can convince ourselves that the function will exit in both branches of the if-statement, and that any code after the if-statement is unreachable, the type checker was not able to detect that β€” it now does. #### πŸ”„ Adoption New programs do not need workarounds anymore, and can be written naturally. Programs that previously resolved the incorrect error with a workaround, for example by adding an additional exit at the end of the function, are now invalid: ```cadence resource R {} fun mint(id: UInt64):@R { if id > 100 { return <- create R() } else { panic("bad id") } // unnecessary, but added to avoid error panic("unreachable") } ``` The improved type checker now detects and reports the unreachable code after the if-statement as an error: ```bash error: unreachable statement --> test.cdc:12:4 | 12| panic("unreachable") | ^^^^^^^^^^^^^^^^^^^^ exit status 1 ``` To make the code valid, simply remove the unreachable code.
Semantics for Variables in For-Loop Statements Got Improved ([FLIP 13]) #### πŸ’‘ Motivation Previously, the iteration variable of `for-in` loops was re-assigned on each iteration. Even though this is a common behavior in many programming languages, it is surprising behavior and a source of bugs. The behavior was improved to the often assumed/expected behavior of a new iteration variable being introduced for each iteration, which reduces the likelihood for a bug. #### ℹ️ Description The behavior of `for-in` loops improved, so that a new iteration variable is introduced for each iteration. This change only affects a few programs, as the behavior change is only noticeable if the program captures the iteration variable in a function value (closure). This improvement was proposed in [FLIP 13]. To learn more, consult the FLIP and documentation. #### ✨ Example Previously, `values` would result in `[3, 3, 3]`, which might be surprising and unexpected. This is because `x` was *reassigned* the current array element on each iteration, leading to each function in `fs` returning the last element of the array. ```cadence // Capture the values of the array [1, 2, 3] let fs: [((): Int)] = [] for x in [1, 2, 3] { // Create a list of functions that return the array value fs.append(fun (): Int { return x }) } // Evaluate each function and gather all array values let values: [Int] = [] for f in fs { values.append(f()) } ```
References to Resource-Kinded Values Get Invalidated When the Referenced Values Are Moved ([FLIP 1043]) #### πŸ’‘ Motivation Previously, when a reference is taken to a resource, that reference remains valid even if the resource was moved, for example when created and moved into an account, or moved from one account into another. In other words, references to resources stayed alive forever. This could be a potential safety foot-gun, where one could gain/give/retain unintended access to resources through references. #### ℹ️ Description References are now invalidated if the referenced resource is moved after the reference was taken. The reference is invalidated upon the first move, regardless of the origin and the destination. This feature was proposed in [FLIP 1043]. To learn more, please consult the FLIP and documentation. #### ✨ Example ```cadence // Create a resource. let r <-createR() // And take a reference. let ref = &r as &R // Then move the resource into an account. account.save(<-r, to: /storage/r) // Update the reference. ref.id = 2 ``` Old behavior: ```cadence // This will also update the referenced resource in the account. ref.id = 2 ``` The above operation will now result in a static error. ```cadence // Trying to update/access the reference will produce a static error: // "invalid reference: referenced resource may have been moved or destroyed" ref.id = 2 ``` However, not all scenarios can be detected statically. e.g: ```cadence fun test(ref: &R) { ref.id = 2 } ``` In the above function, it is not possible to determine whether the resource to which the reference was taken has been moved or not. Therefore, such cases are checked at run-time, and a run-time error will occur if the resource has been moved. #### πŸ”„ Adoption Review code that uses references to resources, and check for cases where the referenced resource is moved. Such code may now be reported as invalid, or result in the program being aborted with an error when a reference to a moved resource is de-referenced.
Capability Controller API Replaced Existing Linking-based Capability API ([FLIP 798]) #### πŸ’‘ Motivation Cadence encourages a capability-based security model. Capabilities are themselves a new concept that most Cadence programmers need to understand. The existing API for capabilities was centered around _links_ and _linking_, and the associated concepts of the public and private storage domains led to capabilities being even confusing and awkward to use. A better API is easier to understand and easier to work with. #### ℹ️ Description The existing linking-based capability API has been replaced by a more powerful and easier-to-use API based on the notion of Capability Controllers. The new API makes the creation of new capabilities and the revocation of existing capabilities simpler. This improvement was proposed in [FLIP 798]. To learn more, consult the FLIP and the documentation. #### πŸ”„ Adoption Existing uses of the linking-based capability API must be replaced with the new Capability Controller API. | Removed | Replacement | | ----------------------------------------- | --------------------------------------------------------------- | | `AuthAccount.link`, with private path | `Account.capabilities.storage.issue` | | `AuthAccount.link`, with public path | `Account.capabilities.storage.issue` and `Account.capabilities.publish` | | `AuthAccount.linkAccount` | `AuthAccount.capabilities.account.issue` | | `AuthAccount.unlink`, with private path | - Get capability controller: `Account.capabilities.storage/account.get`
- Revoke controller: `Storage/AccountCapabilityController.delete` | | `AuthAccount.unlink`, with public path | - Get capability controller: `Account.capabilities.storage/account.get`
- Revoke controller: `Storage/AccountCapabilityController.delete`
- Unpublish capability: `Account.capabilities.unpublish` | | `AuthAccount/PublicAccount.getCapability` | `Account.capabilities.get` | | `AuthAccount/PublicAccount.getCapability` with followed borrow | `Account.capabilities.borrow` | | `AuthAccount.getLinkTarget` | N/A | #### ✨ Example Assume there is a `Counter` resource which stores a count, and it implements an interface `HasCount` which is used to allow read access to the count. ```cadence access(all) resource interface HasCount { access(all) count: Int } access(all) resource Counter: HasCount { access(all) var count: Int init(count: Int) { self.count = count } } ``` Granting access, before: ```cadence transaction { prepare(signer: AuthAccount) { signer.save( <-create Counter(count: 42), to: /storage/counter ) signer.link<&{HasCount}>( /public/hasCount, target: /storage/counter ) } } ``` Granting access, after: ```cadence transaction { prepare(signer: auth(Storage, Capabilities)&Account) { signer.save( <-create Counter(count: 42), to: /storage/counter ) let cap = signer.capabilities.storage.issue<&{HasCount}>( /storage/counter ) signer.capabilities.publish(cap, at: /public/hasCount) } } ``` Getting access, before: ```cadence access(all) fun main(): Int { let counterRef = getAccount(0x1) .getCapabilities<&{HasCount}>(/public/hasCount) .borrow()! return counterRef.count } ``` Getting access, after: ```cadence access(all) fun main(): Int { let counterRef = getAccount(0x1) .capabilities .borrow<&{HasCount}>(/public/hasCount)! return counterRef.count } ```
External Mutation Improvement ([FLIP 89] & [FLIP 86]) #### πŸ’‘ Motivation A previous version of Cadence (_Secure Cadence_), attempted to prevent a common safety foot-gun: Developers might use the `let` keyword for a container-typed field, assuming it would be immutable. Though Secure Cadence implements the [Cadence mutability restrictions FLIP], it did not fully solve the problem / prevent the foot-gun and there were still ways to mutate such fields, so a proper solution was devised. To learn more about the problem and motivation to solve it, please read the associated [Vision] document. #### ℹ️ Description The mutability of containers (updating a field of a composite value, key of a map, or index of an array) through references has changed: When a field/element is accessed through a reference, a reference to the accessed inner object is returned, instead of the actual object. These returned references are unauthorized by default, and the author of the object (struct/resource/etc.) can control what operations are permitted on these returned references by using entitlements and entitlement mappings. This improvement was proposed in two FLIPs: - [FLIP 89: Change Member Access Semantics] - [FLIP 86: Introduce Built-in Mutability Entitlements] To learn more, please consult the FLIPs and the documentation. #### πŸ”„ Adoption As mentioned in the previous section, the most notable change in this improvement is that, when a field/element is accessed through a reference, a reference to the accessed inner object is returned, instead of the actual object. So developers would need to change their code to: - Work with references, instead of the actual object, when accessing nested objects through a reference. - Use proper entitlements for fields when they declare their own `struct` and `resource` types.
#### ✨ Example Consider the followinbg resource collection: ```cadence pub resource MasterCollection { pub let kittyCollection: @Collection pub let topshotCollection: @Collection } pub resource Collection { pub(set) var id: String access(all) var ownedNFTs: @{UInt64: NonFungibleToken.NFT} access(all) fun deposit(token:@NonFungibleToken.NFT) {... } } ``` Earlier, it was possible to mutate the inner collections, even if someone only had a reference to the `MasterCollection`. e.g: ```cadence var masterCollectionRef:&MasterCollection =... // Directly updating the field masterCollectionRef.kittyCollection.id = "NewID" // Calling a mutating function masterCollectionRef.kittyCollection.deposit(<-nft) // Updating via the referencelet ownedNFTsRef=&masterCollectionRef.kittyCollection.ownedNFTs as &{UInt64: NonFungibleToken.NFT} destroy ownedNFTsRef.insert(key: 1234, <-nft) ``` Once this change is introduced, the above collection can be re-written as below: ```cadence pub resource MasterCollection { access(KittyCollectorMapping) let kittyCollection: @Collection access(TopshotCollectorMapping) let topshotCollection: @Collection } pub resource Collection { pub(set) var id: String access(Identity) var ownedNFTs: @{UInt64: NonFungibleToken.NFT} access(Insert) fun deposit(token:@NonFungibleToken.NFT) { /* ... */ } } // Entitlements and mappings for `kittyCollection` entitlement KittyCollector entitlement mapping KittyCollectorMapping { KittyCollector -> Insert KittyCollector -> Remove } // Entitlements and mappings for `topshotCollection` entitlement TopshotCollector entitlement mapping TopshotCollectorMapping { TopshotCollector -> Insert TopshotCollector -> Remove } ``` Then for a reference with no entitlements, none of the previously mentioned operations would be allowed: ```cadence var masterCollectionRef:&MasterCollection <- ... // Error: Cannot update the field. Doesn't have sufficient entitlements. masterCollectionRef.kittyCollection.id = "NewID" // Error: Cannot directly update the dictionary. Doesn't have sufficient entitlements. destroy masterCollectionRef.kittyCollection.ownedNFTs.insert(key: 1234,<-nft) destroy masterCollectionRef.ownedNFTs.remove(key: 1234) // Error: Cannot call mutating function. Doesn't have sufficient entitlements. masterCollectionRef.kittyCollection.deposit(<-nft) // Error: `masterCollectionRef.kittyCollection.ownedNFTs` is already a non-auth reference.// Thus cannot update the dictionary. Doesn't have sufficient entitlements. let ownedNFTsRef = &masterCollectionRef.kittyCollection.ownedNFTsas&{UInt64: NonFungibleToken.NFT} destroy ownedNFTsRef.insert(key: 1234, <-nft) ``` To perform these operations on the reference, one would need to have obtained a reference with proper entitlements: ```cadence var masterCollectionRef: auth{KittyCollector} &MasterCollection <- ... // Directly updating the field masterCollectionRef.kittyCollection.id = "NewID" // Updating the dictionary destroy masterCollectionRef.kittyCollection.ownedNFTs.insert(key: 1234, <-nft) destroy masterCollectionRef.kittyCollection.ownedNFTs.remove(key: 1234) // Calling a mutating function masterCollectionRef.kittyCollection.deposit(<-nft) ```
Removal Of Nested Type Requirements ([FLIP 118]) #### πŸ’‘ Motivation [Nested Type Requirements] were a fairly advanced concept of the language. Just like an interface could require a conforming type to provide a certain field or function, it could also have required the conforming type to provide a nested type. This is an uncommon feature in other programming languages and hard to understand. In addition, the value of nested type requirements was never realized. While it was previously used in the FT and NFT contracts, the addition of other language features like interface inheritance and events being emittable from interfaces, there were no more uses case compelling enough to justify a feature of this complexity. #### ℹ️ Description Contract interfaces can no longer declare any concrete types (`struct`, `resource` or `enum`) in their declarations, as this would create a type requirement. `event` declarations are still allowed, but these create an `event` type limited to the scope of that contract interface; this `event` is not inherited by any implementing contracts. Nested interface declarations are still permitted, however. This improvement was proposed in [FLIP 118]. #### πŸ”„ Adoption Any existing code that made use of the type requirements feature should be rewritten not to use this feature.
Event Definition And Emission In Interfaces ([FLIP 111]) #### πŸ’‘ Motivation In order to support the removal of nested type requirements, events have been made define-able and emit-able from contract interfaces, as events were among the only common uses of the type requirements feature. #### ℹ️ Description Contract interfaces may now define event types, and these events can be emitted from function conditions and default implementations in those contract interfaces. This improvement was proposed in [FLIP 111]. #### πŸ”„ Adoption Contract interfaces that previously used type requirements to enforce that concrete contracts that implement the interface should also declare a specific event, should instead define and emit that event in the interface. #### ✨ Example **Before:** A contract interface like the one below (`SomeInterface`) used a type requirement to enforce that contracts which implement the interface also define a certain event (`Foo`): ```cadence contract interface SomeInterface { event Foo() //^^^^^^^^^^^ type requirement fun inheritedFunction() } contract MyContract: SomeInterface { event Foo() //^^^^^^^^^^^ type definition to satisfy type requirement fun inheritedFunction() { // ... emit Foo() } } ``` **After:** This can be rewritten to emit the event directly from the interface, so that any contracts that implement `Intf` will always emit `Foo` when `inheritedFunction` is called: ```cadence contract interface Intf { event Foo() //^^^^^^^^^^^ type definition fun inheritedFunction() { pre { emit Foo() } } } ```
Force Destruction of Resources ([FLIP 131]) #### πŸ’‘ Motivation It was previously possible to panic in the body of a resource or attachment’s `destroy` method, effectively preventing the destruction or removal of that resource from an account. This could be used as an attack vector by handing people undesirable resources or hydrating resources to make them extremely large or otherwise contain undesirable content. #### ℹ️ Description Contracts may no longer define `destroy` functions on their resources, and are no longer required to explicitly handle the destruction of resource fields. These will instead be implicitly destroyed whenever a resource is destroyed. Additionally, developers may define a `ResourceDestroyed` event in the body of a resource definition using default arguments, which will be lazily evaluated and then emitted whenever a resource of that type is destroyed. This improvement was proposed in [FLIP 131]. #### πŸ”„ Adoption Contracts that previously used destroy methods will need to remove them, and potentially define a ResourceDestroyed event to track destruction if necessary. #### ✨ Example A pair of resources previously written as: ```cadence event E(id: Int) resource SubResource { let id: Int init(id: Int) { self.id = id } destroy() { emit E(id: self.id) } } resource R { let subR: @SubResource init(id: Int) { self.subR <- create SubResource(id: id) } destroy() { destroy self.subR } } ``` can now be equivalently written as: ```cadence resource SubResource { event ResourceDestroyed(id: Int = self.id) let id: Int init(id: Int) { self.id = id } } resource R { let subR: @SubResource init(id: Int) { self.subR <- create SubResource(id: id) } } ```
New `domainSeparationTag` parameter added to `Crypto.KeyList.verify` #### πŸ’‘ Motivation `KeyList`’s `verify` function used to hardcode the domain separation tag (`"FLOW-V0.0-user"`) used to verify each signature from the list. This forced users to use the same domain tag and didn’t allow them to scope their signatures to specific use-cases and applications. Moreover, the `verify` function didn’t mirror the `PublicKey` signature verification behavior which accepts a domain tag parameter. #### ℹ️ Description `KeyList`’s `verify` function requires an extra parameter to specify the domain separation tag used to verify the input signatures. The tag is is a single `string` parameter and is used with all signatures. This mirrors the behavior of the simple public key (see [Signature verification] for more information). #### πŸ”„ Adoption Contracts that use `KeyList` need to update the calls to `verify` by adding the new domain separation tag parameter. Using the tag as `"FLOW-V0.0-user"` would keep the exact same behavior as before the breaking change. Applications may also define a new domain tag for their specific use-case and use it when generating valid signatures, for added security against signature replays. See [Signature verification] and specifically [Hashing with a domain tag] for details on how to generate valid signatures with a tag. #### ✨ Example A previous call to `KeyList`’s `verify` is written as: ```cadence let isValid = keyList.verify( signatureSet: signatureSet, signedData: signedData ) ``` can now be equivalently written as: ```cadence let isValid = keyList.verify( signatureSet: signatureSet, signedData: signedData, domainSeparationTag: "FLOW-V0.0-user" ) ``` Instead of the existing hardcoded domain separation tag, a new domain tag can be defined, but it has to be also used when generating valid signatures, e.g., `"my_app_custom_domain_tag"`.
## FT / NFT standard changes In addition to the upcoming language changes, the Cadence 1.0 upgrade also includes breaking changes to core contracts, such as the FungibleToken and NonFungibleToken standards. All Fungible and Non-Fungible Token contracts will need to be updated to the new standard. These interfaces are being upgraded to allow for multiple tokens per contract, fix some issues with the original standards, and introduce other various improvements suggested by the community. - Original Proposal: [Flow forum] - Fungible Token Changes PR (WIP): [V2 FungibleToken Standard by joshuahannan β€” Pull Request #77 β€” onflow/flow-ft] - NFT Changes PR: [GitHub] It will involve upgrading your token contracts with changes to events, function signatures, resource interface conformances, and other small changes. There are some existing guides for upgrading your token contracts to the new standard: - [Upgrading Fungible Token Contracts] - [Upgrading Non-Fungible Token Contracts] ## More resources If you have any questions or need help with the upgrade, feel free to reach out to the Flow team on the [Flow Discord]. Help is also available during the [Cadence 1.0 Office Hours] each week at 10:00AM PST on the Flow Developer Discord. {/* Relative links. Will not render on the page */} [FLIP 1043]: https://github.com/onflow/flips/blob/main/cadence/20220708-resource-reference-invalidation [FLIP 1056]: https://github.com/onflow/flips/blob/main/cadence/20220715-cadence-purity-analysis [FLIP 111]: https://github.com/onflow/flips/blob/main/cadence/20230417-events-emitted-from-interfaces [FLIP 118]: https://github.com/onflow/flips/blob/main/cadence/20230711-remove-type-requirements [FLIP 13]: https://github.com/onflow/flips/blob/main/cadence/20221011-for-loop-semantics [FLIP 131]: https://github.com/onflow/flips/pull/131 [FLIP 242]: https://github.com/onflow/flips/blob/main/cadence/20240123-capcon-get-capability-api-improvement [FLIP 262]: https://github.com/onflow/flips/blob/main/cadence/20240415-remove-non-public-entitled-interface-members [FLIP 40]: https://github.com/onflow/flips/blob/main/cadence/20221024-interface-inheritance [FLIP 43]: https://github.com/onflow/flips/blob/main/cadence/20221018-change-fun-type-syntax [FLIP 54]: https://github.com/onflow/flips/blob/main/cadence/20221214-auth-remodel [FLIP 798]: https://github.com/onflow/flips/blob/main/cadence/20220203-capability-controllers [FLIP 84]: https://github.com/onflow/flips/blob/main/cadence/20230505-remove-priv-and-pub [FLIP 85]: https://github.com/onflow/flips/blob/main/cadence/20230505-remove-restricted-types [FLIP 86: Introduce Built-in Mutability Entitlements]: https://github.com/onflow/flips/blob/main/cadence/20230519-built-in-mutability-entitlements [FLIP 86]: https://github.com/onflow/flips/blob/main/cadence/20230519-built-in-mutability-entitlements [FLIP 89: Change Member Access Semantics]: https://github.com/onflow/flips/blob/main/cadence/20230517-member-access-semnatics [FLIP 89]: https://github.com/onflow/flips/blob/main/cadence/20230517-member-access-semnatics [FLIP 92]: https://github.com/onflow/flips/blob/main/cadence/20230525-account-type [FLIP 94]: https://github.com/onflow/flips/blob/main/cadence/20230623-entitlement-improvements [FLIP 941]: https://github.com/onflow/flips/blob/main/cadence/20220516-reference-creation-semantics [Account keys]: https://developers.flow.com/cadence/language/accounts#account-keys [Cadence 1.0 Office Hours]: https://calendar.google.com/calendar/ical/c_47978f5cd9da636cadc6b8473102b5092c1a865dd010558393ecb7f9fd0c9ad0%40group.calendar.google.com/public/basic.ics [Cadence mutability restrictions FLIP]: https://github.com/onflow/flips/blob/main/cadence/20211129-cadence-mutability-restrictions [Entitlements]: https://cadence-lang.org/docs/1.0/language/access-control#entitlements [Flow Discord]: https://discord.gg/flowblockchain. [Flow forum]: http://forum.flow.com/t/streamlined-token-standards-proposal/3075 [GitHub]: https://github.com/onflow/flow-nft/pull/126 [Hashing with a domain tag]: https://cadence-lang.org/docs/1.0/language/crypto#hashing-with-a-domain-tag [Nested Type Requirements]: https://docs.onflow.org/cadence/language/interfaces/#nested-type-requirements [Signature verification]: https://cadence-lang.org/docs/1.0/language/crypto#signature-verification [Upgrading Fungible Token Contracts]: ./ft-guide [Upgrading Non-Fungible Token Contracts]: ./nft-guide [Vision]: https://github.com/onflow/flips/blob/main/cadence/vision/mutability-restrictions [V2 FungibleToken Standard by joshuahannan β€” Pull Request #77 β€” onflow/flow-ft]: https://github.com/onflow/flow-ft/pull/77 --- # Cadence 1.0 Migration Guide (/docs/cadence-migration-guide) On September 4th, 2024, the Flow Mainnet upgraded to Cadence 1.0. This migration guide offers developers guidance and actionable steps for updating projects to be compatible with Cadence 1.0. The Cadence 1.0 release, introduced in the [Crescendo] network upgrade, is a breaking change. Developers need to make sure all Cadence code used by their apps (transactions and scripts) is updated to Cadence 1.0, to ensure it continues to work after the network upgrade. Many of the improvements of Cadence 1.0 fundamentally change how Cadence works and is used. This means it is necessary to break existing code to release this version, which will guarantee stability going forward. ## Benefits of Cadence 1.0 Cadence 1.0 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 new features and improvements] that provide new possibilities, 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. ## Upgrading NFT and FT contracts In addition to changes to the Cadence programming language, the Cadence token standards were also streamlined and improved. Existing Cadence scripts and transactions interacting with NFTs and FTs must be updated. If you do _not_ update your code, your applications will become non-functional. - [Guide for NFT Standard v2] - [Guide for FT Standard v2] - [Cadence 1.0 Improvements & New Features] {/* Relative links. Will not render on the page */} [Crescendo]: https://flow.com/upgrade/crescendo [comprehensive suite of new features and improvements]: ./improvements [Guide for NFT Standard v2]: ./nft-guide [Guide for FT Standard v2]: ./ft-guide [Cadence 1.0 Improvements & New Features]: ./improvements --- # Non-Fungible Token Cadence 1.0 Migration Guide (/docs/cadence-migration-guide/nft-guide) # Non-Fungible Tokens in Cadence 1.0 :::important On September 4th, 2024, the Flow Mainnet upgraded to Cadence 1.0. In addition to many changes to the Cadence programming language, the Cadence token standards were also streamlined and improved. All applications' scripts and transactions need to be updated. If you do not update your code, your applications will not function properly. ::: 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] 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 information Please read the [NFT-V2 FLIP] that describes the changes to the `NonFungibleToken` standard first. The updated code for the V2 Non-Fungible Token standard is located in the [`master` branch of the flow-nft repo]. Please look at the [PR that made the changes] to understand how the standard and examples have changed. Note the changes to the `NonFungibleToken`, `MetadataViews`, `ViewResolver`, and `NFTForwarding` contracts. Additionally, here are the import addresses for all of the important contracts related to non-fungible tokens. The second column is the import address if you are testing with a basic version of the emulator. The third column contains the import addresses if you are using the Cadence testing framework: | Contract | Emulator import address | Testing framework | | ------------------ | ----------------------- | -------------------- | | `NonFungibleToken` | `0xf8d6e0586b0a20c7` | `0x0000000000000001` | | `FungibleToken` | `0xee82856bf20e2aa6` | `0x0000000000000002` | | `ViewResolver` | `0xf8d6e0586b0a20c7` | `0x0000000000000001` | | `Burner` | `0xf8d6e0586b0a20c7` | `0x0000000000000001` | | `MetadataViews` | `0xf8d6e0586b0a20c7` | `0x0000000000000001` | 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** β€” The NFT Catalog has been deprecated for Cadence 1.0. Now that the token standards require implementing metadata views, NFT Catalog is not needed in its current form. The Flow team now maintains [TokenList], which is similar to NFT Catalog but is decentralized. Projects can register there without needing to be approved. - **NFT Storefront** β€” See the [`master` branch in the NFT Storefront Repo] for the updated versions of the `NFTStorefront` and `NFTStorefrontV2` contracts. - **USDC** β€” USDC was migrated to standard bridged USDC on Flow. See the [repo] for the latest version of the USDC contract. - **Account Linking and Hybrid Custody** β€” See the [`main` branch in the hybrid custody repo] for updated hybrid custody contracts. [This Discord announcement] also contains versions of a lot of important contracts. Use the [Flow Contract Browser] to find the 1.0 code of other 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 from the `master` branch of the `flow-nft` repo. Additionally, the Flow community is working on the [`BasicNFT` contract] in the `universal-collection` branch of the flow-nft GitHub repo. This is a simplified version of standard NFT contracts, but has not been completed yet. ## `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` contract]. `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`], 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 of 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 programming language as well as the token standard. The improvements are 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. ### Token Standard Changes **`NonFungibleToken.NFT`** `NonFungibleToken.NFT` used to be a nested type specification, but now it is an interface! In your code, any instance that refers to `@NonFungibleToken.NFT` or `&NonFungibleToken.NFT` must be updated to `@{NonFungibleToken.NFT}` or `&{NonFungibleToken.NFT}` respectively. **`NonFungibleToken.Collection`** Similar to `NFT`, `NonFungibleToken.Collection` is now an interface. 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. ## 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! {/* Relative links. Will not render on the page */} [`ExampleNFT` contract]: https://github.com/onflow/flow-nft/blob/master/contracts/ExampleNFT.cdc [`master` branch of the flow-nft repo]: https://github.com/onflow/flow-nft [PR that made the changes]: https://github.com/onflow/flow-nft/pull/126 [TokenList]: https://token-list.fixes.world/?utm_source=Flowverse&utm_medium=Website&utm_campaign=Dapp [`master` branch in the NFT Storefront Repo]: https://github.com/onflow/nft-storefront/tree/master/contracts [repo]: https://github.com/onflow/bridged-usdc [`main` branch in the hybrid custody repo]: https://github.com/onflow/hybrid-custody [This Discord announcement]: https://discord.com/channels/613813861610684416/811693600403357706/1225909248429527140 [Flow Contract Browser]: https://contractbrowser.com/ [`BasicNFT` contract]: https://github.com/onflow/flow-nft/blob/universal-collection/contracts/BasicNFT.cdc [`UniversalCollection`]: https://github.com/onflow/flow-nft/blob/universal-collection/contracts/UniversalCollection.cdc [NFT-V2 FLIP]: https://github.com/onflow/flips/pull/56 --- # Contract Upgrades with Incompatible Changes (/docs/contract-upgrades) The following explains what to do when facing an incompatible upgrade for a contract. ## How to deploy Please don't perform incompatible upgrades between contract versions in the same account. There is too much that can go wrong. You can make [compatible upgrades] and then run a post-upgrade function on the new contract code if needed. If you must replace your contract rather than update it, the simplest solution is to add or increase a suffix on any named paths in the contract code (e.g., `/public/MyProjectVault` becomes `/public/MyProjectVault002`) in addition to making the incompatible changes, then create a new account and deploy the updated contract there. :::note Flow identifies types relative to addresses, so you will also need to provide _upgrade transactions_ to exchange the old contract's resources for the new contract's ones. Make sure to inform users as soon as possible when and how they will need to perform this task. ::: If you absolutely must keep the old address when making an incompatible upgrade, then you do so at your own risk. Make sure you perform the following actions in this exact order: 1. Delete any resources used in the contract account (e.g., an Admin resource). 2. Delete the contract from the account. 3. Deploy the new contract to the account. :::warning If any user accounts contain `structs` or `resources` from the _old_ version of the contract that have been replaced with incompatible versions in the new one, **they will not load and will cause transactions that attempt to access them to crash**. For this reason, once any users have received `structs` or `resources` from the contract, this method of making an incompatible upgrade should not be attempted! ::: {/* Relative links. Will not render on the page */} [compatible upgrades]: ./language/contract-updatability --- # Cadence Design Patterns (/docs/design-patterns) This is a selection of software design patterns developed by core Flow developers while writing Cadence code for deployment to Flow Mainnet. Many of these design patters apply to most other programming languages, but some are specific to Cadence. [Design patterns](https://en.wikipedia.org/wiki/Software_design_pattern) are building blocks for software development. They may provide a solution to a problem that you encounter when writing smart contracts in Cadence. If they do not clearly fit, these patterns may not be the right solution for a given situation or problem. They are not meant to be rules to be followed strictly, especially where a better solution presents itself. # General These are general patterns to follow when writing smart contracts. ## Use named value fields for constants instead of hard-coding ### Problem Your contracts, resources, and scripts all have to refer to the same value. A number, a string, a storage path, etc. Entering these values manually in transactions and scripts is a potential source of error. See [Wikipedia's page on magic numbers](https://en.wikipedia.org/wiki/Magic_number_(programming)) ### Solution Add a public (`access(all)`), constant (`let`) field, e.g. a `Path` , to the contract responsible for the value, and set it in the contract's initializer. Refer to that value via this public field rather than specifying it manually. Example Snippet: ```cadence // BAD Practice: Do not hard code storage paths access(all) contract NamedFields { access(all) resource Test {} init() { // BAD: Hard-coded storage path self.account.storage.save(<-create Test(), to: /storage/testStorage) } } // GOOD practice: Instead, use a field // access(all) contract NamedFields { access(all) resource Test {} // GOOD: field storage path access(all) let testStoragePath: StoragePath init() { // assign and access the field here and in transactions self.testStoragePath = /storage/testStorage self.account.storage.save(<-create Test(), to: self.TestStoragePath) } } ``` [Example Code](https://github.com/onflow/flow-core-contracts/blob/71ea0dfe843da873d52c6a983e7c8f44a4677b26/contracts/LockedTokens.cdc#L779) ## Script-Accessible public field/function Data availability is important in a blockchain environment. It is useful to publicize information about your smart contract and the assets it controls so other smart contracts and apps can easily query it. ### Problem Your contract, resource, or struct has a field or resource that will need to be read and used on or off-chain, often in bulk. ### Solution Make sure that the field can be accessed from a script. This saves the time and fees required to read a property using a transaction. Making the field or function `access(all)` and exposing it via a `/public/` capability will allow this. Be careful not to expose any data or functionality that should be kept private when doing so. Example: ```cadence // BAD: Field is private, so it cannot be read by the public access(self) let totalSupply: UFix64 // GOOD: Field is public, so it can be read and used by anyone access(all) let totalSupply: UFix64 ``` ## Script-Accessible report ### Problem Your contract has a resource that you wish to access fields of. Resources are often stored in private places and are hard to access. Additionally, scripts cannot return resources to the external context, so a struct must be used to hold the data. ### Solution Return a reference to a resource if the data from a single resource is all that is needed. Otherwise, declare a struct to hold the data that you wish to return from the script. Write a function that fills out the fields of this struct with the data from the resource that you wish to access. Then call this on the resource that you wish to access the fields of in a script, and return the struct from the script. See [Script-Accessible public field/function](#script-accessible-public-fieldfunction), above, for how best to expose this capability. ### Example ```cadence access(all) contract AContract { access(all) let BResourceStoragePath: StoragePath access(all) let BResourcePublicPath: PublicPath init() { self.BResourceStoragePath = /storage/BResource self.BResourcePublicPath = /public/BResource } // Resource definition access(all) resource BResource { access(all) var c: UInt64 access(all) var d: String // Generate a struct with the same fields // to return when a script wants to see the fields of the resource // without having to return the actual resource access(all) fun generateReport(): BReportStruct { return BReportStruct(c: self.c, d: self.d) } init(c: UInt64, d: String) { self.c = c self.d = d } } // Define a struct with the same fields as the resource access(all) struct BReportStruct { access(all) var c: UInt64 access(all) var d: String init(c: UInt64, d: String) { self.c = c self.d = d } } } ... // Transaction import AContract from 0xAContract transaction { prepare(acct: auth(IssueStorageCapabilityController, PublishCapability) &Account) { //... let cap = acct.capabilities.storage.issue<&AContract.BResource>(AContract.BResourceStoragePath) acct.capabilities.publish(cap, at: AContract.BResourcePublicPath) } } // Script import AContract from 0xAContract // Return the struct with a script access(all) fun main(account: Address): AContract.BReportStruct { // borrow the resource let b = getAccount(account).capabilities .borrow<&AContract.BResource>(AContract.BResourcePublicPath) // return the struct return b.generateReport() } ``` ## Init singleton ### Problem An admin resource must be created and delivered to a specified account. There should not be a function to do this, as that would allow anyone to create an admin resource. ### Solution Create any one-off resources in the contract's initializer and deliver them to an address or `&Account` specified as an argument. See how this is done in the LockedTokens contract initializer: [LockedTokens.cdc](https://github.com/onflow/flow-core-contracts/blob/71ea0dfe843da873d52c6a983e7c8f44a4677b26/contracts/LockedTokens.cdc#L765-L780) and in the transaction that is used to deploy it: [admin_deploy_contract.cdc](https://github.com/onflow/flow-core-contracts/blob/master/transactions/lockedTokens/admin/admin_deploy_contract.cdc) ## Use descriptive names for fields, paths, functions and variables ### Problem Smart contracts often are vitally important pieces of a project and often have many other smart contracts and applications that rely on them. Therefore, they need to be clearly written and easy to understand. ### Solution All fields, functions, types, variables, etc., need to have names that clearly describe what they are used for. `account` / `accounts` is better than `array` / `element`. `providerAccount` / `tokenRecipientAccount` is better than `acct1` / `acct2`. `/storage/bestPracticesDocsCollectionPath` is better than `/storage/collection` ### Example ```cadence // BAD: Unclear naming // access(all) contract Tax { // Do not use abbreviations unless absolutely necessary access(all) var pcnt: UFix64 // Not clear what the function is calculating or what the parameter should be access(all) fun calculate(num: UFix64): UFix64 { // What total is this referring to? let total = num + (num * self.pcnt) return total } } // GOOD: Clear naming // access(all) contract TaxUtilities { // Clearly states what the field is for access(all) var taxPercentage: UFix64 // Clearly states that this function calculates the // total cost after tax access(all) fun calculateTotalCostPlusTax(preTaxCost: UFix64): UFix64 { let postTaxCost = preTaxCost + (preTaxCost * self.taxPercentage) return postTaxCost } } ``` ## Plural names for arrays and maps are preferable For example, use `accounts` rather than `account` for an array of accounts. This signals that the field or variable is not scalar. It also makes it easier to use the singular form for a variable name during iteration. ## Use transaction post-conditions when applicable ### Problem Transactions can contain any amount of valid Cadence code and access many contracts and accounts. The power of resources and capabilities means that there may be some behaviors of programs that are not expected. ### Solution It is usually safe to include post-conditions in transactions to verify the intended outcome. ### Example This could be used when purchasing an NFT to verify that the NFT was deposited in your account's collection. ```cadence // Pseudo-code transaction { access(all) let buyerCollectionRef: &NonFungibleToken.Collection prepare(acct: auth(BorrowValue) &Account) { // Get tokens to buy and a collection to deposit the bought NFT to let temporaryVault <- vaultRef.withdraw(amount: 10.0) let self.buyerCollectionRef = acct.storage.borrow(from: /storage/Collection) // purchase, supplying the buyers collection reference saleRef.purchase(tokenID: 1, recipient: self.buyerCollectionRef, buyTokens: <-temporaryVault) } post { // verify that the buyer now owns the NFT self.buyerCollectionRef.idExists(1) == true: "Bought NFT ID was not deposited into the buyers collection" } } ``` ## Avoid unnecessary load and save storage operations, prefer in-place mutations ### Problem When modifying data in account storage, `load()` and `save()` are costly operations: All data is unnecessarily moved out of the account, then moved back into the account. This can quickly cause your transaction to reach its limits. This also applies to nested, stored in fields, arrays, and dictionaries: Moving objects out of containers and moving them back into the container, just to modify the object, is just as costly. For example, a collection contains a dictionary of NFTs. There is no need to move the whole dictionary out of the field, update the dictionary on the stack (e.g., adding or removing an NFT), and then move the whole dictionary back to the field: the dictionary can be updated in-place, which is easier and more efficient. The same goes for a more complex data structure like a dictionary of nested resources: Each resource can be updated in-place by taking a reference to the nested object instead of loading and saving. ### Solution For making modifications to values in storage or accessing stored objects, `borrow()` should always be used to access them instead of `load` or `save` unless absolutely necessary. `borrow()` returns a reference to the object at the storage path instead of having to load the entire object. This reference can be assigned to or can be used to access fields or call methods on stored objects. Fields and value in containers, such as in arrays and dictionaries, can be borrowed using a reference expression (`&v as &T`). ### Example ```cadence // BAD: Loads and stores a resource to use it // transaction { prepare(acct: auth(LoadValue, SaveValue) &Account) { // Removes the vault from storage, a costly operation let vault <- acct.storage.load<@ExampleToken.Vault>(from: /storage/exampleToken) // Withdraws tokens let burnVault <- vault.withdraw(amount: 10) destroy burnVault // Saves the used vault back to storage, another costly operation acct.storage.save(to: /storage/exampleToken) } } // GOOD: Uses borrow instead to avoid costly operations // transaction { prepare(acct: auth(BorrowValue) &Account) { // Borrows a reference to the stored vault, much less costly operation let vault <- acct.storage.borrow<&ExampleToken.Vault>(from: /storage/exampleToken) let burnVault <- vault.withdraw(amount: 10) destroy burnVault // No `save` required because we only used a reference } } ``` # Capabilities ## Capability bootstrapping ### Problem An account must be given a [capability](/docs/language/capabilities) to an object stored in another account. To create (issue) the capability, the transaction must be signed by a key which has access to the target account. To transfer / deliver the capability to the other account, the transaction also needs write access to that one. It is not as easy to produce a single transaction which is authorized by two accounts as it is to produce a typical transaction which is authorized by one account. This prevents a single transaction from fetching the capability from one account and delivering it to the other. ### Solution The solution to the bootstrapping problem in Cadence is provided by the [Inbox API](/docs/language/accounts/inbox). Account A (which we will call the provider) creates the capability they wish to send to account B (which we will call the recipient), and stores this capability on their account in a place where the recipient can access it using the `Inbox.publish` function on their account. They choose a name for the capability that the recipient can later use to identify it, and specify the recipient's address when calling `publish`. This call to `publish` will emit an `InboxValuePublished` event that the recipient can listen for off-chain to know that the Capability is ready for them to claim. The recipient then later can use the `Inbox.claim` function to securely claim the capability from the provider's account. They must provide the name and type with which the capability was published, as well as the address of the provider's account (all of this information is available in the `InboxValuePublished` event emitted on `publish`). This will remove the capability from the provider's account and emit an `InboxValueClaimed` event that the provider can listen for off-chain. One important caveat to this is that the published capability is stored on the provider's account until the recipient claims it, so the provider can also use the `Inbox.unpublish` function to remove the capability from their account if they no longer wish to pay for storage for it. This also requires the name and type which the capability was published, and emits an `InboxValueUnpublished` event that the recipient can listen for off-chain. It is also important to note that the recipient becomes the owner of the capability object once they have claimed it, and can thus store it or copy it anywhere they have access to. This means providers should only publish capabilities to recipients they trust to use them properly, or limit the type with which the capability is authorized in order to only give recipients access to the functionality that the provider is willing to allow them to copy. ```cadence import "BasicNFT" transaction(receiver: Address, name: String) { prepare(signer: auth(IssueStorageCapabilityController, PublishInboxCapability) &Account) { // Issue a capability controller for the storage path let capability = signer.capabilities.storage.issue<&BasicNFT.Minter>(BasicNFT.minterPath) // Set the name as tag so it is easy for us to remember its purpose let controller = signer.capabilities.storage.getController(byCapabilityID: capability.id) ?? panic("Cannot get the storage capability controller with ID " .concat(capabilityID.toString()) .concat(" from the signer's account! Make sure the ID belongs to a capability that the owner controls and that it is a storage capability.") controller.setTag(name) // Publish the capability, so it can be later claimed by the receiver signer.inbox.publish(capability, name: name, recipient: receiver) } } ``` ```cadence import "BasicNFT" transaction(provider: Address, name: String) { prepare(signer: auth(ClaimInboxCapability, SaveValue) &Account) { // Claim the capability from our inbox let capability = signer.inbox.claim<&BasicNFT.Minter>(name, provider: provider) ?? panic("Cannot claim the storage capability controller with name " .concat(name).concat(" from the provider account (").concat(provider.toString()) .concat("! Make sure the provider address is correct and that they have published " .concat(" a capability with the desired name.") // Save the capability to our storage so we can later retrieve and use it signer.storage.save(capability, to: BasicNFT.minterPath) } } ``` ## Check for existing capabilities before issuing or publishing new ones ### Problem When issuing or publishing a capability, a capability might be already be issued or published at the specified path for the desired capability type. ### Solution Check if a capability is already issued and/or published at the given paths. ### Example ```cadence transaction { prepare(signer: auth(Capabilities) &Account) { var capability: Capability<&ExampleToken.Vault>? = nil // get the capability to the vault at the given storage path if it exists let vaultCaps = account.capabilities.storage.getControllers(forPath: /storage/exampleTokenVault) for cap in vaultCaps { if let cap = cap as? Capability<&ExampleToken.Vault> { capability = cap break } } if capability == nil { // issue a new capability to the vault since it wasn't found capability = account.capabilities.storage.issue<&ExampleToken.Vault>(/storage/exampleTokenVault) } let publicPath = /public/exampleTokenReceiver if signer.capabilities.exits(publicPath) { signer.capabilities.unpublish(publicPath) } signer.capabilities.publish(capability, at: publicPath) } } ``` ## Capability Revocation ### Problem A capability provided by one account to a second account must able to be revoked by the first account without the co-operation of the second. ### Solution If the capability is a storage capability: ```cadence transaction(capabilityID: UInt64) { prepare(signer: auth(StorageCapabilities) &Account) { let controller = signer.capabilities.storage .getController(byCapabilityID: capabilityID) ?? panic("Cannot get the storage capability controller with ID " .concat(capabilityID.toString()) .concat(" from the signer's account! Make sure the ID belongs to a capability that the owner controls and that it is a storage capability.") controller.delete() } } ``` If the capability is an account capability: ```cadence transaction(capabilityID: UInt64) { prepare(signer: auth(AccountCapabilities) &Account) { let controller = signer.capabilities.account .getController(byCapabilityID: capabilityID) ?? panic("Cannot get the account capability controller with ID " .concat(capabilityID.toString()) .concat(" from the signer's account! Make sure the ID belongs to a capability that the owner controls and that it is an account capability.") controller.delete() } } ``` --- # Introduction to Cadence (/docs/) In a blockchain environment like Flow, programs that are stored and executed onchain are referred to as smart contracts. A smart contract programmatically verifies and executes the performance of a contract without the need for a trusted third party. Many people think of it as code-as-law. They control and execute important functionality such as the creation and management of currency, buying and selling of digital property, and the execution of contractual agreements without having to rely on a central authority (like a bank). All of this happens on the same shared computer that anyone can use and no one can shut down or exercise admin control. ## A new programming language Cadence is a resource-oriented programming language that introduces new features to smart contract programming, which help developers ensure that their code is safe, secure, clear, and approachable. Some of these features are: - Type safety and a strong static type system. - Resource-oriented programming β€” a new paradigm that pairs linear types with object capabilities to create a secure and declarative model for digital ownership by ensuring that resources (which are used to represent scarce digital assets) can only exist in one location at a time, cannot be copied, and cannot be accidentally lost or deleted. - Built-in pre-conditions and post-conditions for functions and transactions. - The utilization of capability-based security, which enforces that access to objects is restricted to only the owner of the object and those who have a valid reference to it. This is Cadence's main form of access control. Cadence’s syntax is inspired by popular modern general-purpose programming languages like [Swift], [Kotlin], and [Rust]. Its use of resource types maps well to that of [Move], the programming language used by Aptos and Sui, though Flow provides greater fine-grained permission control with Capabilities. ## Cadence's programming language pillars Cadence, a new high-level programming language, observes the following requirements: - **Safety and security:** Safety is the underlying reliability of any smart contract (i.e., it’s bug-free and performs its function). Security is the prevention of attacks on the network or smart contracts (i.e., unauthorized actions by malicious actors). Safety and security are critical in smart contracts because of the immutable nature of blockchains and because they often deal with high-value assets. While auditing and reviewing code will be a crucial part of smart contract development, Cadence maximizes efficiency while maintaining the highest levels of safety and security at its foundation. It accomplishes this via a strong static type system, design by contract, and ownership primitives inspired by linear types (which are useful when dealing with assets). - **Clarity:** Code needs to be easy to read, and its meaning should be as unambiguous as possible. It should also be suited for verification so that tooling can help with ensuring safety and security guarantees. These guarantees can be achieved by making the code declarative and allowing the developer to express their intentions directly. We make those intentions explicit by design, which, along with readability, make auditing and reviewing more efficient, at a small cost to verbosity. - **Approachability:** Writing code and creating programs should be as approachable as possible. Incorporating features from languages like Swift and Rust, developers should find Cadence’s syntax and semantics familiar. Practical tooling, documentation, and examples enable developers to start creating programs quickly and effectively. - **Developer experience:** The developer should be supported throughout the entire development lifecycle, from initial application logic to onchain bug fixes. - **Intuiting ownership with resources:** Resources are a composite data type, similar to a struct, that expresses direct ownership of assets. Cadence’s strong static type system ensures that resources can only exist in one location at a time and cannot be copied or lost because of a coding mistake. Most smart contract languages currently use a ledger-style approach to record ownership, where an asset like a fungible token is stored in the smart contract as an entry in a central ledger. Cadence’s resources directly tie an asset’s ownership to the account that owns it by saving the resource in the account’s storage. As a result, ownership isn’t centralized in a smart contract’s storage. Each account owns its assets, and the assets can be transferred freely between accounts without the need for arbitration by a central smart contract. ## Addressing challenges with existing languages Other languages pioneered smart contract development, but they lack in areas that affect the long-term viability of next-generation applications. ### Safety Safety is the reliability of a smart contract to perform its function as intended. It is heavily influenced by the _unchangeable-once-deployed_ nature of smart contracts: Developers must take certain precautions in order to avoid introducing any potentially catastrophic vulnerabilities prior to publishing a smart contract on the blockchain. It is standard across many blockchains that modifying or updating a smart contract, even to fix a vulnerability, is not allowed. Thus, any bugs that are present in the smart contract will exist forever. For example, in 2016, an overlooked vulnerability in an Ethereum Decentralized Autonomous Organization (DAO) smart contract saw millions of dollars siphoned from a smart contract, eventually leading to a fork in Ethereum and two separate active blockchains (Ethereum and Ethereum Classic). Bug fixes are only possible if a smart contract is designed to support changes, a feature that introduces complexity and security issues. Lengthy auditing and review processes can ensure a bug-free smart contract. Still, they add substantial time to the already time-consuming task of getting the smart contract’s core logic working correctly. Overlooked mistakes cause the most damaging scenarios. It is easy to lose or duplicate monetary value or assets in existing languages because they don’t check relevant invariants or make it harder to express them. For example, a plain number represents a transferred amount that can be accidentally (or maliciously) multiplied or ignored. Some languages also express behaviors that developers tend to forget about. For example, a fixed-range type might express monetary value, without considerations for a potential overflow or underflow. In Solidity, Ethereum's smart contract language, an overflow originally caused the value to wrap around, as shown [here]. Solidity also allows contracts to declare variables without initializing them, and doesn't have a `null` or `undefined` value. Even more confusing, the `mapping` type automatically includes values at all possible entries - `0`, `false`, or whatever the default value is for that type. Cadence is type-safe and has a strong static type system, which prevents important classes of erroneous or undesirable program behavior at compile-time (i.e., before the program is run onchain). Types are checked statically and are not implicitly converted. Cadence also improves the safety of programs by preventing arithmetic underflow and overflow, introduces optionals to make nil-cases explicit, and always requires variables to be initialized. This helps ensure the behavior of these smart contracts is apparent and not dependent on context. ### Security Security, in combination with safety, ensures the successful execution of a smart contract over time by preventing unsanctioned access and guaranteeing that only authorized actions can be performed in the protocol. In some languages, functions are public by default, creating vulnerabilities that allow malicious users to find attack vectors. Cadence utilizes capability-based security, which allows the type system to enforce access control based on rules that users and developers have control over. Security is a consideration when interacting with other smart contracts. Any external call potentially allows malicious code to be executed. For example, in Solidity, when the called function signature does not match any of the available ones, it triggers Solidity’s fallback functions. These functions can be used in malicious ways. Language features such as multiple inheritances and overloading or dispatch can also make it difficult to determine which code is invoked. In Cadence, the safety and security of programs are enhanced by **Design By Contract** and **Ownership Primitives.** Design by contract allows developers to state pre-conditions and post-conditions for functions and interfaces in a declarative manner so that callers can be certain about the behavior of called code. Ownership primitives are inspired by linear types and increase safety when working with assets. They ensure that valuable assets are, for example, not accidentally or maliciously lost or duplicated. ### Clarity and approachability Implicitness, context-dependability, and expressiveness are language-based challenges that developers often encounter. They affect the clarity (i.e., the readability of code and the ability to determine its intended function) and the approachability (i.e., the ability to interpret or write code) of the language and the programs built using it. For example, in Solidity, storage must be implemented in a low-level key-value manner, which obfuscates the developer’s intentions. Syntax confusion is another example, with "=+" being legal syntax leading to an assignment instead of a probably-intended increment. Solidity also has features with uncommon behaviors that can lead to unintended results. [Multiple inheritance may lead to unexpected behaviours in the program], and testing and auditing the code is unlikely to identify this issue. The Ethereum blockchain’s code immutability showcases the need for considerations around extensibility and mechanisms that allow ad-hoc fixes. Developers using custom-made approaches, such as the 'data separation' approach to upgradability, may run into problems with the complexity of data structures, while developers using '`delegate_call`-based proxies' may run into problems with the consistency of memory layouts. Either way, these challenges compromise approachability and overall extensibility. Cadence has [contract upgradability built in by default], and contracts can be made immutable by removing all keys from an account. Cadence improves the clarity and extensibility of programs by utilizing interfaces to allow extensibility, code reuse, and interoperability between contracts. Cadence modules also have configurable and transparent upgradeability built in to enable projects to test and iterate before making their code immutable. Cadence allows the use of argument labels to describe the meaning of function arguments. It also provides a rich standard library with useful data structures (e.g., dictionaries, sets, and so on) and data types for common use cases, like fixed-point arithmetic, which helps when working with currencies. ## Intuiting ownership with resources Most smart contract languages currently use a ledger-style approach to record ownership, where an asset is stored in the smart contract as an entry in a central ledger, and this ledger is the source of truth around asset ownership. There are many disadvantages to this design, especially when it comes to tracking the ownership of multiple assets belonging to a single account. To find out all of the assets that an account owns, you would have to enumerate all the possible smart contracts that could potentially include this account and search to see if the account owns these assets. In a resource-oriented language like Cadence, resources directly tie an asset to the account that owns it by saving the resource in the account’s storage. As a result, ownership isn’t centralized in a single, central smart contract’s storage. Instead, each account owns and stores its own assets, and the assets can be transferred freely between accounts without the need for arbitration by a central smart contract. Resources are inspired by linear types and increase safety when working with assets, which often have real, intrinsic value. Resources, as enforced by Cadence’s type system, ensure that assets are correctly manipulated and not abused. - Every resource has exactly one owner. If a resource is used as a function parameter, an initial value for a variable, or something similar, the object is not copied. Instead, it is moved to the new location, and the old location is immediately invalidated. - The language will report an error if ownership of a resource was not properly transferred, i.e., when the program attempts to introduce multiple owners for the resource or the resource ends up in a state where it does not have an owner. For example, a resource can only be assigned to exactly one variable and cannot be passed to functions multiple times. - Resources cannot go out of scope. If a function or transaction removes a resource from an account’s storage, it either needs to end the transaction in an account's storage, or it needs to be explicitly and safely deleted. There is no "garbage collection" for resources. The special status of resource objects must be enforced by the runtime; if they were just a compiler abstraction it would be easy for malicious code to break the value guarantees. Resources change how assets are used in a programming environment to better resemble assets in the real world. Users store their currencies and assets in their own account, in their own wallet storage, and they can do with them as they wish. Users can define custom logic and structures for resources that give them flexibility with how they are stored. Additionally, because everyone stores their own assets, the calculation and charging of state rent is fair and balanced across all users in the network. ## An interpreted language Currently, Cadence is an interpreted language, as opposed to a compiled language. This means that there is no Cadence Assembly, bytecode, compiler, or Cadence VM. The structure of the language lends itself well to compilation (e.g., static typing), but using an interpreter for the first version allows us to refine the language features more quickly as we define them. ## Getting started with Cadence Now that you've learned about the goals and design of Cadence and Flow, you're ready to get started with the Flow emulator and tools! Go to the [Getting Started] page to work through language fundamentals and tutorials. {/* Relative links. Will not render on the page */} [Swift]: https://developer.apple.com/swift/ [Kotlin]: https://kotlinlang.org/ [Rust]: https://www.rust-lang.org/ [Move]: https://medium.com/coinmonks/overview-of-move-programming-language-a860ffd8f55d [here]: https://ethfiddle.com/CAp-kQrDUP [Multiple inheritance may lead to unexpected behaviours in the program]: https://medium.com/consensys-diligence/a-case-against-inheritance-in-smart-contracts-d7f2c738f78e [contract upgradability built in by default]: ./language/contract-updatability [Getting Started]: ./tutorial/first-steps --- # JSON-Cadence Data Interchange Format (/docs/json-cadence-spec) > Version 0.3.1 JSON-Cadence is a data interchange format used to represent Cadence values as language-independent JSON objects. This format includes less type information than a complete [ABI], and instead promotes the following tenets: - **Human-readability** β€” JSON-Cadence is easy to read and comprehend, which speeds up development and debugging. - **Compatibility** β€” JSON is a common format with built-in support in most high-level programming languages, making it easy to parse on a variety of platforms. - **Portability** β€” JSON-Cadence is self-describing and thus can be transported and decoded without accompanying type definitions (i.e., an ABI). The following provides reference information and examples when working with various values and types. ## Values ### Void ```json { "type": "Void" } ``` **Example** ```json { "type": "Void" } ``` --- ### Optional ```json { "type": "Optional", "value": null | } ``` **Example** ```json // Non-nil { "type": "Optional", "value": { "type": "UInt8", "value": "123" } } // Nil { "type": "Optional", "value": null } ``` ### Bool ```json { "type": "Bool", "value": true | false } ``` **Example** ```json { "type": "Bool", "value": true } ``` ### String ```json { "type": "String", "value": "..." } ``` **Example** ```json { "type": "String", "value": "Hello, world!" } ``` ### Address ```json { "type": "Address", "value": "0x0" // as hex-encoded string with 0x prefix } ``` **Example** ```json { "type": "Address", "value": "0x1234" } ``` ### Integers `[U]Int`, `[U]Int8`, `[U]Int16`, `[U]Int32`,`[U]Int64`,`[U]Int128`, `[U]Int256`, `Word8`, `Word16`, `Word32`, `Word64`, `Word128` or `Word256`. Although JSON supports integer literals up to 64 bits, all integer types are encoded as strings for consistency. While the static type is not strictly required for decoding, it is provided to inform the client of the potential range. ```json { "type": "", "value": "" } ``` **Example** ```json { "type": "UInt8", "value": "123" } ``` ### Fixed point numbers - `[U]Fix64` Although fixed point numbers are implemented as integers, JSON-Cadence uses a decimal string representation for readability. ```json { "type": "[U]Fix64", "value": "." } ``` **Example** ```json { "type": "Fix64", "value": "12.3" } ``` ### Array ```json { "type": "Array", "value": [ , // ... ] } ``` **Example** ```json { "type": "Array", "value": [ { "type": "Int16", "value": "123" }, { "type": "String", "value": "test" }, { "type": "Bool", "value": true } ] } ``` ### Dictionary Dictionaries are encoded as a list of key-value pairs to preserve the deterministic ordering implemented by Cadence. ```json { "type": "Dictionary", "value": [ { "key": "", "value": }, ... ] } ``` **Example** ```json { "type": "Dictionary", "value": [ { "key": { "type": "UInt8", "value": "123" }, "value": { "type": "String", "value": "test" } } ] // ... } ``` ### Composites (Struct, Resource, Event, Contract, Enum) Composite fields are encoded as a list of name-value pairs in the order in which they appear in the composite type declaration. ```json { "type": "Struct" | "Resource" | "Event" | "Contract" | "Enum", "value": { "id": "", "fields": [ { "name": "", "value": }, // ... ] } } ``` **Example** ```json { "type": "Resource", "value": { "id": "0x3.GreatContract.GreatNFT", "fields": [ { "name": "power", "value": { "type": "Int", "value": "1" } } ] } } ``` ### Path ```json { "type": "Path", "value": { "domain": "storage" | "private" | "public", "identifier": "..." } } ``` **Example** ```json { "type": "Path", "value": { "domain": "storage", "identifier": "flowTokenVault" } } ``` ### Type value ```json { "type": "Type", "value": { "staticType": } } ``` **Example** ```json { "type": "Type", "value": { "staticType": { "kind": "Int" } } } ``` ### InclusiveRange ```json { "type": "InclusiveRange", "value": { "start": , "end": , "step": } } ``` **Example** ```json { "type": "InclusiveRange", "value": { "start": { "type": "Int256", "value": "10" }, "end": { "type": "Int256", "value": "20" }, "step": { "type": "Int256", "value": "5" } } } ``` ### Capability ```json { "type": "Capability", "value": { "id": , "address": "0x0", // as hex-encoded string with 0x prefix "borrowType": , } } ``` **Example** ```json { "type": "Capability", "value": { "id": "1", "address": "0x1", "borrowType": { "kind": "Int" } } } ``` ### Functions ```json { "type": "Function", "value": { "functionType": } } ``` Function values can only be exported β€” they cannot be imported. **Example** ```json { "type": "Function", "value": { "functionType": { "kind": "Function", "typeID": "fun():Void", "parameters": [], "return": { "kind": "Void" } } } } ``` ## Types ### Simple Types These are basic types such as `Int`, `String`, or `StoragePath`. ```json { "kind": } ``` Where `kind` is one of: - `Account` - `AccountCapabilityController` - `AccountKey` - `Address` - `AnyResource` - `AnyResourceAttachment` - `AnyStruct` - `AnyStructAttachment` - `Block` - `Bool` - `Capability` - `CapabilityPath` - `Character` - `DeployedContract` - `DeploymentResult` - `Fix64` - `FixedPoint` - `FixedSizeUnsignedInteger` - `HashAlgorithm` - `HashableStruct` - `Int` - `Int128` - `Int16` - `Int256` - `Int32` - `Int64` - `Int8` - `Integer` - `Never` - `Number` - `Path` - `PrivatePath` - `PublicKey` - `PublicPath` - `SignatureAlgorithm` - `SignedFixedPoint` - `SignedInteger` - `SignedNumber` - `StorageCapabilityController` - `StoragePath` - `String` - `Type` - `UFix64` - `UInt` - `UInt128` - `UInt16` - `UInt256` - `UInt32` - `UInt64` - `UInt8` - `Void` - `Word128` - `Word16` - `Word256` - `Word32` - `Word64` - `Word8` **Example** ```json { "kind": "UInt8" } ``` ### Optional types ```json { "kind": "Optional", "type": } ``` **Example** ```json { "kind": "Optional", "type": { "kind": "String" } } ``` ### Variable sized array types ```json { "kind": "VariableSizedArray", "type": } ``` **Example** ```json { "kind": "VariableSizedArray", "type": { "kind": "String" } } ``` ### Constant sized array types ```json { "kind": "ConstantSizedArray", "type": , "size": , } ``` **Example** ```json { "kind": "ConstantSizedArray", "type": { "kind": "String" }, "size": 3 } ``` ### Dictionary types ```json { "kind": "Dictionary", "key": , "value": } ``` **Example** ```json { "kind": "Dictionary", "key": { "kind": "String" }, "value": { "kind": "UInt16" } } ``` ### Composite types ```json { "kind": "Struct" | "Resource" | "Event" | "Contract" | "StructInterface" | "ResourceInterface" | "ContractInterface", "type": "", // this field exists only to keep parity with the enum structure below; the value must be the empty string "typeID": "", "initializers": [ , // ... ], "fields": [ , // ... ], } ``` **Example** ```json { "kind": "Resource", "type": "", "typeID": "0x3.GreatContract.GreatNFT", "initializers": [ [ { "label": "foo", "id": "bar", "type": { "kind": "String" } } ] ], "fields": [ { "id": "foo", "type": { "kind": "String" } } ] } ``` ### Field types ```json { "id": "", "type": } ``` **Example** ```json { "id": "foo", "type": { "kind": "String" } } ``` ### Parameter types ```json { "label": "