diff --git a/docs/blockchain-development-tutorials/cadence/cadence-advantages/compose-with-cadence-transactions.md b/docs/blockchain-development-tutorials/cadence/cadence-advantages/compose-with-cadence-transactions.md index a2b9492565..ff022c6a49 100644 --- a/docs/blockchain-development-tutorials/cadence/cadence-advantages/compose-with-cadence-transactions.md +++ b/docs/blockchain-development-tutorials/cadence/cadence-advantages/compose-with-cadence-transactions.md @@ -19,20 +19,24 @@ keywords: - Flowscan --- -In this tutorial, you will **compose with someone else's contracts** on Flow testnet. You'll write a Cadence transaction that reads public state from a contract named `Counter` and only increments the counter when it is odd. Then you will extend the transaction to mint NFTs when the counter is odd, demonstrating how to compose multiple contracts in a single transaction. Everything runs against testnet using the Flow CLI and the dependency manager. +# Compose wth Cadence Transactions + +## Overview + +In this tutorial, you'll **compose with someone else's contracts** on Flow testnet. You'll write a Cadence transaction that reads public state from a contract named `Counter` and only increments the counter when it is odd. Then you'll extend the transaction to mint NFTs when the counter is odd, demonstrating how to compose multiple contracts in a single transaction. Everything runs against testnet using the Flow CLI and the dependency manager. You can use transactions developed and tested this way from the frontend of your app. ## Objectives -After completing this guide, you will be able to: +After you complete this guide, you will be able to: -- Configure the Flow CLI _dependency manager_ to import named contracts from **testnet** -- Write a Cadence **transaction** that reads and writes to a public contract you did not deploy -- Run the transaction on **testnet** with a funded account using the Flow CLI -- Extend the transaction to compose multiple public contracts (`Counter` + `ExampleNFT` + `NonFungibleToken`) without redeploying anything -- Set up NFT collections and mint NFTs conditionally based on on-chain state -- View transaction results and NFT transfers using Flowscan +- Configure the Flow CLI _dependency manager_ to import named contracts from **testnet**. +- Write a Cadence **transaction** that reads and writes to a public contract you didn't deploy. +- Run the transaction on **testnet** with a funded account using the Flow command line interface (CLI). +- Extend the transaction to compose multiple public contracts (`Counter` + `ExampleNFT` + `NonFungibleToken`) without redeploying anything. +- Set up NFT collections and mint NFTs conditionally based on on-chain state. +- View transaction results and NFT transfers using Flowscan. ## Prerequisites @@ -54,17 +58,17 @@ Follow the prompts and create a `Basic Cadence project (no dependencies)`. ### Install dependencies -We will resolve imports **using string format** (`import "Counter"`) using the [dependency manager]. +We will resolve imports **using string format** (`import "Counter"`) with the [dependency manager]. -This is the recommended way of working with imports of already-deployed contracts. You should also use the CLI to create new files and add existing ones to `flow.json`. +We recommend that you work this way with imports of already-deployed contracts. You should also use the CLI to create new files and add existing ones to `flow.json`. :::warning -For this exercise, you need to **delete** the existing contract entry for `Counter` from your `flow.json`. You could also use an alias here, but this is simpler since you won't be deploying the `Counter` contract. +For this exercise, **delete** the existing contract entry for `Counter` from your `flow.json`. You could also use an alias here, but this is simpler since you won't deploy the `Counter` contract. ::: -You can install dependencies for already deployed contracts, whether yours or those deployed by others: +You can install dependencies for already deployed contracts, whether yours or those that others deployed: ```bash # Add a deployed instance of the Counter contract @@ -73,11 +77,11 @@ flow dependencies install testnet://0x8a4dce54554b225d.Counter Pick `none` for the deployment account as you won't need to redeploy these contracts. -Once installed with the dependency manager, Cadence imports like `import "Counter"` will resolve to the testnet address when sending transactions on testnet. +After they're installed with the dependency manager, Cadence imports like `import "Counter"` will resolve to the testnet address when they send transactions on testnet. :::info -In Cadence, contracts are deployed to the account storage of the deploying address. Due to security reasons, the same private key produces different address on Cadence testnet and mainnet. One of the features of the dependency manager is to automatically select the right address for imports based on the network you're working on. +In Cadence, contracts deploy to the account storage of the deploying address. Due to security reasons, the same private key produces different address on Cadence testnet and mainnet. One of the features of the dependency manager is to automatically select the right address for imports based on the network you're working on. ::: @@ -85,7 +89,7 @@ In Cadence, contracts are deployed to the account storage of the deploying addre ## Compose with the public `Counter` contract -Review the `Counter` contract that's created as an example by `flow init`: +Review the `Counter` simple contract that's created as an example by `flow init`: ```cadence access(all) contract Counter { @@ -121,8 +125,6 @@ access(all) contract Counter { } ``` -It's an example of a simple contract. - Unlike in Solidity, apps aren't limited to the functionality deployed in a smart contract. One of the ways you can expand your app is to write new transactions that call multiple functions in multiple contracts, with branching based on conditions and state, using a single call and a single signature. You don't need to deploy a new contract, use a proxy, or switch to V2. In this simple example, imagine that you've already deployed a product that has thousands of users and is dependent on the `Counter` smart contract. After a time, you realize that a significant portion of your users only wish to use the `increment` feature if the current `count` is odd, to try and make the number be even. @@ -207,7 +209,7 @@ flow accounts fund testnet-account :::danger -As with other blockchain accounts, once the private key for an account is compromised, anyone with that key has complete control over an account and it's assets. **Never** put private keys directly in `flow.json`. +As with other blockchain accounts, after an account's private key is compromised, anyone with that key completely controls an account and it's assets. **Never** put private keys directly in `flow.json`. ::: @@ -219,11 +221,11 @@ Creating an account using the CLI automatically puts the private key in a `.pkey flow transactions send cadence/transactions/IncrementIfOdd.cdc --signer testnet-account --network testnet ``` -You should see logs that show the prior value and whether the increment occurred. +You will see logs that show the prior value and whether the increment occurred. :::tip -This same transaction could be triggered **from an app** and **signed by a wallet** with a single user click. Your dApp would assemble and submit this exact Cadence transaction using your preferred client library, and the user's wallet would authorize it. +You could trigger this same transaction **from an app** and **signed by a wallet** with a single user click. Your dApp would assemble and submit this exact Cadence transaction using your preferred client library, and the user's wallet would authorize it. ::: @@ -245,7 +247,7 @@ flow dependencies install testnet://012e4d204a60ac6f.ExampleNFT :::warning -This repository uses different deployments for core contracts than those installed by the Flow CLI. If you previously installed core contract dependencies (like `NonFungibleToken`, `MetadataViews`, etc.) using the CLI, you should manually delete all `dependencies` except `Counter` from your `flow.json` file to avoid conflicts. +This repository uses different deployments for core contracts than those that the Flow CLI installs. If you previously installed core contract dependencies (like `NonFungibleToken`, `MetadataViews`, etc.) using the CLI, manually delete all `dependencies` except `Counter` from your `flow.json` file to avoid conflicts. ::: @@ -341,7 +343,7 @@ transaction() { ### Setup NFT Collection -Before you can mint NFTs, you need to set up an NFT collection in your account. Create a transaction to do this: +Before you can mint NFTs, set up an NFT collection in your account. Create a transaction to do this: ```bash flow generate transaction SetupCollection @@ -392,7 +394,7 @@ flow transactions send cadence/transactions/IncrementCounter.cdc --signer testne ### View Your NFT -Click the transaction link in the console to view the transaction in [testnet Flowscan]. After running the transaction **while the counter is odd**, you'll see an NFT in the `Asset Transfers` tab. +Click the transaction link in the console to view the transaction in [testnet Flowscan]. After you run the transaction **while the counter is odd**, you'll see an NFT in the `Asset Transfers` tab. :::info @@ -416,12 +418,12 @@ In this tutorial, you learned how to compose with multiple on-chain contracts us Now that you have completed the tutorial, you should be able to: -- Configure the Flow CLI _dependency manager_ to import named contracts from **testnet** -- Write a Cadence **transaction** that reads and writes to a public contract you did not deploy -- Run the transaction on **testnet** with a funded account using the Flow CLI -- Extend the transaction to compose multiple public contracts (`Counter` + `ExampleNFT` + `NonFungibleToken`) without redeploying anything -- Set up NFT collections and mint NFTs conditionally based on on-chain state -- View transaction results and NFT transfers using Flowscan +- Configure the Flow CLI _dependency manager_ to import named contracts from **testnet**. +- Write a Cadence **transaction** that reads and writes to a public contract you did not deploy. +- Run the transaction on **testnet** with a funded account using the Flow CLI. +- Extend the transaction to compose multiple public contracts (`Counter` + `ExampleNFT` + `NonFungibleToken`) without redeploying anything. +- Set up NFT collections and mint NFTs conditionally based on on-chain state. +- View transaction results and NFT transfers using Flowscan. This approach gives you the freedom to build complex application logic that composes with any public contracts on Flow, making Cadence's composition model a powerful tool for developers building on Flow. diff --git a/docs/blockchain-development-tutorials/cadence/cadence-advantages/index.md b/docs/blockchain-development-tutorials/cadence/cadence-advantages/index.md index 836c29ab26..a3fdc05cff 100644 --- a/docs/blockchain-development-tutorials/cadence/cadence-advantages/index.md +++ b/docs/blockchain-development-tutorials/cadence/cadence-advantages/index.md @@ -19,13 +19,13 @@ keywords: # Cadence Advantages -This series explores the unique advantages and capabilities of Cadence smart contracts on Flow, demonstrating how Cadence's innovative features enable powerful development patterns that aren't possible on other blockchain platforms. From native data availability to seamless transaction composition, these tutorials showcase why Cadence represents the future of smart contract development. +This series explores the unique advantages and capabilities of Cadence smart contracts on Flow, and demonstrates how Cadence's innovative features allow powerful development patterns that aren't possible on other blockchain platforms. From native data availability to seamless transaction composition, these tutorials showcase why Cadence represents the future of smart contract development. ## Tutorials ### [Compose with Cadence Transactions] -Learn how to compose with someone else's on-chain contracts by writing a Cadence transaction that conditionally calls a public contract on testnet, then extend it to mint NFTs when conditions are met—no redeploy required. This tutorial demonstrates Cadence's powerful composition model, showing how you can build complex application logic that interacts with multiple contracts in a single atomic transaction. You'll work with the Flow CLI dependency manager, learn to set up NFT collections, and view results using Flowscan. +Learn how to compose with someone else's on-chain contracts by writing a Cadence transaction that conditionally calls a public contract on testnet, then extend it to mint NFTs when conditions are met, with no redeploy required. This tutorial demonstrates Cadence's powerful composition model, which lets you build complex application logic that interacts with multiple contracts in a single atomic transaction. You'll work with the Flow command line interface (CLI) dependency manager, learn to set up NFT collections, and view results using Flowscan. ### [Native Data Availability with Cadence Scripts] @@ -33,11 +33,16 @@ Discover how Cadence scripts provide native data availability, allowing you to q ### [Upgrading Cadence Contracts] -Learn how to upgrade deployed Cadence contracts through multiple incremental upgrades while preserving existing state and maintaining the same contract address. This tutorial demonstrates Cadence's sophisticated contract upgrade system through two realistic scenarios: first adding an event to notify users when the counter reaches an even number, then extending the contract with additional functionality like incrementing by 2 and checking if numbers are even. You'll understand what can and cannot be changed during upgrades, perform multiple contract updates using Flow CLI, and test upgraded functionality with comprehensive transactions and scripts. +Learn how to upgrade deployed Cadence contracts through multiple incremental upgrades while preserving existing state and maintaining the same contract address. This tutorial demonstrates Cadence's sophisticated contract upgrade system through two realistic scenarios: + +- Adding an event to notify users when the counter reaches an even number. +- Extending the contract with additional functionality like incrementing by two and checking if numbers are even. + +You'll understand what you can and can't change during upgrades, perform multiple contract updates using Flow CLI, and test upgraded functionality with comprehensive transactions and scripts. ## Conclusion -Cadence's unique features—from resource-oriented programming to native data availability, seamless transaction composition, and sophisticated contract upgrade capabilities—represent a fundamental advancement in smart contract development. These tutorials demonstrate how Cadence enables developers to build sophisticated applications with capabilities that simply aren't possible on other blockchain platforms, while maintaining security and developer experience as core principles. +Cadence's unique features, such as resource-oriented programming to native data availability, seamless transaction composition, and sophisticated contract upgrade capabilities, represent a fundamental advancement in smart contract development. These tutorials demonstrate how Cadence allows developers to build sophisticated applications with capabilities that simply aren't possible on other blockchain platforms, while maintaining security and developer experience as core principles. [Compose with Cadence Transactions]: ./compose-with-cadence-transactions.md [Native Data Availability with Cadence Scripts]: ./native-data-availibility-with-cadence-scripts.md diff --git a/docs/blockchain-development-tutorials/cadence/cadence-advantages/native-data-availibility-with-cadence-scripts.md b/docs/blockchain-development-tutorials/cadence/cadence-advantages/native-data-availibility-with-cadence-scripts.md index 6de32eb673..c7c141392e 100644 --- a/docs/blockchain-development-tutorials/cadence/cadence-advantages/native-data-availibility-with-cadence-scripts.md +++ b/docs/blockchain-development-tutorials/cadence/cadence-advantages/native-data-availibility-with-cadence-scripts.md @@ -23,6 +23,8 @@ keywords: # Native Data Availability With Cadence Scripts +## Overview + In Solidity, you can only retrieve data from **view** functions that the contract author anticipated and included in the original contract. If the exact query you want is not exposed, teams typically rely on a _data availability service_ such as The Graph, Covalent, Alchemy Enhanced APIs, Reservoir, or NFTScan to compute and serve that view. In Cadence, **scripts** are general-purpose read programs. They can traverse public account storage, read public capabilities, and compose types from multiple contracts to answer new questions without modifying those contracts. You are not limited to the pre-written surface area of a single contract's views. @@ -35,24 +37,24 @@ In Cadence, a _script_ is a read-only program that can access public data across ## Objectives -After completing this guide, you will be able to: +After you complete this guide, you will be able to: -- Explain why Cadence **scripts** are more powerful than Solidity **view** functions -- Use the [Flow CLI Commands] to execute a Cadence script against mainnet -- Analyze an account for [NBA Top Shot] NFTs held by the account or its child accounts +- Explain why Cadence **scripts** are more powerful than Solidity **view** functions. +- Use the [Flow CLI Commands] to execute a Cadence script against mainnet. +- Analyze an account for [NBA Top Shot] NFTs held by the account or its child accounts. - Build the script incrementally to: - - Query a parent account for child accounts via [_Hybrid Custody_] - - Inspect each child account's storage paths - - Detect NFT collections the parent can control - - List only NBA Top Shot NFTs with display metadata - - Update the script to also list NFL All Day NFT metadata + - Query a parent account for child accounts via [_Hybrid Custody_]. + - Inspect each child account's storage paths. + - Detect NFT collections the parent can control. + - List only NBA Top Shot NFTs with display metadata. + - Update the script to also list NFL All Day NFT metadata. ## Prerequisites -- Basic familiarity with [Cadence] and [Flow accounts] -- Flow CLI installed and authenticated for mainnet (see [Flow CLI Commands]) -- The target parent account uses _Hybrid Custody_ and controls at least one child account that holds NBA Top Shot NFTs - - If you don't have an account that owns NBA Top Shots, you can use `0xfeb88a0fcc175a3d` for this tutorial +- Basic familiarity with [Cadence] and [Flow accounts]. +- Flow command line interface (CLI) installed and authenticated for mainnet (see [Flow CLI Commands]). +- The target parent account uses _Hybrid Custody_ and controls at least one child account that holds NBA Top Shot NFTs. + - If you don't have an account that owns NBA Top Shots, you can use `0xfeb88a0fcc175a3d` for this tutorial. :::tip @@ -77,13 +79,13 @@ flow generate script TopShotQuery This creates a proper Flow project structure with `flow.json` configuration and generates a script template at `cadence/scripts/TopShotQuery.cdc`. -We will **revise one script file** in four passes, running it after each step. This mirrors how you would build and verify a script from scratch. +We will **revise one script file** in four passes, and run it after each step. This mirrors how you would build and verify a script from scratch. --- ## Querying the account to find child accounts -Start by writing a script to borrow the parent's _Hybrid Custody_ manager and return the child addresses it controls. This verifies that imports resolve and that the parent account is configured as expected. +To start, write a script that borrows the parent's _Hybrid Custody_ manager and returns the child addresses it controls. This verifies that imports resolve and that the parent account is configured as expected. First, you'll need to install the `HybridCustody` contract from mainnet. @@ -103,7 +105,7 @@ This will install the contract and its own dependencies. You don't need to deplo :::warning -Installing dependencies in this way is treated by the language server similar to installing packages in other platforms. You'll need to close and reopen the file or type something to trigger a refresh. +The language server treats installing dependencies in this way similar to installing packages in other platforms. You'll need to close and reopen the file or type something to trigger a refresh. ::: @@ -184,7 +186,7 @@ Run it again: flow scripts execute cadence/scripts/TopShotQuery.cdc --network mainnet 0xfeb88a0fcc175a3d ``` -You should see a map from each child address to its storage paths. This tells us where to look for potential collections. +You'll see a map from each child address to its storage paths. This tells us where to look for potential collections. ```bash Result: {0xa16b948ba2c9a858: ["/storage/flowTokenVault", "/storage/PinnacleNFTCollectionProviderForNFTStorefront", "/storage/BackpackCollection", "/storage/PackNFTCollection", "/storage/HybridCustodyChild_0xd8a7e05a7ac670c0", "/storage/ChildAccount_0xfeb88a0fcc175a3d", "/storage/privateForwardingStorage", "/storage/PinnacleCollection", "/storage/AllDayNFTCollection", "/storage/NFTStorefrontV2", "/storage/PinnaclePackNFTCollection", "/storage/ChildAccount_0x0f566b3217c33c4a", "/storage/dapperUtilityCoinReceiver", "/storage/CapFilterParent0xfeb88a0fcc175a3d", "/storage/ChildCapabilityDelegator_0x0f566b3217c33c4a", "/storage/CapFilterParent0x0f566b3217c33c4a", "/storage/flowUtilityTokenReceiver", "/storage/MomentCollection", "/storage/ChildCapabilityDelegator_0xfeb88a0fcc175a3d", "/storage/NFTStorefrontV20x3cdbb3d569211ff3"]} @@ -408,13 +410,13 @@ Run the updated script: flow scripts execute cadence/scripts/TopShotQuery.cdc --network mainnet 0xfeb88a0fcc175a3d ``` -You should now see both Top Shot and AllDay NFTs in the results (truncated for space): +You will see both Top Shot and AllDay NFTs in the results (truncated for space): ```bash Result: {0xa16b948ba2c9a858: {44311697: A.1d7e57aa55817448.MetadataViews.Display(name: "Immanuel Quickley 3 Pointer", description: "", thumbnail: A.1d7e57aa55817448.MetadataViews.HTTPFile(url: "https://assets.nbatopshot.com/media/44311697?width=256")), 8220605: A.1d7e57aa55817448.MetadataViews.Display(name: "Zach Ertz Reception", description: "Normally used to overwhelming his NFC East foes in a different, midnight-green attire, Zach Ertz, in his most productive yardage-based game since 2022, showed in Week 2 that productivity remains well within reach. Challenged to a \u{201c}who wants it more\u{201d}-type battle during a corner route, Ertz adjusted to a floated ball, using both a 6-foot-5 frame and pure strength to rip away a potential interception, turning it into a 21-yard catch for himself. The 12-year veteran helped the Washington Commanders \u{2014} whose seven field goals offset the New York Giants\u{2019} three touchdowns \u{2014} survive for a unique 21-18 win, with Ertz providing four catches (on four targets) and 62 yards on Sept. 15, 2024.", thumbnail: A.1d7e57aa55817448.MetadataViews.HTTPFile(url: "https://media.nflallday.com/editions/3304/media/image?format=jpeg&width=256"))}} ``` -This demonstrates how Cadence scripts can be easily modified to answer different questions about the same data, unlike Solidity where you'd need to deploy new contracts or rely on external indexers. +This demonstrates how you can easily modify Cadence scripts to answer different questions about the same data, unlike Solidity, where you'd need to deploy new contracts or rely on external indexers. --- diff --git a/docs/blockchain-development-tutorials/cadence/cadence-advantages/upgrading-cadence-contracts.md b/docs/blockchain-development-tutorials/cadence/cadence-advantages/upgrading-cadence-contracts.md index 708689468e..c2588d28c9 100644 --- a/docs/blockchain-development-tutorials/cadence/cadence-advantages/upgrading-cadence-contracts.md +++ b/docs/blockchain-development-tutorials/cadence/cadence-advantages/upgrading-cadence-contracts.md @@ -18,58 +18,63 @@ keywords: # Upgrading Cadence Contracts +## Overview + In Cadence, you can upgrade deployed contracts by adding new functionality while preserving existing state and maintaining the same contract address. Unlike other blockchain platforms that require complex proxy patterns or complete redeployment, Cadence allows you to seamlessly extend your contracts with new functions and events through multiple incremental upgrades. -This tutorial demonstrates how to upgrade a deployed contract through two scenarios: first adding an event to notify users when the counter reaches an even number, then extending the contract with additional functionality like incrementing by 2 and checking if numbers are even. +This tutorial demonstrates how to upgrade a deployed contract through two scenarios: + +- Add an event to notify users when the counter reaches an even number. +- Extend the contract with additional functionality, like incrementing by two and checking if numbers are even. ## Objectives -After completing this guide, you will be able to: +After you complete this guide, you will be able to: -- **Deploy a contract** to Flow testnet using Flow CLI -- **Perform incremental contract upgrades** by adding new events and functions +- **Deploy a contract** to Flow testnet using Flow command line interface (CLI). +- **Perform incremental contract upgrades** by adding new events and functions. - **Update deployed contracts multiple times** using the `flow accounts update-contract` command -- **Test upgraded functionality** with Cadence transactions and scripts -- **Understand what can and cannot be changed** during contract upgrades -- **Apply realistic upgrade scenarios** based on user feedback and requirements +- **Test upgraded functionality** with Cadence transactions and scripts. +- **Understand what can and cannot be changed** during contract upgrades. +- **Apply realistic upgrade scenarios** based on user feedback and requirements. ## Prerequisites -- [Flow CLI installed] and configured -- Basic familiarity with [Cadence] and [Flow accounts] -- A **funded testnet account** to deploy and update contracts - - See [Create accounts] and [Fund accounts] in the Flow CLI commands +- [Flow CLI installed] and configured. +- Basic familiarity with [Cadence] and [Flow accounts]. +- A **funded testnet account** to deploy and update contracts. + - See [Create accounts] and [Fund accounts] in the Flow CLI commands. ## Contract Upgrade Overview -Cadence provides a sophisticated contract upgrade system that allows you to modify deployed contracts while ensuring data consistency and preventing runtime crashes. Understanding what you can and cannot change is crucial for successful upgrades. +Cadence provides a sophisticated contract upgrade system that allows you to modify deployed contracts while ensuring data consistency and preventing runtime crashes. It's crucial for successful upgrades that you understand what you can and can't change. ### What You CAN Upgrade -- **Add new functions** - Extend contract functionality with new methods -- **Add new events** - Emit additional events for monitoring and indexing -- **Modify function implementations** - Change how existing functions work -- **Change function signatures** - Update parameters and return types -- **Remove functions** - Delete functions that are no longer needed -- **Change access modifiers** - Update visibility of functions and fields -- **Reorder existing fields** - Field order doesn't affect storage +- **Add new functions** - Extend contract functionality with new methods. +- **Add new events** - Emit additional events for monitoring and indexing. +- **Modify function implementations** - Change how existing functions work. +- **Change function signatures** - Update parameters and return types. +- **Remove functions** - Delete functions that are no longer needed. +- **Change access modifiers** - Update visibility of functions and fields. +- **Reorder existing fields** - Field order doesn't affect storage. ### What You CANNOT Upgrade -- **Add new fields** - Would cause runtime crashes when loading existing data -- **Change field types** - Would cause deserialization errors -- **Remove existing fields** - Fields become inaccessible but data remains -- **Change enum structures** - Raw values must remain consistent -- **Change contract name** - Contract address must remain the same +- **Add new fields** - Would cause runtime crashes when loading existing data. +- **Change field types** - Would cause deserialization errors. +- **Remove existing fields** - Fields become inaccessible, but data remains. +- **Change enum structures** - Raw values must remain consistent. +- **Change contract name** - Contract address must remain the same. ### Why These Restrictions Exist The [Cadence Contract Updatability documentation](https://cadence-lang.org/docs/language/contract-updatability) explains that these restrictions prevent: -- **Runtime crashes** from missing or garbage field values -- **Data corruption** from type mismatches -- **Storage inconsistencies** from structural changes -- **Type confusion** from enum value changes +- **Runtime crashes** from missing or garbage field values. +- **Data corruption** from type mismatches. +- **Storage inconsistencies** from structural changes. +- **Type confusion** from enum value changes. The validation system ensures that existing stored data remains valid and accessible after upgrades. @@ -117,7 +122,7 @@ The faucet provides free testnet tokens for development and testing purposes. Th ## Deploy the Initial Counter Contract -Let's start by deploying a simple Counter contract to testnet. +To start, let's deploy a simple Counter contract to testnet. Open and review `cadence/contracts/Counter.cdc`. This is a simple contract created with all projects: @@ -195,7 +200,7 @@ Deploy your Counter contract to testnet: flow project deploy --network testnet ``` -You should see output similar to: +You will see output similar to: ```bash Deploying 1 contracts for accounts: testnet-account @@ -243,7 +248,7 @@ Run the test transaction: flow transactions send cadence/transactions/IncrementCounter.cdc --signer testnet-account --network testnet ``` -You should see logs showing the counter incrementing and decrementing as expected. +You will see logs that show the counter incrementing and decrementing as expected. ```bash Transaction ID: 251ee40a050b8c7298d33f1b73ed94996a9d99deae8559526d9dddae182f7752 @@ -329,13 +334,13 @@ access(all) contract Counter { This first upgrade adds: -1. **New event**: `CounterIncrementedToEven` to notify when incrementing results in an even number -2. **Enhanced existing function**: The `increment()` function now also emits the new event when appropriate -3. **No new fields**: We only use the existing `count` field to avoid validation errors +1. **New event**: `CounterIncrementedToEven` to notify when incrementing results in an even number. +2. **Enhanced existing function**: The `increment()` function now also emits the new event when appropriate. +3. **No new fields**: We only use the existing `count` field to avoid validation errors. :::info -This demonstrates how you can enhance existing functionality by adding new events and modifying existing function behavior. The original `CounterIncremented` event still works as before, ensuring backward compatibility. +This demonstrates how you can add new behavior and modify existing function behavior, which enhances existing functionality. The original `CounterIncremented` event still works as before, ensuring backward compatibility. ::: @@ -376,11 +381,11 @@ Contract: 'Counter' :::success -The contract has been successfully updated! Notice that: +The contract successfully updated! Notice that: -- The contract address remains the same (`0x9942a81bc6c3c5b7`) -- The existing state (`count`) is preserved -- New functionality is now available +- The contract address remains the same (`0x9942a81bc6c3c5b7`). +- The existing state (`count`) is preserved. +- New functionality is available. ::: @@ -411,7 +416,7 @@ Run the script to check the current state: flow scripts execute cadence/scripts/CheckCounter.cdc --network testnet ``` -You should see output showing the counter state: +You will see output showing the counter state: ```bash Result: {"count": 1, "isEven": false} @@ -419,8 +424,8 @@ Result: {"count": 1, "isEven": false} Notice that: -- The original `count` value is preserved (showing the increment from our earlier test) -- The new `isEven()` function works correctly (1 is odd, so it returns false) +- The original `count` value is preserved (showing the increment from our earlier test). +- The new `isEven()` function works correctly (1 is odd, so it returns false). --- @@ -501,10 +506,10 @@ access(all) contract Counter { This second upgrade adds: -1. **New functions**: `incrementByTwo()` and `decrementByTwo()` that modify the existing counter by 2 +1. **New functions**: `incrementByTwo()` and `decrementByTwo()` that modify the existing counter by two. 2. **New events**: `CounterIncrementedByTwo` and `CounterDecrementedByTwo` for the new functionality -3. **New view function**: `isEven()` to check if the current count is even -4. **Preserved existing functionality**: All previous functionality remains intact +3. **New view function**: `isEven()` to check if the current count is even. +4. **Preserved existing functionality**: All previous functionality remains intact. --- @@ -520,7 +525,7 @@ Use the [Flow CLI update contract command] to upgrade your deployed contract wit flow accounts update-contract ./cadence/contracts/Counter.cdc --signer testnet-account --network testnet ``` -You should see output similar to: +You will see output similar to: ```bash Contract 'Counter' updated on account '0x9942a81bc6c3c5b7' @@ -543,12 +548,12 @@ Contract: 'Counter' :::success -The contract has been successfully updated again! Notice that: +The contract successfully updated again! Notice that: -- The contract address remains the same (`0x9942a81bc6c3c5b7`) -- The existing state (`count`) is preserved -- All previous functionality is still available -- New functionality is now available +- The contract address remains the same (`0x9942a81bc6c3c5b7`). +- The existing state (`count`) is preserved. +- All previous functionality is still available. +- New functionality is now available. ::: @@ -581,7 +586,7 @@ Run the script to check the current state: flow scripts execute cadence/scripts/CheckCounter.cdc --network testnet ``` -You should see output showing the counter state: +You will see output showing the counter state: ```bash Result: {"count": 2, "isEven": true} @@ -589,8 +594,8 @@ Result: {"count": 2, "isEven": true} Notice that: -- The original `count` value is preserved (showing the increments from our earlier tests) -- The new `isEven()` function works correctly (2 is even, so it returns true) +- The original `count` value is preserved (showing the increments from our earlier tests). +- The new `isEven()` function works correctly (two is even, so it returns true). --- @@ -654,10 +659,10 @@ Execute the transaction to test the new functionality: flow transactions send cadence/transactions/TestNewCounter.cdc --signer testnet-account --network testnet ``` -You should see logs showing: +You will see logs that show: -- The counter incrementing by 2 each time with `incrementByTwo()` -- The counter decrementing by 2 with `decrementByTwo()` +- The counter incrementing by two each time with `incrementByTwo()` +- The counter decrementing by two with `decrementByTwo()` - The `isEven()` function working correctly - The original `increment()` function still working normally - The new `CounterIncrementedToEven` event being emitted when incrementing results in an even number @@ -670,7 +675,7 @@ Run the check script again to see the final state: flow scripts execute cadence/scripts/CheckCounter.cdc --network testnet ``` -You should see output similar to: +You will see output similar to: ```bash Result: {"count": 6, "isEven": true} @@ -678,9 +683,9 @@ Result: {"count": 6, "isEven": true} This confirms that: -- The new functions work correctly with the existing counter -- The original state was preserved during the upgrade -- The new functionality is fully operational +- The new functions work correctly with the existing counter. +- The original state was preserved during the upgrade. +- The new functionality is fully operational. --- @@ -690,7 +695,7 @@ Cadence provides a sophisticated contract upgrade system that ensures data consi ### What You Can Upgrade -When upgrading Cadence contracts, you can: +When you upgrade Cadence contracts, you can: - **Add new state variables** (like `countEven`) - **Add new functions** (like `incrementEven()` and `decrementEven()`) @@ -706,26 +711,26 @@ When upgrading Cadence contracts, you can: There are important limitations to contract upgrades: -- **Cannot add new fields** to existing structs, resources, or contracts - - This would cause runtime crashes when loading existing data - - The initializer only runs once during deployment, not on updates -- **Cannot change the type** of existing state variables - - Would cause deserialization errors with stored data -- **Cannot remove existing state variables** (though they become inaccessible) -- **Cannot change enum structures** (raw values must remain consistent) -- **Cannot change the contract name** or address +- **Cannot add new fields** to existing structs, resources, or contracts. + - This would cause runtime crashes when loading existing data. + - The initializer only runs once during deployment, not on updates. +- **Cannot change the type** of existing state variables. + - Would cause deserialization errors with stored data. +- **Cannot remove existing state variables** (though they become inaccessible). +- **Cannot change enum structures** (raw values must remain consistent). +- **Cannot change the contract name** or address. ### Validation Goals The contract update validation ensures that: -- **Stored data doesn't change its meaning** when a contract is updated -- **Decoding and using stored data** does not lead to runtime crashes -- **Type safety is maintained** across all stored values +- **Stored data doesn't change its meaning** when a contract updates. +- **Decoding and using stored data** does not lead to runtime crashes. +- **Type safety is maintained** across all stored values. :::warning -The validation system focuses on preventing runtime inconsistencies with stored data. It does not ensure that programs importing the updated contract remain valid - you may need to update dependent code if you change function signatures or remove functions. +The validation system focuses on preventing runtime inconsistencies with stored data. It does not ensure that programs which import the updated contract remain valid - you may need to update dependent code if you change function signatures or remove functions. ::: @@ -733,7 +738,7 @@ The validation system focuses on preventing runtime inconsistencies with stored #### The `#removedType` Pragma -For cases where you need to remove a type declaration (which is normally invalid), Cadence provides the `#removedType` pragma. This allows you to "tombstone" a type, preventing it from being re-added with the same name: +For cases where you need to remove a type declaration (which is normally invalid), Cadence provides the `#removedType` pragma. This allows you to "tombstone" a type, which prevents it from being re-added with the same name: ```cadence access(all) contract Foo { @@ -746,31 +751,31 @@ access(all) contract Foo { This pragma: -- **Prevents security issues** from type confusion -- **Cannot be removed** once added (prevents circumventing restrictions) -- **Only works with composite types**, not interfaces +- **Prevents security issues** from type confusion. +- **Cannot be removed** after you add it (prevents circumventing restrictions). +- **Only works with composite types**, not interfaces. #### Enum Upgrade Restrictions Enums have special restrictions due to their raw value representation: -- **Can only add enum cases at the end** of existing cases -- **Cannot reorder, rename, or remove** existing enum cases -- **Cannot change the raw type** of an enum -- **Cannot change enum case names** (would change stored values' meaning) +- **Can only add enum cases at the end** of existing cases. +- **Cannot reorder, rename, or remove** existing enum cases. +- **Cannot change the raw type** of an enum. +- **Cannot change enum case names** (would change stored values' meaning). ### Best Practices -When upgrading contracts: +When you upgrade contracts: -1. **Plan upgrades carefully** - Consider future extensibility and avoid breaking changes -2. **Test thoroughly** - Verify both old and new functionality work correctly -3. **Use events** - Emit events for new functionality to enable monitoring and indexing -4. **Document changes** - Keep track of what was added, removed, or modified in each upgrade -5. **Consider dependent code** - Update any programs that import your contract if you change function signatures -6. **Use the `#removedType` pragma** - When you need to permanently remove types -7. **Validate enum changes** - Ensure enum modifications follow the strict rules -8. **Test with existing data** - Verify upgrades work with real stored state, not just empty contracts +1. **Plan upgrades carefully** - Consider future extensibility and avoid breaking changes. +2. **Test thoroughly** - Verify both old and new functionality work correctly. +3. **Use events** - Emit events for new functionality to allow monitoring and indexing. +4. **Document changes** - Keep track of what was added, removed, or modified in each upgrade. +5. **Consider dependent code** - Update any programs that import your contract if you change function signatures. +6. **Use the `#removedType` pragma** - When you need to permanently remove types. +7. **Validate enum changes** - Ensure enum modifications follow the strict rules. +8. **Test with existing data** - Verify upgrades work with real stored state, not just empty contracts. --- @@ -778,34 +783,34 @@ When upgrading contracts: Cadence's contract upgrade model provides several advantages: -- **No proxy patterns needed** - Unlike Ethereum, you don't need complex proxy contracts -- **State preservation** - Existing data and functionality remain intact -- **Address stability** - Contract addresses don't change during upgrades -- **Gas efficiency** - Upgrades are more efficient than redeployment -- **User experience** - Applications continue working without interruption +- **No proxy patterns needed** - Unlike Ethereum, you don't need complex proxy contracts. +- **State preservation** - Existing data and functionality remain intact. +- **Address stability** - Contract addresses don't change during upgrades. +- **Gas efficiency** - Upgrades are more efficient than redeployment. +- **User experience** - Applications continue working without interruption. -This approach allows you to evolve your contracts over time, adding new features and capabilities while maintaining backward compatibility and preserving user data. +This approach allows you to evolve your contracts over time, You can add new features and capabilities and maintain backward compatibility and preserving user data. ## Conclusion In this tutorial, you learned how to upgrade deployed Cadence contracts through multiple incremental upgrades by: -- **Deploying an initial contract** to Flow testnet -- **Performing a first upgrade** to add an event for even numbers based on user feedback -- **Testing the first upgrade** to verify the new event functionality works correctly -- **Performing a second upgrade** to add additional functions and events -- **Testing the complete upgraded functionality** with comprehensive transactions -- **Verifying state preservation** and backward compatibility across multiple upgrades +- **Deploying an initial contract** to Flow testnet. +- **Performing a first upgrade** to add an event for even numbers based on user feedback. +- **Testing the first upgrade** to verify the new event functionality works correctly. +- **Performing a second upgrade** to add additional functions and events. +- **Testing the complete upgraded functionality** with comprehensive transactions. +- **Verifying state preservation** and backward compatibility across multiple upgrades. Now that you have completed the tutorial, you should be able to: -- Deploy contracts to Flow testnet using Flow CLI -- Perform incremental contract upgrades by adding new functions and events -- Update deployed contracts multiple times while preserving existing state -- Test upgraded functionality with Cadence transactions and scripts -- Understand what can and cannot be changed during contract upgrades -- Apply realistic upgrade scenarios based on user feedback and requirements -- Plan and execute multiple contract upgrades over time +- Deploy contracts to Flow testnet using Flow CLI. +- Perform incremental contract upgrades by adding new functions and events. +- Update deployed contracts multiple times while preserving existing state. +- Test upgraded functionality with Cadence transactions and scripts. +- Understand what can and cannot be changed during contract upgrades. +- Apply realistic upgrade scenarios based on user feedback and requirements. +- Plan and execute multiple contract upgrades over time. This incremental upgrade model makes Cadence contracts more flexible and maintainable than traditional smart contract platforms, allowing you to evolve your applications over time based on real user needs without complex migration patterns or breaking changes. The ability to make multiple upgrades while preserving state and maintaining the same contract address provides a powerful foundation for long-term application development.