diff --git a/docs/build/cadence/smart-contracts/best-practices/contract-upgrades.md b/docs/build/cadence/smart-contracts/best-practices/contract-upgrades.md index 8acf65b090..37d3b5d7ba 100644 --- a/docs/build/cadence/smart-contracts/best-practices/contract-upgrades.md +++ b/docs/build/cadence/smart-contracts/best-practices/contract-upgrades.md @@ -20,28 +20,30 @@ keywords: - contract security --- -### Problem +# Contract Upgrades with Incompatible Changes + +## Problem I have an incompatible upgrade for a contract. How can I deploy this? -### Solution +## Solution -Please don't perform incompatible upgrades between contract versions in the same account. -There is too much that can go wrong. +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](https://cadence-lang.org/docs/language/contract-updatability) and then run a post-upgrade function on the new contract code if needed. +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. +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 (for example, `/public/MyProjectVault` becomes `/public/MyProjectVault002`) in addition to making the incompatible changes, then create a new account and deploy the updated contract there. ⚠️ 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: +If you absolutely must keep the old address when you make 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. +1. Delete any resources used in the contract account, such as an Admin resource. 2. Delete the contract from the account. 3. Deploy the new contract to the account. -⚠️ Note that 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! +⚠️ 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, after any users have received `structs` or `resources` from the contract, do not attempt an incompatible upgrade with this method! + + + +[compatible upgrades]: https://cadence-lang.org/docs/language/contract-updatability \ No newline at end of file diff --git a/docs/build/cadence/smart-contracts/best-practices/project-development-tips.md b/docs/build/cadence/smart-contracts/best-practices/project-development-tips.md index 513a5846e3..cc5b665093 100644 --- a/docs/build/cadence/smart-contracts/best-practices/project-development-tips.md +++ b/docs/build/cadence/smart-contracts/best-practices/project-development-tips.md @@ -25,242 +25,139 @@ keywords: ## Context -Smart Contracts are the bedrock piece of security for many important parts -of the Flow blockchain, as well as for any project that is deployed to a blockchain. - -They are also the most visible technical parts of any project, -since users will be querying them for data, building other smart contracts that interact with them, -and using them as learning materials and templates for future projects. -Furthermore, when deployed they are publicly available code on the blockchain -and often also in public Github repos. - -Therefore, the process around designing, building, testing, documenting, -and managing these projects needs to reflect the critical importance they hold in the ecosystem. - -Every software project strikes a balance between effort spent on product/feature delivery -vs the many other demands of the software development lifecycle, whether testing, technical debt, -automation, refactoring, or documentation etc. Building in Web3 we face the same trade-offs, -but in a higher risk and consequence environment than what is typical for most software. -A mismanaged or untested smart contract may result in **significant** financial losses -as a result of vulnerabilities which were overlooked then exploited. -We highly recommend builders adopt these best practices to help mitigate these risks. - -If they do so, they will be able to build better smart contracts, avoid potential bugs, -support user and third-party adoption of their projects, and increase their chances of success -by being a model for good software design. Additionally, the more projects that adopt -good software design and management standards normalizes this behavior, -encouraging other projects in the ecosystem to do the same which creates a healthier -and more vibrant community. - -Ensuring appropriate levels of testing results in better smart contracts which have -pro-actively modeled threats and engineered against them. Ensuring appropriate levels -of standards adoption ([FungibleToken](https://github.com/onflow/flow-ft), -[NFT Metadata](../../advanced-concepts/metadata-views.md), [NFT StoreFront](https://github.com/onflow/nft-storefront), etc) by dapp -builders amplifies the network effects for all in the ecosystem. NFTs in one dapp can be -readily consumed by other dapps through onchain events with no new integration -required. With your help and participation we can further accelerate healthy and vibrant -network effects across the Flow ecosystem! - -Some of these suggestions might seem somewhat unnecessary, -but it is important to model what a project can do to manage its smart contracts the best -so that hopefully all of the other projects follow suit. - -This also assumes standard software design best practices also apply. -Indeed, many of these suggestions are more general software design best practices, -but there may be others that are assumed but not included here. - -### Implementing These Practices - -This document serves as mostly an outline of best practices the projects should follow. -As with all best practices, teams will choose which applies to them and their work process, -however, we recommend that teams explicitly define a minimum acceptable set of standards -for themselves along with the mechanisms to ensure they are being observed. - -Some teams may also have their own set of development standards that achieve a similar goal -to these. These recommendations are not meant to be the only paths to success, -so if a team disagrees with some of these and wants to do things their own way, -they are welcome to pursue that. This document just shows some generic suggestions -for teams who might not know how they want to manage their project. +Smart Contracts are the bedrock piece of security for many important parts of the Flow blockchain, as well as for any project that is deployed to a blockchain. + +They are also the most visible technical parts of any project, since users will query them for data, build other smart contracts that interact with them, and use them as materials to learn and templates for future projects. Furthermore, when deployed they are publicly available code on the blockchain and often also in public Github repos. + +Therefore, the process to design, build, test, document, and manage these projects needs to reflect the critical importance they hold in the ecosystem. + +Every software project strikes a balance between effort spent on product or feature delivery versus the many other demands of the software development lifecycle, whether testing, technical debt, automation, refactoring, or documentation. Since we build in Web3, we face the same trade-offs, but in a higher risk and consequence environment than what is typical for most software. A mismanaged or untested smart contract may result in **significant** financial losses because of overlooked and exploited vulnerabilities. We highly recommend builders adopt these best practices to help mitigate these risks. + +If they do so, they can build better smart contracts, avoid potential bugs, support user and third-party adoption of their projects, and increase their chances of success as a model for good software design. Additionally, the more projects that adopt good software design and management standards normalizes this behavior, and encourages other projects in the ecosystem to do the same, which creates a healthier and more vibrant community. + +When you ensure appropriate levels of testing, it results in better smart contracts which have pro-actively modeled threats and engineered against them. dApp builders who ensure appropriate levels of standards adoption ([FungibleToken](https://github.com/onflow/flow-ft), [NFT Metadata], [NFT StoreFront], and so on) amplify the network effects for all in the ecosystem. NFTs in one dApp can be readily consumed by other dApps through onchain events with no new integration required. With your help and participation, we can further accelerate healthy and vibrant network effects across the Flow ecosystem! + +Some of these suggestions might seem somewhat unnecessary, but it is important to model what a project can do to manage its smart contracts the best so that hopefully all of the other projects follow suit. + +This also assumes standard software design best practices also apply. Indeed, many of these suggestions are more general software design best practices, but there may be others that are assumed but not included here. + +### Implement These Practices + +This document serves as mostly an outline of best practices the projects should follow. As with all best practices, teams will choose which applies to them and their work process. However, we recommend that teams explicitly define a minimum acceptable set of standards for themselves along with the mechanisms to ensure that they are observed. + +Some teams may also have their own set of development standards that achieve a similar goal to these. These recommendations are not meant to be the only paths to success, so if a team disagrees with some of these and wants to do things their own way, they are welcome to pursue that. This document just shows some generic suggestions for teams who might not know how they want to manage their project. ## Design Process -Smart contracts usually manage a lot of value, have many users, and are difficult to upgrade -for a variety of reasons. Therefore, it is important to have a clearly defined design -process for the smart contracts before much code is written so that the team +Smart contracts usually manage a lot of value, have many users, and are difficult to upgrade for a variety of reasons. Therefore, it is important to have a clearly defined design process for the smart contracts before much code is written so that the team can set themselves up for success. Here are some recommendations for how projects can organize the foundations of their projects. ### Projects should ensure that there is strong technical leadership for their smart contracts -Developing a dapp requires a clear vision for the role of the smart contract and how it's integrated. -Security vulnerabilities may arise from bugs directly in smart contract code (and elsewhere in the system). -Asynchronous interaction vectors may lead to forms of malicious abuse, -DOS etc in a contract triggering explosive compute unit costs for the developer or other problems. +To develop a dApp requires a clear vision for the role of the smart contract and how it's integrated. Security vulnerabilities may arise from bugs directly in smart contract code (and elsewhere in the system). Asynchronous interaction vectors may lead to forms of malicious abuse, Denial of Service (DOS), and so on in a contract that trigger explosive compute unit costs for the developer or other problems. -We recommend that engineers leading a project and deploying to mainnet have an understanding -of software and security engineering fundamentals and have been thorough -in their Cadence skills development. More in-depth resources for learning Cadence -are available [here](https://cadence-lang.org/docs/). +We recommend that engineers who lead a project and deploy to mainnet understand software and security engineering fundamentals and have been thorough in their Cadence skills development. For more in-depth resources to help learn Cadence, see the [Cadence documentation]. -The technical leader should be someone who understands Cadence well and has written Cadence smart contracts -before. Production-level smart contracts are not the place for beginners to get their start. +The technical leader should be someone who understands Cadence well and has written Cadence smart contracts before. Production-level smart contracts are not the place for beginners to get their start. -It should be this person's responsibility to lead design discussions -with product managers and the community, write most of the code and tests, -solicit reviews, make requested changes and make sure the project gets completed in a timely manner. +It should be this person's responsibility to lead design discussions with product managers and the community, write most of the code and tests, solicit reviews, make requested changes and make sure the project gets completed in a timely manner. -The leader should also understand how to sign transactions with the CLI -to deploy/upgrade smart contracts, run admin transactions, and troubleshoot problems, etc. -If something goes wrong in relation to the smart contract -that needs to be handled with a bespoke transaction, it is important that the owner -knows how to build and run transactions and scripts safely to address the issues -and/or upgrade the smart contracts. +The leader should also understand how to sign transactions with the CLI to deploy and upgrade smart contracts, run admin transactions, troubleshoot problems, and so on. If something goes wrong in relation to the smart contract that needs to be handled with a bespoke transaction, it is important that the owner knows how to build and run transactions and scripts safely to address the issues and upgrade the smart contracts. -The project should also have a clear plan of succession in case the original owner -is not available or leaves the project. It is important that there are others who -can fill in who have a clear understanding of the code and requirements so they can give good feedback, -perform effective reviews, and make changes where needed. +The project should also have a clear plan of succession in case the original owner is not available or leaves the project. It is important that there are others who can fill in who clearly understand the code and requirements so they can give good feedback, perform effective reviews, and make changes where needed. ### Projects should maintain a well-organized open source Repo for their smart contracts -As projects like NBA Topshot have shown, when a blockchain product becomes successful -others can and do to build on top of what you are doing. -Whether that is analytics, tools, or other value adds that could help grow your project ecosystem, -composability is key and that depends on open source development. -If there isn't already an open source repo, builders should consider creating one. +As projects like NBA Topshot have shown, when a blockchain product becomes successful others can and do to build on top of what you are doing. Whether that is analytics, tools, or other value adds that could help grow your project ecosystem, composability is key and that depends on open source development. If there isn't already an open source repo, builders should consider creating one. + +Builders can start from the [the Flow open source template] and make sure all of their repo is set up with some initial documentation for what the repo is for before any code is written. External developers and users should have an easily accessible home page to go to to understand any given project. -Builders can start from the [the Flow open source template](https://github.com/onflow/open-source-template) -and make sure all of their repo is set up with some initial documentation for what the repo is for -before any code is written. External developers and users should have an easily accessible home page -to go to to understand any given project. +The repo should also have some sort of high-level design document that lays out the intended design and architecture of the smart contract. The project leads should determine what is best for them to include in the document, but some useful things to include are basic user stories, architecture of the smart contracts, and any questions that still need to be answered about it. -The repo should also have some sort of high-level design document that lays out -the intended design and architecture of the smart contract. -The project leads should determine what is best for them to include in the document, -but some useful things to include are basic user stories, architecture of the smart contracts, -and any questions that still need to be answered about it. - Where applicable, diagrams should be made describing state machines, user flows, etc. - This document should be shared in an issue in the open source repo -where the contracts or features are being developed, -then later moved to the README or another important docs page. +Where applicable, diagrams should be made that describe state machines, user flows, etc. - This document should be shared in an issue in the open source repo where the contracts or features are developed, then later moved to the `.README` or another important docs page. -A high level design is a key opportunity to model threats -and understand the risks of the system. The process of collaborating -and reviewing designs together helps ensure that more edge-cases are captured and addressed. -It's also a lot less effort to iterate on a design than on hundreds of lines of Cadence. +A high level design is a key opportunity to model threats and understand the risks of the system. When we collaborate and review designs together, it helps ensure that we capture and address more edge-cases. It's also a lot less effort to iterate on a design than on hundreds of lines of Cadence. -## Development Process Recommendations +## Development process recommendations -### The Development process should be iterative, if possible +### The development process should be iterative, if possible -The project should develop an MVP first, get reviews, and test thoroughly, -then add additional features with tests. This ensures that the core features are designed -thoughtfully and makes the review process easier because they can focus on each feature -one at a time instead of being overwhelmed by a huge block of code. +The project should develop an MVP first, get reviews, and test thoroughly, then add additional features with tests. This ensures that the core features are designed thoughtfully and makes the review process easier because they can focus on each feature one at a time, rather than get overwhelmed by a huge block of code. -### Comments and field/function descriptions are essential! +### Comments and field or function descriptions are essential! -Our experience writing many Cadence smart contracts has taught us how important documentation -is. It especially matters what is documented and for whom, and in that way we are no different from -any software language. The Why is super important, if for example something - an event - that -happens in one contract leads to outcomes in a different contract. The What helps give context, -the reason for the code turning out the way it is. The How, you don't document - you've written -the code. Comments should be directed to those who will follow after you in changing the code. +Our experience writing many Cadence smart contracts has taught us how important documentation is. It especially matters what is documented and for whom, and in that way we are no different from any software language. The "why" is super important, if for example something - an event - that happens in one contract leads to outcomes in a different contract. The "what" helps give context, the reason that the code turned out the way it is. The "how" you don't document - you've written the code. Comments should be directed to those who will change the code after you. -Comments should be written at the same time (or even before) the code is written. -This helps the developer and reviewers understand the work-in-progress code better, -as well as the intentions of the design (for testing and reviewing). -Functions should be commented with a - Description - Parameter descriptions - Return value descriptions +Write comments at the same time (or even before) the code is written. This helps the developer and reviewers understand the work-in-progress code better, as well as the intentions of the design (for test and review). Comment functions with: -Top Level comments and comments for types, fields, events, -and functions should use `///` (three slashes) to be recognised by the -[Cadence Documentation Generator](https://github.com/onflow/cadence-tools/tree/master/docgen). -Regular comments within functions should only use two slashes (`//`) +- A description +- Parameter descriptions +- Return value descriptions -## Testing Recommendations +Top-Level comments and comments for types, fields, events, and functions should use `///` (three slashes) to be recognised by the [Cadence Documentation Generator]. Regular comments within functions should only use two slashes (`//`) -Summarized below is a list of testing related recommendations -which are noteworthy to mention for a typical smart contract project. +## Test Recommendations -Popular testing frameworks to use for cadence are listed here: +Summarized below is a list of test-related recommendations for a typical smart contract project. -- Cadence: [Cadence Testing Framework](../../smart-contracts/testing.md) -- Go: [Overflow](https://github.com/bjartek/overflow) +Popular testing frameworks to use for Cadence are listed here: -The same person who writes the code should also write the tests. -They have the clearest understanding of the code paths and edge cases. +- Cadence: [Cadence Testing Framework] +- Go: [Overflow] -Tests should be **mandatory**, not optional, even if the contract is copied from somewhere else. -There should be thorough emulator unit tests in the public repo. -[See the flow fungible token repo](https://github.com/onflow/flow-ft/tree/master/lib/js/test) -for an example of unit tests in javascript. +The same person who writes the code should also write the tests. They have the clearest knowledge of the code paths and edge cases. -Every time there is a new Cadence version or emulator version, -the dependencies of the repo should be updated to make sure the tests are all still passing. +Tests should be **mandatory**, not optional, even if the contract is copied from somewhere else. There should be thorough emulator unit tests in the public repo. [See the flow fungible token repo] for an example of unit tests in javascript. -Tests should avoid being monolithic; -Individual test cases should be set up for each part of the contract to test them in isolation. -There are some exceptions, like contracts that have to run through a state machine -to test different cases. Positive and negative cases need to be tested. +Every time there is a new Cadence version or emulator version, make sure to update the repo dependencies to confirm the tests all still pass. -Integration tests should also be written to ensure that your app and/or backend can interact -properly with the smart contracts. +Tests should avoid being monolithic; you should set up individual test cases for each part of the contract to test them in isolation There are some exceptions, like contracts that have to run through a state machine to test different cases. Positive and negative cases need to be tested. -## Managing Project Keys and Deployments +You should also write integration tests to ensure that your app or backend can interact properly with the smart contracts. + +## Manage Project Keys and deployments Smart contract keys and deployments are very important and need to be treated as such. -### Private Keys should be stored securely +### Store Private Keys securely + +Do not keep Private Keys for the contract and admin accounts in plain text format anywhere. Projects should determine a secure solution that works best for them to store their private keys. We recommend that you them in a secure key store such as Google KMS or something similar. -Private Keys for the contract and/or admin accounts should not be kept in plain text format anywhere. -Projects should determine a secure solution that works best for them to store their private keys. -We recommend storing them in a secure key store such as google KMS or something similar. +### Handle deployments to Testnet or Mainnet -### Deployments to Testnet or Mainnet should be handled transparently +As projects become more successful, communities around them grow. In a trustless ecosystem, that also means more of others building on your contracts. Before you deploy or upgrade a contract, it is important to maintain clear community communications with sufficient notice, since changes will always bring added risk. When you give community members time to review and address issues with upgrades before they happen, it builds trust and confidence in projects. -As projects become more successful, communities around them grow. -In a trustless ecosystem, that also means more of others building on your contracts. -Before deploying or upgrading a contract, it is important to maintain -clear community communications with sufficient notice, since changes will always bring added risk. -Giving community members time to review and address issues with upgrades -before they happen builds trust and confidence in projects. -Here are a few suggestions for how to manage a deployment or upgrade. +Here are a few suggestions for how to manage a deployment or upgrade: - Communicate to all stake-holders well in advance - - Share the proposal with the community at least a week in advance (unless it is a critical bug fix) - - Examples of places to share are your project's chat, forum, blog, email list, etc. - - This will allow the community and other stakeholders to have plenty of time - to view the upcoming changes and provide feedback if necessary. - - Share the time of the deployment and the deployment transaction with branch/commit hash information to ensure the transaction itself is correct. + - Share the proposal with the community at least a week in advance (unless it is a critical bug fix). + - Examples of places to share are your project's chat, forum, blog, email list, and so on. + - This will allow the community and other stakeholders to have plenty of time to view the upcoming changes and provide feedback if necessary. + - Share the time of the deployment and the deployment transaction with branch and commit hash information to ensure the transaction itself is correct. - Coordinate deployment with stakeholders to make sure it is done correctly and on time. ## Responsibilities to the Community -Web3 brings tremendous possibilities for engineering applications with trustlessness -and composability in mind, with Cadence and Flow offering unique features to achieve this. -If every project treats their community and the Flow community with respect and care, -the things we can all build together will be very powerful. +Web3 brings tremendous possibilities for engineering applications with trustlessness and composability in mind, and Cadence and Flow offer unique features to achieve this. If every project treats their community and the Flow community with respect and care, the things we can all build together will be very powerful. ### Projects should have thorough documentation -Encouraging adoption of project contracts to the broader ecosystem -raises the bar around code providing clear high-level descriptions, -with detailed and useful comments within contracts, transactions, and scripts. -The more that a project can be understood, that it adheres to standards, -and can be built upon with ease, the more likely others will build against it in turn. +Encouraging adoption of project contracts to the broader ecosystem raises the bar around code to provides clear high-level descriptions, with detailed and useful comments within contracts, transactions, and scripts. The more that users can understand a project, that it adheres to standards, and can be built upon with ease, the more likely others will build against it in turn. -Each project should have a detailed README.md with these sections: - Explanation of the project itself with links to the app - Addresses on various networks - High-level technical description of the contracts with emphasis on important types and functionality - Architecture diagram (if applicable) - Include links to tutorials if they are external - Flow smart contract standards that a project implements +Each project should have a detailed README.md with these sections: -Additionally, each contract, transaction, and script should have high-level descriptions -at the top of their files. This way, anyone in the community can easily -come in and understand what each one is doing without having to parse confusing code. +- Explanation of the project itself with links to the app. +- Addresses on various networks. +- High-level technical description of the contracts with emphasis on important types and functionality +- Architecture diagram (if applicable) - Include links to tutorials if they are external - Flow smart contract standards that a project implements + +Additionally, each contract, transaction, and script should have high-level descriptions at the top of their files. This way, anyone in the community can easily come in and understand what each one is doing without the need to parse confusing code. ### Projects should engage with and respond to their own Community -Once a contract is deployed, the work doesn't stop there. -Project communities require ongoing nurturing and support. -As the developer of a public project on a public blockchain, -the owners have an obligation to be helpful and responsive to the community -so that they can encourage composability and third party interactions. +After a contract is deployed, the work doesn't stop there. Project communities require continuous nurturing and support. As the developer of a public project on a public blockchain, the owners have an obligation to be helpful and responsive to the community so that they can encourage composability and third party interactions. - Keep issues open in the repo. - The owner should turn on email notifications for new issue creation in the repo. @@ -269,29 +166,34 @@ so that they can encourage composability and third party interactions. ### Projects should contribute to the greater Flow and Cadence community -Flow has a vibrant and growing community of contributors around the world. -Through our mutual collaboration we've had numerous community Flow Improvement Proposals -([FLIP](https://github.com/onflow/flow/tree/master/flips)s) shipped. -If you have an interest in a particular improvement for Flow or Cadence, -we host open meetings which you are welcome to join (announced on discord) -and can participate anytime on any of the FLIPs -[already proposed](https://github.com/onflow/flow/pulls?q=is%3Aopen+is%3Apr+label%3AFLIP). - -Responsible project maintainers should contribute to discussions -about important proposals (new cadence features, standard smart contracts, metadata, etc) -and generally be aware about evolving best practices and anti-pattern understandings. -Projects who contribute to these discussions are able to influence them to ensure -that the language/protocol changes are favorable to them -and the rest of the app developers in the ecosystem. -It also helps the owner to promote the project and themselves. - -Resources for Best Practices: +Flow has a vibrant and growing community of contributors around the world. Through our mutual collaboration, we've had numerous community Flow Improvement Proposals ([FLIP]s) shipped. If you have an interest in a particular improvement for Flow or Cadence, we host open meetings which you are welcome to join (announced on discord) and can participate anytime on any of the FLIPs [already proposed]. -- [cadence/design-pattern](https://cadence-lang.org/docs/design-patterns) -- [cadence/anti-patterns](https://cadence-lang.org/docs/anti-patterns) -- [cadence/security-best-practices](./security-best-practices.md) +Responsible project maintainers should contribute to discussions about important proposals (new cadence features, standard smart contracts, metadata, and so on), and generally be aware about current best practices and anti-pattern knowledge. Projects who contribute to these discussions are able to influence them to ensure that the language and protocol changes are favorable to them and the rest of the app developers in the ecosystem. It also helps the owner to promote the project and themselves. -Composability and extensibility should also be priorities while designing, developing, -and documenting their projects. +Resources for Best Practices: -If you have any feedback about these guidelines, please create an issue in the onflow/cadence-style-guide repo or make a PR updating the guidelines so we can start a discussion. +- [cadence/design-pattern] +- [cadence/anti-patterns] +- [cadence/security-best-practices] + +Composability and extensibility should also be priorities while they design, develop, and document their projects. + +If you have any feedback about these guidelines, create an issue in the [onflow/cadence-style-guide] repo or make a PR to update the guidelines so we can start a discussion. + + + +[cadence/design-pattern]: https://cadence-lang.org/docs/design-patterns +[cadence/anti-patterns]: https://cadence-lang.org/docs/anti-patterns +[cadence/security-best-practices]: ./security-best-practices.md) +[FLIP]: https://github.com/onflow/flow/tree/master/flips +[already proposed]: https://github.com/onflow/flow/pulls?q=is%3Aopen+is%3Apr+label%3AFLIP +[onflow/cadence-style-guide]: https://github.com/onflow/cadence-style-guide +[See the flow fungible token repo]: https://github.com/onflow/flow-ft/tree/master/lib/js/test +[Cadence Testing Framework]: ../../smart-contracts/testing.md +[Overflow]: https://github.com/bjartek/overflow +[Cadence Documentation Generator]: https://github.com/onflow/cadence-tools/tree/master/docgen +[the Flow open source template]: https://github.com/onflow/open-source-template +[Cadence documentation]: https://cadence-lang.org/docs/ +[FungibleToken]: https://github.com/onflow/flow-ft +[NFT Metadata]: ../../advanced-concepts/metadata-views.md +[NFT StoreFront]: https://github.com/onflow/nft-storefront \ No newline at end of file diff --git a/docs/build/cadence/smart-contracts/best-practices/security-best-practices.md b/docs/build/cadence/smart-contracts/best-practices/security-best-practices.md index a1d7eb8b10..1f2da9da20 100644 --- a/docs/build/cadence/smart-contracts/best-practices/security-best-practices.md +++ b/docs/build/cadence/smart-contracts/best-practices/security-best-practices.md @@ -21,54 +21,47 @@ keywords: - security guidelines --- +# Cadence Security Best Practices + This is an opinionated list of best practices Cadence developers should follow to write more secure Cadence code. -Some practices listed below might overlap with advice in the [Cadence Anti-Patterns](https://cadence-lang.org/docs/design-patterns) section, which is a recommended read as well. +Some practices listed below might overlap with advice in the [Cadence Anti-Patterns] section, which is a recommended read as well. ## References -[References](https://cadence-lang.org/docs/language/references) are ephemeral values and cannot be stored. If persistence is required, store a capability and borrow it when needed. +[References] are ephemeral values and cannot be stored. If persistence is required, store a capability and borrow it when needed. -References allow freely upcasting and downcasting, e.g. a restricted type can be cast to its unrestricted type which will expose all `access(all)` functions and fields of the type. -So even if your capability uses an interface to restrict its functionality, it can -still be downcasted to expose all other public functionality. +References allow free upcasting and downcasting. For example, a restricted type can cast to its unrestricted type, which exposes all `access(all)` functions and fields of the type. So, even if your capability uses an interface to restrict its functionality, it can still downcast to expose all other public functionality. -Therefore, any privileged functionality in a resource or struct that will have a public -capability needs to have entitled accecss, for example `access(Owner)`. -Then, the only way to access that functionality would be through an entitled reference, -like ``. +Therefore, any privileged functionality in a resource or struct that will have a public capability needs to have entitled accecss, for example `access(Owner)`. Then, the only way to access that functionality would be through an entitled reference, like ``. ## Account Storage -Don't trust a users' [account storage](https://cadence-lang.org/docs/language/accounts#account-storage). Users have full control over their data and may reorganize it as they see fit. Users may store values in any path, so paths may store values of "unexpected" types. These values may be instances of types in contracts that the user deployed. +Don't trust a users' [account storage]. Users have full control over their data and may reorganize it as they see fit. Users may store values in any path, so paths may store values of "unexpected" types. These values may be instances of types in contracts that the user deployed. -Always [borrow](https://cadence-lang.org/docs/language/capabilities) with the specific type that is expected. Or, check if the value is an instance of the expected type. +Always [borrow] with the specific type that is expected. Or, check if the value is an instance of the expected type. ## Authorized Accounts -Access to an `&Account` gives access to whatever is specified in the account entitlements -list when that account reference is created. -Therefore, [avoid using Account references](https://cadence-lang.org/docs/anti-patterns#avoid-using-authaccount-as-a-function-parameter) as a function parameter or field unless absolutely necessary and only use the minimal set of entitlements required -for the specified functionality so that other account functionality cannot be accessed. +Access to an `&Account` gives access to whatever is specified in the account entitlements list when that account reference is created. Therefore, [don't use Account references] as a function parameter or field unless absolutely necessary and only use the minimum set of entitlements required for the specified functionality so that other account functionality cannot be accessed. -It is preferable to use capabilities over direct `&Account` references when exposing account data. Using capabilities allows the revocation of access by unlinking and limits the access to a single value with a certain set of functionality. +It is preferable to use capabilities over direct `&Account` references when you expose account data. Capabilities revoke access by unlinking and limits the access to a single value with a certain set of functionality. ## Capabilities -Don't store anything under the [public capability storage](https://cadence-lang.org/docs/language/capabilities) unless strictly required. Anyone can access your public capability using `Account.capabilities.get`. If something needs to be stored under `/public/`, make sure only read functionality is provided by restricting privileged functions with entitlements. +Don't store anything under the [public capability storage] unless strictly required. Anyone can access your public capability with `Account.capabilities.get`. If something needs to be stored under `/public/`, restrict privileged functions with entitlements to make sure only read functionality is provided. -When publishing a capability, the capability might already be present at the given `PublicPath`. -In that case, Cadence will panic with a runtime error to not override the already published capability. +When you publish a capability, the capability might already be present at the given `PublicPath`. In that case, Cadence will panic with a runtime error to not override the already published capability. -It is a good practice to check if the public capability already exists with `account.capabilities.get().check` before creating it. This function will return `nil` if the capability does not exist. +It is a good practice to check if the public capability already exists with `account.capabilities.get().check` before you create it. This function will return `nil` if the capability does not exist. -If it is necessary to handle the case where borrowing a capability might fail, the `account.check` function can be used to verify that the target exists and has a valid type. +If there's a case where borrowing a capability might fail, use the `account.check` function to verify that the target exists and has a valid type. -Ensure capabilities cannot be accessed by unauthorized parties. For example, capabilities should not be accessible through a public field, including public dictionaries or arrays. Exposing a capability in such a way allows anyone to borrow it and perform all actions that the capability allows. +Ensure that unauthorized parties cannot access capabilities. For example, capabilities should not be accessible through a public field, such as public dictionaries or arrays. When you expose a capability in such a way, anyone can borrow it and perform all actions that the capability allows. ## Transactions -Audits of Cadence code should also include [transactions](https://cadence-lang.org/docs/language/transactions), as they may contain arbitrary code, just, like in contracts. In addition, they are given full access to the accounts of the transaction's signers, i.e. the transaction is allowed to manipulate the signers' account storage, contracts, and keys. +Audits of Cadence code should also include [transactions], as they may contain arbitrary code, just, like in contracts. In addition, they are given full access to the accounts of the transaction's signers, i.e. the transaction is allowed to manipulate the signers' account storage, contracts, and keys. Signing a transaction gives access to the `&Account`, i.e. access to the account's storage, keys, and contracts depending on what entitlements are specified. @@ -76,14 +69,26 @@ Do not blindly sign a transaction. The transaction could for example change depl ## Types -Use [restricted types and interfaces](https://cadence-lang.org/docs/language/restricted-types). Always use the most specific type possible, following the principle of least privilege. Types should always be as restrictive as possible, especially for resource types. +Use [restricted types and interfaces]. Always use the most specific type possible, following the principle of least privilege. Types should always be as restrictive as possible, especially for resource types. If given a less-specific type, cast to the more specific type that is expected. For example, when implementing the fungible token standard, a user may deposit any fungible token, so the implementation should cast to the expected concrete fungible token type. ## Access Control -Declaring a field as [`access(all)`](https://cadence-lang.org/docs/language/access-control) only protects from replacing the field's value, but the value itself can still be mutated if it is mutable. Remember that containers, like dictionaries, and arrays, are mutable. +Declaring a field as [`access(all)`] only protects from replacing the field's value, but the value itself can still be mutated if it is mutable. Remember that containers, like dictionaries, and arrays, are mutable. Prefer non-public access to a mutable state. That state may also be nested. For example, a child may still be mutated even if its parent exposes it through a field with non-settable access. Do not use the `access(all)` modifier on fields and functions unless necessary. Prefer `access(self)`, `acccess(Entitlement)`, or `access(contract)` and `access(account)` when other types in the contract or account need to have access. + + + +[Cadence Anti-Patterns]: https://cadence-lang.org/docs/design-patterns +[References]: https://cadence-lang.org/docs/language/references +[account storage]: https://cadence-lang.org/docs/language/accounts#account-storage +[borrow]: https://cadence-lang.org/docs/language/capabilities +[don't use Account references]: https://cadence-lang.org/docs/anti-patterns#avoid-using-authaccount-as-a-function-parameter +[public capability storage]: https://cadence-lang.org/docs/language/capabilities +[restricted types and interfaces]: https://cadence-lang.org/docs/language/restricted-types +[`access(all)`]: https://cadence-lang.org/docs/language/access-control +[transactions]: https://cadence-lang.org/docs/language/transactions \ No newline at end of file diff --git a/docs/build/cadence/smart-contracts/deploying.md b/docs/build/cadence/smart-contracts/deploying.md index c62321b18a..d726824269 100644 --- a/docs/build/cadence/smart-contracts/deploying.md +++ b/docs/build/cadence/smart-contracts/deploying.md @@ -25,43 +25,43 @@ keywords: # Deploying Contracts -Deploying smart contracts to Flow's networks is the final step in bringing your blockchain application to life. This guide covers everything you need to know to deploy your Cadence contracts to both Flow Testnet and Mainnet, from account creation to contract updates. +Deploying smart contracts to Flow's networks is the final step for you to bring your blockchain application to life. This guide covers everything you need to know to deploy your Cadence contracts to both Flow Testnet and Mainnet, from account creation to contract updates. -## What You'll Learn +## What you'll learn -After completing this guide, you'll be able to: +After you complete this guide, you'll be able to: -- **Create and fund accounts** on Flow Testnet and Mainnet -- **Deploy contracts** using Flow CLI with proper configuration -- **Update existing contracts** while preserving their addresses -- **Understand the differences** between testnet and mainnet deployment -- **Follow security best practices** for production deployments +- **Create and fund accounts** on Flow Testnet and Mainnet. +- **Deploy contracts** with Flow CLI with proper configuration. +- **Update current contracts** and preserve their addresses. +- **Understand the differences** between testnet and mainnet deployment. +- **Follow security best practices** for production deployments. ## Prerequisites -Before deploying contracts, make sure you have: +Before you deploy contracts, make sure you have: -- **Flow CLI installed** and configured -- **A Flow project** with contracts ready for deployment -- **Basic understanding** of Cadence smart contracts -- **Completed testing** of your contracts locally +- **Flow CLI installed** and configured. +- **A Flow project** with contracts ready for deployment. +- **Basic understanding** of Cadence smart contracts. +- **Completed testing** of your contracts locally. ## Deployment Workflow The recommended deployment workflow follows this progression: -1. **Emulator Deployment** - Deploy and test your contracts locally (free, instant) -2. **Testnet Deployment** - Deploy and test your contracts on Flow Testnet (free) -3. **Mainnet Deployment** - Deploy to Flow Mainnet once testing is complete (costs FLOW tokens) -4. **Contract Updates** - Update contracts as needed using the update command +1. **Emulator Deployment** - Deploy and test your contracts locally (free, instant). +2. **Testnet Deployment** - Deploy and test your contracts on Flow Testnet (free). +3. **Mainnet Deployment** - Deploy to Flow Mainnet after testing is complete (costs FLOW tokens). +4. **Contract Updates** - Update contracts as needed with the `update` command. -This approach ensures your contracts work correctly before committing real resources to mainnet deployment. +This approach ensures your contracts work correctly before you commit real resources to mainnet deployment. -## Deploy to Emulator +## Deploy to emulator The Flow Emulator is your local development environment where you can deploy and test contracts instantly without any network costs or delays. This is the first step in your deployment journey. -### Start the Emulator +### Start the emulator First, start the [Flow Emulator]. In a second terminal: @@ -69,7 +69,7 @@ First, start the [Flow Emulator]. In a second terminal: flow emulator start ``` -### Create an Emulator Account +### Create an emulator account Create a local account for testing: @@ -84,7 +84,7 @@ When prompted: This creates a new account on the emulator and adds it to your `flow.json` configuration. -### Configure Emulator Deployment +### Configure emulator deployment Update your `flow.json` to include emulator deployment configuration: @@ -111,7 +111,7 @@ Your `flow.json` will now include an emulator deployment section: } ``` -### Deploy Contract to Emulator +### Deploy contract to emulator Deploy your contract to the local emulator: @@ -139,9 +139,9 @@ YourContract -> 0xf8d6e0586b0a20c7 (contract deployed successfully) 🎉 All contracts deployed successfully ``` -### Test Your Emulator Deployment +### Test your emulator deployment -Verify your contract works by running scripts and transactions: +Verify your contract works via these scripts and transactions: ```zsh # Run a script to read contract state @@ -164,7 +164,7 @@ For a more complete quickstart, visit the [Getting Started] guide. - You should test your contracts, transactions and scripts on Testnet, have strong smart contract test coverage and follow the additional guidelines set out here: [Smart Contract Testing Guidelines]. - Use `flow init` to [Create a Project] if you need one to practice deployment with. -### Create a Testnet Account +### Create a Testnet account First, you'll need a testnet account to deploy your contracts. Create one with: @@ -183,15 +183,15 @@ When prompted: 1. **Account name**: Enter `testnet-account` 2. Select `testnet` as the network when prompted -This creates a new account on testnet and adds it to your `flow.json` configuration. It also saves the private key for the new account in `.pkey` and uses this file to import the key because `flow.json` will be visible in the repo. +This creates a new account on testnet and adds it to your `flow.json` configuration. It also saves the private key for the new account in `.pkey` and uses this file to import the key because `flow.json` is visible in the repo. :::danger -As with any other blockchain network, **anyone** with access to the private key for an account can access that account at any time without you knowing. +As with any other blockchain network, **anyone** with access to the private key for an account can access that account at any time without your knowledge. ::: -### Fund Your Testnet Account +### Fund your Testnet account To deploy contracts and send transactions on testnet, you need FLOW tokens. Flow provides a faucet service to get free testnet tokens. @@ -201,10 +201,10 @@ flow accounts fund testnet-account This will open the faucet in your browser. You can also navigate there manually. -1. Visit the [Testnet Faucet] -2. Enter your testnet account address -3. Complete any required verification (captcha, etc.) -4. Request tokens (you'll receive 100000 testnet FLOW tokens) +1. Visit the [Testnet Faucet]. +2. Enter your testnet account address. +3. Complete any required verification (captcha, and so on). +4. Request tokens (you'll receive 100000 testnet FLOW tokens). Check your account balance: @@ -214,7 +214,7 @@ flow accounts list You will see your account details with a balance of FLOW tokens. -### Configure Testnet Deployment +### Configure Testnet deployment Update your `flow.json` to include testnet deployment configuration: @@ -241,7 +241,7 @@ Your `flow.json` will now include a testnet deployment section: } ``` -### Deploy Contract to Testnet +### Deploy contract to Testnet Deploy your contract to the public testnet: @@ -261,9 +261,9 @@ YourContract -> 0x9942a81bc6c3c5b7 (contract deployed successfully) ## Deploy to Mainnet -Once you've successfully tested your contracts on testnet, you can deploy to mainnet. You'll need a mainnet account with real FLOW tokens. +After you've successfully tested your contracts on testnet, you can deploy to mainnet. You'll need a mainnet account with real FLOW tokens. -### Create a Mainnet Account +### Create a Mainnet account For mainnet, you'll need to acquire FLOW tokens through exchanges or other means, as there's no faucet. @@ -276,11 +276,11 @@ When prompted: 1. **Account name**: Enter `mainnet-account` 2. **Select "Mainnet" Network** -### Acquire FLOW Tokens +### Acquire FLOW tokens You can purchase FLOW tokens from major exchanges. Make sure your mainnet account has sufficient FLOW tokens to cover deployment costs. Flow is a very efficient network, so even 1.0 FLOW is sufficient to deploy large numbers of contracts. -### Configure Mainnet Deployment +### Configure Mainnet deployment Add mainnet deployment configuration to your `flow.json`: @@ -295,7 +295,7 @@ Follow the prompts: 3. **Contract**: `YourContract` 4. **Deploy more contracts**: `no` (or `yes` if you have multiple contracts) -Your `flow.json` should now include mainnet configuration: +Your `flow.json` will now include mainnet configuration: ```json { @@ -317,11 +317,11 @@ flow project deploy --network mainnet :::warning -This deployment costs (a relatively small amount of) real FLOW tokens and cannot be undone. You can however redeploy your contracts to update them, or delete them. +This deployment costs (a relatively small amount of) real FLOW tokens and you cannot undo it. You can, however, redeploy your contracts to update them, or delete them. ::: -You should see output similar to: +You will see output similar to: ```zsh Deploying 1 contracts for accounts: mainnet-account @@ -339,11 +339,12 @@ All your contract deployment addresses are stored in `flow.json`. Mainnet, Testn ## Deploy updated contracts on mainnet -Contracts can be updated and retain the contract address. You can use the [Flow CLI contract update command] to redeploy an updated version of your contract: +You can update contracts and retain the contract address. To do this, use the [Flow CLI contract update command] to redeploy an updated version of your contract: ```zsh flow accounts update-contract ./YourContract.cdc --signer mainnet-account --network mainnet ``` + [Flow CLI]: ../../../build/tools/flow-cli/install [Getting Started]: ../../../blockchain-development-tutorials/cadence/getting-started/smart-contract-interaction diff --git a/docs/build/cadence/smart-contracts/overview.md b/docs/build/cadence/smart-contracts/overview.md index 5e806cfc7a..f50a2c8fe9 100644 --- a/docs/build/cadence/smart-contracts/overview.md +++ b/docs/build/cadence/smart-contracts/overview.md @@ -23,77 +23,97 @@ keywords: - decentralized apps --- -At its core, a decentralized application is defined by the [smart contracts](https://en.wikipedia.org/wiki/Smart_contract) it uses on the blockchain. Rather than relying on centralized application servers and databases, apps model their core application logic using smart contracts, often referred to as the "onchain" code. +# Smart Contracts on Flow + +At its core, a decentralized application is defined by the [smart contracts] it uses on the blockchain. Rather than rely on centralized application servers and databases, apps model their core application logic with smart contracts, often referred to as the "onchain" code. It is therefore helpful to develop a clear model for your app that takes into account the data and logic that will exist in your smart contracts. In particular, it is important to differentiate between the parts of your app that must live on chain and those that should live off chain. -## How to Write Smart Contracts on Flow +## How to write smart contracts on Flow -Smart contracts on the Flow blockchain are implemented in [Cadence](https://github.com/onflow/cadence), a resource-oriented programming language specifically designed for smart contract development. +Smart contracts on the Flow blockchain are implemented in [Cadence], a resource-oriented programming language specifically designed for smart contract development. ### Onboard to Cadence -To get started with Cadence, we recommended covering the introductory tutorials available in the [Flow Playground](https://play.flow.com/), a simple web IDE designed for learning Cadence. +To get started with Cadence, we recommended that you cover the introductory tutorials available in the [Flow Playground], a simple web IDE designed for you to learn Cadence. -### Configure Your Local Environment +### Configure your local environment To build confidently, you will want to set up the appropriate local environment and have an adequate test suite to ensure your smart contracts operate as intended. To do this, familiarize yourself with the following tools: -- [Flow CLI](../../../build/tools/flow-cli/index.md): A utility to directly interact with the chain and manage accounts and contracts. -- [Flow Emulator](../../../build/tools/emulator/index.md): A lightweight server that simulates the Flow blockchain (strongly recommended during development). -- [Flow Dev Wallet](https://github.com/onflow/fcl-dev-wallet/): A utility to simulate user wallets in development. -- [Visual Studio Code Extension](../../../build/tools/vscode-extension/index.md): An IDE integration for developing smart contracts. +- [Flow CLI]: A utility to directly interact with the chain and manage accounts and contracts. +- [Flow Emulator] A lightweight server that simulates the Flow blockchain (strongly recommended during development). +- [Flow Dev Wallet] A utility to simulate user wallets in development. +- [Visual Studio Code Extension] An IDE integration used to develop smart contracts. -## Storing Data on Flow +## Store data on Flow -All apps will store important data on the blockchain, and some more than others -- especially NFT apps. You'll want to consider the following when storing data on the Flow blockchain. +All apps will store important data on the blockchain, and some more than others -- especially NFT apps. You'll want to consider the following when you store data on the Flow blockchain. ### What does your data need to represent? Permanence is a key property of blockchains; users trust that the data they store will continue to exist for years to come, and this is a defining characteristic of assets like NFTs. Therefore, well-designed digital assets store the information necessary to retain their value without external dependencies. -### Storage Limits & Fees +### Storage limits and fees + +However, there are practical constraints to data storage on a blockchain. Developer and user accounts must retain a small amount of FLOW tokens, known as the storage fee, for bytes of data stored in their accounts. The minimum storage fee will grant each account a minimum storage amount. If an account holds assets that demand more bytes of storage, the account will need to retain more FLOW tokens to increase the storage amount according to Flow's [fee schedule]. A more compact data model can keep storage needs down. -However, there are practical constraints to storing data on a blockchain. Developer and user accounts must retain a small amount of FLOW tokens, known as the storage fee, for bytes of data stored in their accounts. The minimum storage fee will grant each account a minimum storage amount. If an account holds assets that demand more bytes of storage, the account will need to retain more FLOW tokens to increase the storage amount according to Flow's [fee schedule](../basics/fees.md#storage). A more compact data model can keep storage needs down. \ - \ Furthermore, a single Flow transaction has a size limit of 4MB, which limits the rate at which large amounts of data can be transferred to the blockchain. Lastly, a blockchain is not a content delivery network and therefore cannot serve media assets, such as videos, at the speeds expected by modern applications. -For these reasons, it usually isn't practical to store large media assets such as videos and high-definition images on the Flow blockchain. Instead, consider using an external storage solution. +For these reasons, it usually isn't practical to store large media assets such as videos and high-definition images on the Flow blockchain. Instead, consider an external storage solution. -### External Storage Networks +### External storage networks -Decentralized storage networks such as IPFS allow you to store large digital assets off chain, but without relying on centralized servers. Rather than saving an entire asset to the Flow blockchain, you can save the content hash (known as a CID on IPFS) on the blockchain and then store the source file off-chain. This way, users can verify that the media file matches the digital asset. +Decentralized storage networks such as IPFS allow you to store large digital assets off chain, but with no need to rely on centralized servers. Instead of save an entire asset to the Flow blockchain, you can save the content hash (known as a CID on IPFS) on the blockchain and then store the source file off-chain. This way, users can verify that the media file matches the digital asset. -IPFS files can be uploaded via a pinning service such as Pinata; see their [NFT tutorial](https://medium.com/pinata/how-to-create-nfts-like-nba-top-shot-with-flow-and-ipfs-701296944bf) for an example of how to use Pinata with Flow. +IPFS files can be uploaded via a pinning service such as Pinata; see their [NFT tutorial] for an example of how to use Pinata with Flow. -It's worth noting that IPFS files are served through [gateways](https://docs.ipfs.io/concepts/ipfs-gateway/), many of which leverage caching to provide fast response times. Cloudflare provides a [public IPFS Gateway](https://developers.cloudflare.com/distributed-web/ipfs-gateway), and Pinata also supports [dedicated gateways with custom domains](https://medium.com/pinata/announcing-dedicated-ipfs-gateways-60f599949ce). +IPFS files are served through [gateways], many of which leverage caching to provide fast response times. Cloudflare provides a [public IPFS Gateway], and Pinata also supports [dedicated gateways with custom domains]. -## Using Existing Standards +## Use current standards -The Flow blockchain has existing smart contract standards for both fungible and non-fungible tokens that you should implement when building your contracts. +The Flow blockchain has smart contract standards for both fungible and non-fungible tokens that you should implement when you build your contracts. ### Non-Fungible Tokens (NFTs) -All NFTs on the Flow blockchain implement the [NonFungibleToken](../core-contracts/08-non-fungible-token.md) interface, allowing them to be compatible with wallets, marketplaces and other cross-app experiences. +All NFTs on the Flow blockchain implement the [NonFungibleToken] interface, which allows them to be compatible with wallets, marketplaces and other cross-app experiences. -See the [NFT Guide](../../../blockchain-development-tutorials/tokens/nft-cadence.md) for a guide on how to create a basic NFT contract -that conforms to the standard. +See the [NFT Guide] for a guide on how to create a basic NFT contract that conforms to the standard. -- [Non-Fungible Token (NFT) contract interface](../core-contracts/08-non-fungible-token.md) +- [NonFungibleToken] (NFT) contract interface -### NFT Sales and Trading +### NFT sales and trading Flow has a standard contract to facilitate both the direct sales and peer-to-peer trading of NFTs. The NFT storefront contract is useful for apps that want to provide an NFT marketplace experience. -- [NFT Storefront contract](https://github.com/onflow/nft-storefront) +- [NFT Storefront contract] ### Fungible Tokens -Fungible tokens (i.e. coins, currencies) on the Flow blockchain, including the default cryptocurrency token FLOW, implement the [FungibleToken](../core-contracts/02-fungible-token.md) interface. - -See the [FT Guide](../../../blockchain-development-tutorials/tokens/fungible-token-cadence.md) for a guide on how to create a basic fungible token -contract that conforms to the standard. - -- [Fungible Token contract interface](../core-contracts/02-fungible-token.md) +Fungible tokens (that is, coins, currencies) on the Flow blockchain, which includes the default cryptocurrency token FLOW, implement the [FungibleToken] interface. + +See the [FT Guide] for a guide on how to create a basic fungible token contract that conforms to the standard. + +- [FungibleToken] contract interface: + + + +[smart contracts]: https://en.wikipedia.org/wiki/Smart_contract +[Cadence]: https://github.com/onflow/cadence +[Flow Playground]: https://play.flow.com/ +[Flow CLI]: ../../../build/tools/flow-cli/index.md +[Flow Emulator]: ../../../build/tools/emulator/index.md +[Flow Dev Wallet]: https://github.com/onflow/fcl-dev-wallet/ +[Visual Studio Code Extension]: ../../../build/tools/vscode-extension/index.md +[fee schedule]: ../basics/fees.md#storage +[NFT tutorial]: https://medium.com/pinata/how-to-create-nfts-like-nba-top-shot-with-flow-and-ipfs-701296944bf +[gateways]: https://docs.ipfs.io/concepts/ipfs-gateway/ +[public IPFS Gateway]: https://developers.cloudflare.com/distributed-web/ipfs-gateway +[dedicated gateways with custom domains]: https://medium.com/pinata/announcing-dedicated-ipfs-gateways-60f599949ce +[NonFungibleToken]: ../core-contracts/08-non-fungible-token.md +[NFT Guide]: ../../../blockchain-development-tutorials/tokens/nft-cadence.md +[NFT Storefront contract]: https://github.com/onflow/nft-storefront +[FungibleToken]: ../core-contracts/02-fungible-token.md +[FT Guide]: ../../../blockchain-development-tutorials/tokens/fungible-token-cadence.md \ No newline at end of file diff --git a/docs/build/cadence/smart-contracts/testing-strategy.md b/docs/build/cadence/smart-contracts/testing-strategy.md index 420ca430d2..d17762e914 100644 --- a/docs/build/cadence/smart-contracts/testing-strategy.md +++ b/docs/build/cadence/smart-contracts/testing-strategy.md @@ -31,51 +31,51 @@ keywords: # Testing Smart Contracts -A single, pragmatic strategy for testing on Flow. Use layers that are deterministic and isolated by default, add realism with forks when needed, and keep a minimal set of live network checks before release. +This document describes a single, pragmatic strategy to test on Flow. Use layers that are deterministic and isolated by default, add realism with forks when needed, and keep a minimal set of live network checks before release. ## At a glance -- **Unit & Property — Test Framework**: Hermetic correctness and invariants -- **Integration — Fork Testing**: Real contracts and data; mutations stay local -- **Local integration sandbox (interactive, `flow emulator --fork`)**: Drive apps/E2E against production-like state -- **Staging (testnet)**: Final plumbing and config checks -- **Post-deploy (read-only)**: Invariant dashboards and alerts +- **Unit & Property — Test Framework**: Hermetic correctness and invariants. +- **Integration — Fork Testing**: Real contracts and data; mutations stay local. +- **Local integration sandbox (interactive, `flow emulator --fork`)**: Drive apps/E2E against production-like state. +- **Staging (testnet)**: Final plumbing and config checks. +- **Post-deploy (read-only)**: Invariant dashboards and alerts. ## Layers -### Unit & Property — Test Framework +### Unit and property — test framework - Use `flow test` -- **Use when**: Validating Cadence logic, invariants, access control, error paths, footprint -- **Why**: Fully deterministic and isolated; highest-regression signal -- **Run**: Every commit/PR; wide parallelism -- **Notes**: Write clear success/failure tests, add simple “this should always hold” rules when helpful, and avoid external services +- **Use when**: You validate Cadence logic, invariants, access control, error paths, footprint. +- **Why**: Fully deterministic and isolated; highest-regression signal. +- **Run**: Every commit/PR; wide parallelism. +- **Notes**: Write clear success andfailure tests, add simple “this should always hold” rules when helpful, and avoid external services. See also: [Running Cadence Tests]. -### Integration — Fork Testing +### Integration — fork testing -- **Use when**: Interacting with real on-chain contracts/data (FT/NFT standards, AMMs, wallets, oracles, bridges), upgrade checks, historical repro -- **Why**: Real addresses, capability paths, and resource schemas; catches drift early -- **Run**: On PRs, run the full forked suite if practical (pinned), or a small quick set; run more cases nightly or on main -- **How**: Configure with `#test_fork(network: "mainnet", height: nil)` in your test file, or use `flow test --fork` CLI flags +- **Use when**: You interact with real on-chain contracts or data (FTand NFT standards, AMMs, wallets, oracles, bridges), upgrade checks, historical repro. +- **Why**: Real addresses, capability paths, and resource schemas; catches drift early. +- **Run**: On Pull Requests (PRs), run the full forked suite if practical (pinned), or a small quick set; run more cases nightly or on main. +- **How**: Configure with `#test_fork(network: "mainnet", height: nil)` in your test file, or use `flow test --fork` CLI flags. - **Notes**: - - Pin with `height: 85432100` in the pragma (or `--fork-height` CLI flag) where reproducibility matters - - Prefer local deployment + impersonation over real mainnet accounts - - Mutations are local to the forked runtime; the live network is never changed - - Be mindful of access-node availability and rate limits - - External oracles/protocols: forked tests do not call off-chain services or other chains; mock these or run a local stub + - Pin with `height: 85432100` in the pragma (or `--fork-height` CLI flag) where reproducibility matters. + - Prefer local deployment + impersonation over real mainnet accounts. + - Mutations are local to the forked runtime; the live network is never changed. + - Be mindful of access-node availability and rate limits. + - External oracles and protocols: forked tests do not call off-chain services or other chains; mock these or run a local stub. See also: [Fork Testing with Cadence], [Fork Testing Flags]. -### Local Integration Sandbox — `flow emulator --fork` +### Local integration sandbox — `flow emulator --fork` -- **Use when**: Driving dapps, wallets, bots, indexers, or exploratory debugging outside the test framework -- **Why**: Production-like state with local, disposable control; great for E2E and migrations -- **Run**: Dev machines and focused E2E CI jobs +- **Use when**: You drive dApps, wallets, bots, indexers, or exploratory debugging outside the test framework. +- **Why**: Production-like state with local, disposable control; great for end to end (E2E) and migrations. +- **Run**: Dev machines and focused E2E CI jobs. - **Notes**: - Pin height; run on dedicated ports; impersonation is built-in; mutations are local; off-chain/oracle calls are not live—mock or run local stubs - - What to run: Manual exploration and debugging of flows against a forked state; frontend connected to the emulator (e.g., `npm run dev` pointed at `http://localhost:8888`); automated E2E/FE suites (e.g., Cypress/Playwright) against the local fork; headless clients, wallets/bots/indexers, and migration scripts + - What to run: Manual exploration and debugging of flows against a forked state; frontend connected to the emulator (for example, `npm run dev` pointed at `http://localhost:8888`); automated E2E/FE suites (for example, Cypress or Playwright) against the local fork; headless clients, wallets/bots/indexers, and migration scripts. - Not for the canonical Cadence test suite—prefer fork testing with `flow test` for scripted Cadence tests (see [Fork Testing Flags] and [Running Cadence Tests]) Quick start example: @@ -110,12 +110,12 @@ See also: [Flow Emulator]. ### Staging — Testnet -- **Use when**: Final network plumbing and configuration checks before release -- **Why**: Validates infra differences you cannot fully simulate -- **Run**: Pre-release and on infra changes +- **Use when**: Final network plumbing and configuration checks before release. +- **Why**: Validates infra differences you cannot fully simulate. +- **Run**: Pre-release and on infra changes. - **Notes**: - - Keep canaries minimal and time-boxed; protocol/partner support may be limited on testnet (not all third-party contracts are deployed or up to date) - - What to run: Minimal app smoke tests (login/auth, key flows, mint/transfer, event checks); frontend connected to Testnet with a small Cypress/Playwright smoke set; infra/config checks (endpoints, contract addresses/aliases, env vars, service/test accounts) + - Keep canaries minimal and time-boxed; protocol and partner support may be limited on testnet (not all third-party contracts are deployed or up to date). + - What to run: Minimal app smoke tests (login and auth, key flows, mint and transfer, event checks); frontend connected to Testnet with a small Cypress/Playwright smoke set; infra or config checks (endpoints, contract addresses oraliases, env vars, service or test accounts) - Not for the canonical Cadence test suite — prefer fork testing with `flow test` for scripted tests (see [Fork Testing Flags] and [Running Cadence Tests]) Quick start example: @@ -145,43 +145,43 @@ See also: [Flow Emulator]. See also: [Flow Networks]. -### Post-deploy Monitoring (read-only) +### Post-deploy monitoring (read-only) -- **Use when**: After releases to confirm invariants and event rates -- **Why**: Detects real-world anomalies quickly -- **Run**: Continuous dashboards/alerts tied to invariants +- **Use when**: After releases to confirm invariants and event rates. +- **Why**: Detects real-world anomalies quickly. +- **Run**: Continuous dashboards and alerts tied to invariants. ## Reproducibility and data management - **Pin where reproducibility matters**: Use `--fork-height ` for both `flow test --fork` and `flow emulator --fork`. Pins are per‑spork; historical data beyond spork boundaries is unavailable. For best results, keep a per‑spork stable pin and also run a "latest" freshness job. -- **Named snapshots**: Maintain documented pin heights (e.g., in CI vars or a simple file) with names per dependency/protocol +- **Named snapshots**: Maintain documented pin heights (for example, in CI vars or a simple file) with names per dependency or protocol - **Refresh policy**: Advance pins via a dedicated “freshness” PR; compare old vs. new pins -- **Goldens**: Save a few canonical samples (e.g., event payloads, resource layouts, key script outputs) as JSON in your repo, and compare them in CI to catch accidental schema/shape changes. Update the samples intentionally as part of upgrades. +- **Goldens**: Save a few canonical samples (for example, event payloads, resource layouts, key script outputs) as JSON in your repo, and compare them in CI to catch accidental schema/shape changes. Update the samples intentionally as part of upgrades. ## CI tips -- PRs: Run emulator unit/property and forked integration (pinned). Full suite is fine if practical; otherwise a small quick set. +- PRs: Run emulator unit or property and forked integration (pinned). Full suite is fine if practical; otherwise a small quick set. - Nightly/Main: Add a latest pin job and expand fork coverage as needed. - E2E (optional): Use `flow emulator --fork` at a stable pin and run your browser tests. ## Test selection and tagging -- **Optional naming helpers**: Use simple suffixes in test names like `_fork`, `_smoke`, `_e2e` if helpful -- Run the tests you care about by passing files/directories: `flow test FILE1 FILE2 DIR1 ...` (most common) -- Optionally, use `--name ` to match test functions when it’s convenient -- **Defaults**: PRs can run the full fork suite (pinned) or a small quick set; nightly runs broader coverage (+ optional E2E) +- **Optional naming helpers**: Use simple suffixes in test names like `_fork`, `_smoke`, `_e2e` if helpful. +- Pass files and directories to run the tests you care about: `flow test FILE1 FILE2 DIR1 ...` (most common). +- Optionally, use `--name ` to match test functions when it’s convenient. +- **Defaults**: PRs can run the full fork suite (pinned) or a small quick set; nightly runs broader coverage (and optional E2E). ## Troubleshooting tips - Re-run at the same `--fork-height`, then at latest - Compare contract addresses/aliases in `flow.json` -- Diff event/resource shapes against your stored samples -- Check access-node health and CI parallelism/sharding +- Diff event or resource shapes against your stored samples +- Check access-node health and CI parallelism or sharding -## Do / Don’t +## Dos and Don’ts -- **Do**: Keep a fast, hermetic base; pin forks; tag tests; maintain tiny PR smoke sets; document pins and set a simple refresh schedule (e.g., after each spork or monthly) -- **Don't**: Make "latest" your default in CI; create or rely on real mainnet accounts; conflate fork testing (`flow test`) with the emulator's fork mode (`flow emulator --fork`) +- **Do**: Keep a fast, hermetic base; pin forks; tag tests; maintain tiny PR smoke sets; document pins and set a simple refresh schedule (for example, after each spork or monthly). +- **Don't**: Make "latest" your default in CI; create or rely on real mainnet accounts; conflate fork testing (`flow test`) with the emulator's fork mode (`flow emulator --fork`). ## Related docs diff --git a/docs/build/cadence/smart-contracts/testing.md b/docs/build/cadence/smart-contracts/testing.md index 271d345879..81739308b7 100644 --- a/docs/build/cadence/smart-contracts/testing.md +++ b/docs/build/cadence/smart-contracts/testing.md @@ -19,18 +19,20 @@ keywords: Testing is an essential part of smart contract development to ensure the correctness and reliability of your code. The Cadence Testing Framework provides a convenient way to write tests for your contracts, scripts and transactions which allows you to verify the functionality and correctness of your smart contracts. :::info + Looking for high‑level guidance on when to use emulator, forks, or testnet? See [Testing Smart Contracts](./testing-strategy.md). + ::: ## Install Flow CLI -The [Flow CLI] is the primary tool for developing, testing, and deploying smart contracts to the Flow network. +The [Flow CLI] is the primary tool for you to develop, test, and deploy smart contracts to the Flow network. If you haven't installed the Flow CLI yet and have [homebrew](https://brew.sh/) installed, simply run `brew install flow-cli`. Alternatively, refer to the Flow CLI [installation instructions]. ## Create a new project -In your preferred code editor, create a new directory for your project and navigate to it in the terminal. Then initialize a new Flow project by running the command `flow init`. This will create a `flow.json` config file that contains the [project's configuration]. +In your preferred code editor, create a new directory for your project and navigate to it in the terminal. Then initialize a new Flow project with the `flow init` command. This will create a `flow.json` config file that contains the [project's configuration]. ```bash mkdir test-cadence @@ -132,7 +134,7 @@ This code: - defines two test cases: `testAdd()` and `testSubtract()` - calls `add()` and `subtract()` methods with different input values respectively. -## Running the test cases +## Run the test cases To run the test cases, use the following command in the terminal: @@ -140,7 +142,7 @@ To run the test cases, use the following command in the terminal: flow test --cover --covercode="contracts" calculator_test.cdc ``` -This command uses the Flow CLI to run the test cases and display the output. You should see the following output: +This command uses the Flow CLI to run the test cases and display the output. You will see the following output: ```bash Test results: "calculator_test.cdc" @@ -149,7 +151,7 @@ Test results: "calculator_test.cdc" Coverage: 66.7% of statements ``` -This output indicates that both test cases ran successfully, and the two smart contract methods are functioning as expected. With the supplied flags (`--cover` & `--covercode="contracts"`), we also get code coverage insights for the contracts under testing. The code coverage percentage is `66.7%`, because we have not added a test case for the `multiply` method. By viewing the auto-generated `coverage.json` file, we see: +This output indicates that both test cases ran successfully, and the two smart contract methods work as expected. With the supplied flags (`--cover` & `--covercode="contracts"`), we also get code coverage insights for the contracts under testing. The code coverage percentage is `66.7%`, because we have not added a test case for the `multiply` method. When we view the auto-generated `coverage.json` file, we see: ```json { @@ -176,7 +178,7 @@ return a * b which is the `multiply` method. -By adding a test case for the above method: +When we add a test case for the above method: ```cadence calculator_test.cdc ... @@ -199,21 +201,21 @@ Test results: "calculator_test.cdc" Coverage: 100.0% of statements ``` -## Advanced Testing Techniques +## Advanced testing techniques -The Cadence testing framework provides various features and techniques for writing comprehensive test scenarios. Some of these include: +The Cadence testing framework provides various features and techniques used to write comprehensive test scenarios. Some of these include: -- [**Code Coverage**](https://github.com/m-Peter/flow-code-coverage): You can use the `--cover` flag with the `flow test` command to view code coverage results when running your tests. This allows you to identify areas of your code that are not adequately covered by your test inputs. -- **Test Helpers**: Test helpers are reusable functions that help you set up the initial state for your test files. You can define test helpers in a Cadence program and use them in your test files by importing it whenever needed. -- [**Assertions**](https://cadence-lang.org/docs/testing-framework#assertions): The testing framework provides built-in assertion functions, such as `assertEqual`, `beNil`, `beEmpty`, `contain`, to help you verify the expected behavior of your smart contracts. +- [**Code Coverage**]: You can use the `--cover` flag with the `flow test` command to view code coverage results when you run your tests. This allows you to identify areas of your code that are not adequately covered by your test inputs. +- **Test Helpers**: Test helpers are reusable functions that help you set up the initial state for your test files. You can define test helpers in a Cadence program and use them in your test files by importing it whenever you need it. +- [**Assertions**]: The testing framework provides built-in assertion functions, such as `assertEqual`, `beNil`, `beEmpty`, `contain`, to help you verify the expected behavior of your smart contracts. - **Test Suites**: You can organize your test files into test suites to improve the readability and maintainability of your test code. Test suites allow you to group related test cases and set up common test helpers for all the tests in the suite. -- [**Integration tests**](https://github.com/bjartek/overflow): In our previous example, we would directly call the available methods on the contract under test. This is generally categorized as unit testing. You can also write integration tests, by executing scripts & transactions to interact with the contracts under testing. If you would like to write your tests in Go, instead of Cadence, you can use [Overflow tool](https://github.com/bjartek/overflow) to run integration tests against either an local emulator, testnet, mainnet or an in memory instance of the flow-emulator. +- [**Integration tests**]: In our previous example, we would directly call the available methods on the contract under test. This is generally categorized as unit testing. You can also write integration testswhen you execute scripts and transactions to interact with the contracts under testing. If you would like to write your tests in Go, instead of Cadence, you can use [Overflow tool] to run integration tests against either an local emulator, testnet, mainnet or an in memory instance of the flow-emulator. -By leveraging these advanced testing techniques, you can write more robust and reliable smart contracts in Cadence. In this example, we set up a basic testing environment, wrote a simple smart contract in Cadence, and created a test file to verify its functionality. We then used the Flow CLI to run the test file and confirm that the smart contract is working correctly. +When you leverage these advanced testing techniques, you can write more robust and reliable smart contracts in Cadence. In this example, we set up a basic testing environment, wrote a simple smart contract in Cadence, and created a test file to verify its functionality. We then used the Flow CLI to run the test file and confirm that the smart contract works correctly. -This is a basic example, and there are many more advanced features and techniques you can explore when working with the Cadence Testing Framework. +This is a basic example, and there are many more advanced features and techniques you can explore when you work with the Cadence Testing Framework. -For more in-depth tutorials and documentation, refer to the official [Cadence language documentation](https://cadence-lang.org/) and the [Flow CLI documentation]. +For more in-depth tutorials and documentation, refer to the official [Cadence language documentation] and the [Flow CLI documentation]. ## Testing Requirements @@ -226,25 +228,24 @@ It is suggested to follow the following best practices: Make sure you test all contracts - and the integration into your application extensively before proceeding to the mainnet. You should aim to replicate all conditions as closely as possible to the usage patterns on mainnet. -## Writing Tests +## Write Tests -There are official SDKs/frameworks for Flow in Cadence, Go and JavaScript. +There are official SDKsand frameworks for Flow in Cadence, Go and JavaScript. -In all three cases, the test code will need to deploy the contracts, configure accounts to interact with them and send transactions to them. It will then have to wait for the transactions to be sealed and check the results by catching exceptions, checking for events, and querying state using scripts. +In all three cases, the test code will need to deploy the contracts, configure accounts to interact with them and send transactions to them. It will then have to wait for the transactions to be sealed and check the results. To do this, it catches exceptions, checks for events, and querys state via scripts. ### Cadence tests -Cadence comes with built-in support for code coverage, as well as a native testing framework which allows developers to write their tests using Cadence. -This framework is bundled with the [Flow CLI] tool, which includes a dedicated command for running tests (`flow test`). +Cadence comes with built-in support for code coverage, as well as a native testing framework which allows developers to write their tests with Cadence. This framework is bundled with the [Flow CLI] tool, which includes a dedicated command to run tests (`flow test`). -You can find examples of Cadence tests in the following projects: [hybrid-custody](https://github.com/onflow/hybrid-custody/tree/main/test), [flow-nft](https://github.com/onflow/flow-nft/tree/master/tests), [flow-ft](https://github.com/onflow/flow-ft/tree/master/tests). -Visit the [documentation](https://cadence-lang.org/docs/testing-framework) to view all the available features. +You can find examples of Cadence tests in the following projects: [hybrid-custody], [flow-nft], [flow-ft]. +Visit the [Cadence documentation] to view all the available features. -The [Hybrid Custody](https://github.com/onflow/hybrid-custody#readme) project is a prime example which utilizes both the Cadence testing framework and code coverage in its CI. +The [Hybrid Custody] project is a prime example which utilizes both the Cadence testing framework and code coverage in its CI. ![Hybrid Custody CI](./hybrid-custody-ci.png) -There is also a [repository](https://github.com/m-Peter/flow-code-coverage#readme) which contains some sample contracts and their tests. +There is also a [repository] which contains some sample contracts and their tests. ![Automated CI Coverage Report](./codecov-in-pr.png) @@ -260,12 +261,12 @@ For running tests against a fork of mainnet/testnet, see the dedicated tutorial: ## References -- [Reference documentation for Cadence testing](https://cadence-lang.org/docs/testing-framework) -- [Overflow](https://github.com/bjartek/overflow) is a powerful Golang-based DSL for efficient testing and execution of blockchain interactions -- projects that have good examples of robust test cases: - - [hybrid-custody](https://github.com/onflow/hybrid-custody/tree/main/test), - - [flow-nft](https://github.com/onflow/flow-nft/tree/master/tests), - - [flow-ft](https://github.com/onflow/flow-ft/tree/master/tests). +- [Cadence documentation] for testing. +- [Overflow tool] is a powerful Golang-based DSL for efficient testing and execution of blockchain interactions +- Projects that have good examples of robust test cases: + - [hybrid-custody] + - [flow-nft] + - [flow-ft] [Testing Strategy on Flow]: ./testing-strategy.md @@ -276,4 +277,15 @@ For running tests against a fork of mainnet/testnet, see the dedicated tutorial: [Network Upgrade (Spork) Process]: ../../../protocol/node-ops/node-operation/network-upgrade.md [Fork Testing Flags]: ../../tools/flow-cli/tests.md#fork-testing-flags [Flow Emulator]: ../../tools/emulator/index.md -[Fork Testing with Cadence (Step-by-Step)]: ../../../blockchain-development-tutorials/cadence/fork-testing/index.md \ No newline at end of file +[Fork Testing with Cadence (Step-by-Step)]: ../../../blockchain-development-tutorials/cadence/fork-testing/index.md +[**Code Coverage**]: https://github.com/m-Peter/flow-code-coverage +[**Assertions**]: https://cadence-lang.org/docs/testing-framework#assertions +[**Integration tests**]: https://github.com/bjartek/overflow +[Overflow tool]: https://github.com/bjartek/overflow +[Cadence language documentation]: https://cadence-lang.org/ +[hybrid-custody]: https://github.com/onflow/hybrid-custody/tree/main/test +[flow-nft]: https://github.com/onflow/flow-nft/tree/master/tests +[flow-ft]: https://github.com/onflow/flow-ft/tree/master/tests +[Cadence documentation]: https://cadence-lang.org/docs/testing-framework +[Hybrid Custody]: https://github.com/onflow/hybrid-custody#readme +[repository]: https://github.com/m-Peter/flow-code-coverage#readme \ No newline at end of file