Smart Contract Project Development Standards
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, 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 on-chain 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.
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 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 gas 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.
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.
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 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.
Projects should maintain a well-organized open source repository 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 strongly 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.
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.
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.