diff --git a/.gitignore b/.gitignore index 7dd85aff98..41c4af600a 100644 --- a/.gitignore +++ b/.gitignore @@ -34,18 +34,3 @@ docs/references/core-contracts/flow-nft/* !docs/references/core-contracts/flow-nft/index.md docs/.obsidian - -# Remove after cadence is updated to a stable version -# https://github.com/onflow/docs/issues/105 -versioned_docs/version-stable/architecture -versioned_docs/version-stable/building-on-flow -versioned_docs/version-stable/build -versioned_docs/version-stable/overview -versioned_docs/version-stable/community-resources -versioned_docs/version-stable/concepts -versioned_docs/version-stable/references -versioned_docs/version-stable/tools -versioned_docs/version-stable/guides -versioned_docs/version-stable/node-ops -versioned_docs/version-stable/tutorials -versioned_docs/version-stable/getting-started diff --git a/CODEOWNERS b/CODEOWNERS index d5a2a6330b..e69de29bb2 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,3 +0,0 @@ -/docs/cadence @onflow/cadence -/versioned_docs/*/cadence @onflow/cadence - diff --git a/docs/build/advanced-concepts/account-linking/child-accounts.md b/docs/build/advanced-concepts/account-linking/child-accounts.md index d93f433ffb..e34f025628 100644 --- a/docs/build/advanced-concepts/account-linking/child-accounts.md +++ b/docs/build/advanced-concepts/account-linking/child-accounts.md @@ -35,8 +35,8 @@ signed transaction. Very simply, account linking is a [feature in Cadence](https://github.com/onflow/flips/pull/53) that let's an -[AuthAccount](../../../cadence/language/accounts#authaccount) create a -[Capability](../../../cadence/language/capabilities.md) on itself. You can do so in the following +[AuthAccount](https://cadence-lang.org/docs/language/accounts#authaccount) create a +[Capability](https://cadence-lang.org/docs/language/capabilities) on itself. You can do so in the following transaction: ```cadence link_account.cdc @@ -210,7 +210,7 @@ delegated access. We can achieve issuance from the child account and claim from the parent account pattern in either: -1. We can leverage [Cadence’s `AuthAccount.Inbox`](../../../cadence/language/accounts#account-inbox) to publish the +1. We can leverage [Cadence’s `AuthAccount.Inbox`](https://cadence-lang.org/docs/language/accounts#account-inbox) to publish the Capability from the child account & have the parent claim the Capability in a separate transaction. 1. Multi-party signed transaction, signed by both the the accounts on either side of the link diff --git a/docs/build/advanced-concepts/account-linking/index.md b/docs/build/advanced-concepts/account-linking/index.md index 6c26e4f857..f7aa1f3922 100644 --- a/docs/build/advanced-concepts/account-linking/index.md +++ b/docs/build/advanced-concepts/account-linking/index.md @@ -15,7 +15,7 @@ Accounts on flow can be accessed in Cadence through two types, `PublicAccount` a Accessing the auth account allows for account modification, so it's essential to safeguard this access by mandating that transactions are signed by the account being accessed. A transaction can list multiple auth accounts it wants to access as part of the `pre` section of the transaction. Read more about transaction signing in the transaction documentation. -Since access to the `AuthAccount` object enables state change, the idea of account ownership actually translates to the ability to access the auth account. Traditionally, you might consider this the same as having key access on an account, but we'll see in just a minute how programmatic, ownership-level access is unlocked with [Capabilities on Flow](../../../cadence/language/capabilities.md). +Since access to the `AuthAccount` object enables state change, the idea of account ownership actually translates to the ability to access the auth account. Traditionally, you might consider this the same as having key access on an account, but we'll see in just a minute how programmatic, ownership-level access is unlocked with [Capabilities on Flow](https://cadence-lang.org/docs/language/capabilities). ## AuthAccount Capabilities diff --git a/docs/build/basics/accounts.md b/docs/build/basics/accounts.md index 379a89a18e..3079c3dee4 100644 --- a/docs/build/basics/accounts.md +++ b/docs/build/basics/accounts.md @@ -35,7 +35,7 @@ This minimum storage fee is provided by the account creator and covers the cost **Contracts** -An account can optionally store multiple [Cadence contracts](../../cadence/language/contracts.mdx). The code is stored as a human-readable UTF-8 encoded string which makes it easy for anyone to inspect the contents. +An account can optionally store multiple [Cadence contracts](https://cadence-lang.org/docs/language/contracts). The code is stored as a human-readable UTF-8 encoded string which makes it easy for anyone to inspect the contents. **Storage** @@ -80,7 +80,7 @@ There are two curves commonly used with the ECDSA algorithm, secp256r1 ([OID 1.2 | ECDSA | P-256 | ECDSA_P256 | 2 | | ECDSA | secp256k1 | ECDSA_secp256k1 | 3 | -*Please note that the codes listed here are for the signature algorithms as used by the node API, and they are different from the ones [defined in Cadence](../../cadence/language/crypto.mdx#signing-algorithms)* +*Please note that the codes listed here are for the signature algorithms as used by the node API, and they are different from the ones [defined in Cadence](https://cadence-lang.org/docs/language/crypto#signing-algorithms)* | Algorithm | Output Size | ID | Code | | --------- | ----------- | -------- | ---- | @@ -128,7 +128,7 @@ We are supporting ECDSA with the curves `P-256` and `secp256k1`. For these curve ## Account Creation -Accounts are created on the Flow blockchain by calling a special [create account Cadence function](../../cadence/language/accounts#account-creation). Once an account is created we can associate a new key with that account. Of course, all that can be done within a single transaction. Keep in mind that there is an account creation fee that needs to be paid. Account creation fees are relatively low, and we expect that wallet providers and exchanges will cover the cost when a user converts fiat to crypto for the first time. +Accounts are created on the Flow blockchain by calling a special [create account Cadence function](https://cadence-lang.org/docs/language/accounts#account-creation). Once an account is created we can associate a new key with that account. Of course, all that can be done within a single transaction. Keep in mind that there is an account creation fee that needs to be paid. Account creation fees are relatively low, and we expect that wallet providers and exchanges will cover the cost when a user converts fiat to crypto for the first time. For development purposes, [you can use Flow CLI to easily create emulator, testnet and mainnet accounts.](../../tools/flow-cli/accounts/create-accounts.md) The account creation fee is paid by a funding wallet so you don’t need a pre-existing account to create it. diff --git a/docs/build/basics/blocks.md b/docs/build/basics/blocks.md index 34a76fad12..8fe8dc4f09 100644 --- a/docs/build/basics/blocks.md +++ b/docs/build/basics/blocks.md @@ -27,7 +27,7 @@ The Block header contains the following fields: - **ID** represents the block's unique identifier, which is derived from the hashing block header including the payload hash. The algorithm used on Flow to hash the content and get an identifier is SHA3 256. This ID is a commitment to all the values in the block staying the same. - **Parent ID** is a link to the previous block ID in the list making up the blockchain. - **Height** is the block sequence number, where block 0 was the first block produced, and each next block increments the value by 1. -- **Timestamp** is the timestamp at which this block was proposed by the consensus node. Depending on your use case this time might not be accurate enough, [read more about measuring time on the Flow blockchain](../../cadence/measuring-time.mdx#time-on-the-flow-blockchain). +- **Timestamp** is the timestamp at which this block was proposed by the consensus node. Depending on your use case this time might not be accurate enough, [read more about measuring time on the Flow blockchain](https://cadence-lang.org/docs/measuring-time#time-on-the-flow-blockchain). - **Payload Hash** represents the payload hash that is included when producing the ID of the block. Payload hash is calculated by taking Merkle root hashes of collection guarantees, seals, execution receipts, and execution results and hashing them together. More on each of the values in the block payload section. ### Block Payload diff --git a/docs/build/basics/events.md b/docs/build/basics/events.md index 45ddcdb2d8..15431c7cef 100644 --- a/docs/build/basics/events.md +++ b/docs/build/basics/events.md @@ -6,7 +6,7 @@ sidebar_position: 6 Flow events are special values that are emitted on the network during the execution of a Cadence program and can be observed by off-chain observers. -Events are defined as Cadence code and you should [read Cadence documentation](../../cadence/language/events.md) to understand how to define them. +Events are defined as Cadence code and you should [read Cadence documentation](https://cadence-lang.org/docs/language/events) to understand how to define them. Since transactions don’t have return values you can leverage events to broadcast certain changes the transaction caused. Clients listening on Flow networks (apps) can listen to these events being emitted and react. @@ -39,7 +39,7 @@ A list of events that are emitted by the Flow network is: | flow.InboxValueUnpublished | Event that is emitted when a Capability is unpublished from an account. | | flow.InboxValueClaimed1 | Event that is emitted when a Capability is claimed by an account. | -For more details [on the core events, you can read Cadence reference documentation](../../cadence/language/core-events.md). +For more details [on the core events, you can read Cadence reference documentation](https://cadence-lang.org/docs/language/core-events). ## User-defined events diff --git a/docs/build/basics/fees.md b/docs/build/basics/fees.md index 23e257eb7c..1d5fea2126 100644 --- a/docs/build/basics/fees.md +++ b/docs/build/basics/fees.md @@ -294,7 +294,7 @@ pub fun add(_ a: Int, _ b: Int): Int { **Avoid excessive load and save operations** -Avoid costly loading and storage operations and [borrow references](../../cadence/design-patterns.md#avoid-excessive-load-and-save-storage-operations-prefer-in-place-mutations) where possible, for example: +Avoid costly loading and storage operations and [borrow references](https://cadence-lang.org/docs/design-patterns#avoid-excessive-load-and-save-storage-operations-prefer-in-place-mutations) where possible, for example: ```cadence transaction { diff --git a/docs/build/basics/transactions.md b/docs/build/basics/transactions.md index ca0cbfd5cb..9d5be30b0e 100644 --- a/docs/build/basics/transactions.md +++ b/docs/build/basics/transactions.md @@ -21,12 +21,12 @@ In order for a transaction to be valid and executed it must contain signatures f The script section contains instructions for transaction execution. This is a Cadence program in source code form (human-readable), and encoded as UTF-8. The transaction program must contain a `transaction` declaration. -A transaction includes multiple optional phases `prepare`, `pre`, `execute`, and `post` phase. You can read more about it in the [Cadence reference document on transactions](../../cadence/language/transactions.md). Each phase has a purpose, the two most important phases are `prepare` and `execute`. +A transaction includes multiple optional phases `prepare`, `pre`, `execute`, and `post` phase. You can read more about it in the [Cadence reference document on transactions](https://cadence-lang.org/docs/language/transactions). Each phase has a purpose, the two most important phases are `prepare` and `execute`. In the `prepare` phase, we have access to `AuthAccount` objects, which gives us the power to interact with those accounts. The accounts are called authorizers of transactions, so each account we want to interact with in the `prepare` phase must sign the transaction as an authorizer. The `execute` phase does exactly what it says, it executes the main logic of the transaction. This phase is optional, but it is a best practice to add your main transaction logic in the section, so it is explicit. -Again make sure to read Cadence [documentation on transactions](../../cadence/language/transactions.md) +Again make sure to read Cadence [documentation on transactions](https://cadence-lang.org/docs/language/transactions) This is an example of a transaction script: @@ -40,7 +40,7 @@ transaction(greeting: String) { **Arguments** -Transactions may declare parameters it needs during execution, these must be provided as input arguments when sending a transaction. You can think of them as function arguments. Currently, we provide [arguments in the JSON-Cadence Data Interchange Format](../../cadence/json-cadence-spec.md#docusaurus_skipToContent_fallback). Which is a human-readable JSON format. The sample script from above accepts a single `String` argument. +Transactions may declare parameters it needs during execution, these must be provided as input arguments when sending a transaction. You can think of them as function arguments. Currently, we provide [arguments in the JSON-Cadence Data Interchange Format](https://cadence-lang.org/docs/json-cadence-spec#docusaurus_skipToContent_fallback). Which is a human-readable JSON format. The sample script from above accepts a single `String` argument. **Reference Block** diff --git a/docs/build/building-vs-other-chains.md b/docs/build/building-vs-other-chains.md index 2409f8b76f..9b9a8e274e 100644 --- a/docs/build/building-vs-other-chains.md +++ b/docs/build/building-vs-other-chains.md @@ -39,8 +39,8 @@ Check out the [Accounts](./basics/accounts.md) concept document to learn more ab On Flow, smart contracts are written in Cadence. Cadence syntax is user-friendly and inspired by modern languages like Swift. Notable features of Cadence that make it unique and the key power of the Flow blockchain are: -- **Resource-oriented**: Cadence introduces a new type called Resources. Resources enable onchain representation of digital assets natively and securely. Resources can only exist in one location at a time and are strictly controlled by the execution environment to avoid common mishandling mistakes. Each resource has a unique `uuid` associated with it on the blockchain. Examples of usage are fungible tokens, NFTs, or any custom data structure representing a real-world asset. Check out [Resources](../cadence/language/resources.mdx) to learn more. -- **Capability-based**: Cadence offers a [Capability-based Security](https://en.wikipedia.org/wiki/Capability-based_security) model. This also enables the use of Resources as structures to build access control. Capabilities can provide fine-grained access to the underlying objects for better security. For example, when users list an NFT on a Flow marketplace, they create a new Capability to the stored NFT in their account so the buyer can withdraw the asset when they provide the tokens. Check out [Capability-based Access Control](../cadence/language/capabilities.md) to learn more about Capabilities on Cadence. +- **Resource-oriented**: Cadence introduces a new type called Resources. Resources enable onchain representation of digital assets natively and securely. Resources can only exist in one location at a time and are strictly controlled by the execution environment to avoid common mishandling mistakes. Each resource has a unique `uuid` associated with it on the blockchain. Examples of usage are fungible tokens, NFTs, or any custom data structure representing a real-world asset. Check out [Resources](https://cadence-lang.org/docs/language/resources) to learn more. +- **Capability-based**: Cadence offers a [Capability-based Security](https://en.wikipedia.org/wiki/Capability-based_security) model. This also enables the use of Resources as structures to build access control. Capabilities can provide fine-grained access to the underlying objects for better security. For example, when users list an NFT on a Flow marketplace, they create a new Capability to the stored NFT in their account so the buyer can withdraw the asset when they provide the tokens. Check out [Capability-based Access Control](https://cadence-lang.org/docs/language/capabilities) to learn more about Capabilities on Cadence. @@ -52,16 +52,16 @@ Check out the [Cadence website](https://cadencelang.dev/) to learn more about Ca If you’re already familiar with smart contracts, here are some resources that can help you get started with Cadence: -- [The Cadence tutorial](../cadence/tutorial/01-first-steps.md) -- [Guide for Solidity Developers](../cadence/solidity-to-cadence.md) +- [The Cadence tutorial](https://cadence-lang.org/docs/tutorial/first-steps) +- [Guide for Solidity Developers](https://cadence-lang.org/docs/solidity-to-cadence) - ERC-20 equivalent on Flow is the Flow Fungible Token Standard - [Repository](https://github.com/onflow/flow-ft) - - [Tutorial](../cadence/tutorial/06-fungible-tokens.md) + - [Tutorial](https://cadence-lang.org/docs/tutorial/fungible-tokens) - ERC-721 equivalent on Flow is the Flow Non-Fungible Token Standard - [Repository](https://github.com/onflow/flow-nft) - - [Tutorial](../cadence/tutorial/05-non-fungible-tokens-1.md) + - [Tutorial](https://cadence-lang.org/docs/tutorial/non-fungible-tokens-1) - Asset marketplaces with Cadence - - [Tutorial](../cadence/tutorial/07-marketplace-setup.md) + - [Tutorial](https://cadence-lang.org/docs/tutorial/marketplace-setup) - [NFT Storefront](https://github.com/onflow/nft-storefront/) is an example marketplace standard ### Transactions and Scripts @@ -147,7 +147,7 @@ pub fun main(address: Address, collectionPublicPath: PublicPath): [UInt64] { } ``` -Check out [Transactions](./basics/transactions.md) and [Scripts](./basics/scripts.md) to learn more about the concepts. You can also read the Cadence language reference on [Transactions](../cadence/language/transactions.md) to dive deeper. +Check out [Transactions](./basics/transactions.md) and [Scripts](./basics/scripts.md) to learn more about the concepts. You can also read the Cadence language reference on [Transactions](https://cadence-lang.org/docs/language/transactions) to dive deeper. ## Flow Nodes @@ -188,6 +188,6 @@ If you’re already familiar with blockchain development, here's a comparison be - [Flow Playground](https://play.flow.com/) provides basic experimentation on the web - [Cadence VSCode Extension](https://marketplace.visualstudio.com/items?itemName=onflow.cadence) is strongly suggested to install for local development - [Testing Smart Contracts](https://ethereum.org/en/developers/docs/smart-contracts/testing/) - - [Cadence testing framework](../cadence/testing-framework.mdx) enables native tests in Cadence. + - [Cadence testing framework](https://cadence-lang.org/docs/testing-framework) enables native tests in Cadence. - [overflow](https://github.com/bjartek/overflow) for testing in Go. - [js-testing](https://github.com/onflow/flow-js-testing) for testing in JS. \ No newline at end of file diff --git a/docs/build/cadence.md b/docs/build/cadence.md index a841725017..a514aca4ca 100644 --- a/docs/build/cadence.md +++ b/docs/build/cadence.md @@ -133,7 +133,7 @@ Developers using custom-made approaches such as the 'data separation' approach t may run into problems with the complexity of data structures, while developers using ‘delegatecall-based proxies` may run into problems with the consistency of memory layouts. Either way, these challenges compromise approachability and overall extensibility. -Cadence has [contract upgradability built in by default](../cadence/language/contract-updatability.md), +Cadence has [contract upgradability built in by default](https://cadence-lang.org/docs/language/contract-updatability), and contracts can be made immutable by removing all keys from an account. Cadence improves the clarity and extensibility of programs by utilizing interfaces to allow extensibility, code reuse, and interoperability between contracts. @@ -187,7 +187,7 @@ but using an interpreter for the first version allows us to refine the language --- Now that you've learned about the goals and design of Cadence and Flow, you're ready to get started with the Flow emulator and tools! -Go to the [Getting Started](../cadence/tutorial/01-first-steps.md) page to work through language fundamentals and tutorials. +Go to the [Getting Started](https://cadence-lang.org/docs/tutorial/first-steps) page to work through language fundamentals and tutorials. ## Why Cadence? diff --git a/docs/build/flow.md b/docs/build/flow.md index d827089f64..1c78d5120c 100644 --- a/docs/build/flow.md +++ b/docs/build/flow.md @@ -31,7 +31,7 @@ The [development guide](../tutorials/intro.md) covers the Flow core concepts, in ## Core Contracts -The Flow blockchain implements core functionality using its own smart contract language, [Cadence](../cadence/language/). The core functionality is split into a set of contracts, so-called [core contracts](../references/core-contracts/index.md): +The Flow blockchain implements core functionality using its own smart contract language, [Cadence](https://cadence-lang.org/docs/language/). The core functionality is split into a set of contracts, so-called [core contracts](../references/core-contracts/index.md): - **Fungible Token:** The FungibleToken contract implements the Fungible Token Standard. It is the second contract ever deployed on Flow. - **Flow Token:** The FlowToken contract defines the FLOW network token. diff --git a/docs/build/getting-started/testing.md b/docs/build/getting-started/testing.md index 7bccc0238e..956d4f454e 100644 --- a/docs/build/getting-started/testing.md +++ b/docs/build/getting-started/testing.md @@ -184,7 +184,7 @@ The Cadence testing framework provides various features and techniques for writi - [**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**](../../cadence/testing-framework.mdx#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. +- [**Assertions**](https://cadence-lang.org/docs/testing-framework.mdx#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. @@ -196,5 +196,5 @@ For more in-depth tutorials and documentation, refer to the official [Cadence la ## References -- [Reference documentation for Cadence testing](../../cadence/testing-framework.mdx) +- [Reference documentation for Cadence testing](https://cadence-lang.org/docs/testing-framework) - https://github.com/bjartek/overflow diff --git a/docs/build/mobile/react-native-quickstart.md b/docs/build/mobile/react-native-quickstart.md index e1460b6ef4..d1bcc9914a 100644 --- a/docs/build/mobile/react-native-quickstart.md +++ b/docs/build/mobile/react-native-quickstart.md @@ -293,7 +293,7 @@ await fcl.query({ }); ``` -Inside the query you'll see we set two things: `cadence` and `args`. Cadence is Flow's smart contract language we mentioned. For this tutorial, when you look at it you just need to notice that it's importing the `Profile` contract from the account we named `0xProfile` earlier in our config file, then also taking an account address, and reading it. That's it until you're ready to [learn more Cadence](../../cadence/tutorial/01-first-steps.md). +Inside the query you'll see we set two things: `cadence` and `args`. Cadence is Flow's smart contract language we mentioned. For this tutorial, when you look at it you just need to notice that it's importing the `Profile` contract from the account we named `0xProfile` earlier in our config file, then also taking an account address, and reading it. That's it until you're ready to [learn more Cadence](https://cadence-lang.org/docs/tutorial/first-steps). In the `args` section, we are simply passing it our user's account address from the user we set in state after authentication and giving it a type of `Address`. For more possible types, [see this reference](../../tools/clients/fcl-js/api.md#ftype). @@ -612,7 +612,7 @@ If you query the account profile again, "Profile Name:" should now display "Flow That's it! You now have a shippable Flow dapp that can auth, query, init accounts, and mutate the chain. This is just the beginning. There is so much more to know. We have a lot more resources to help you build. To dive deeper, here are a few good places for taking the next steps: **Cadence** -- [Cadence Playground Tutorials](../../cadence/tutorial/01-first-steps.md) +- [Cadence Playground Tutorials](https://cadence-lang.org/docs/tutorial/first-steps) - [Cadence Hello World Video](https://www.youtube.com/watch?v=pRz7EzrWchs) - [Why Cadence?](https://www.onflow.org/post/flow-blockchain-cadence-programming-language-resources-assets) diff --git a/docs/cadence/_category_.yml b/docs/cadence/_category_.yml deleted file mode 100644 index d303479308..0000000000 --- a/docs/cadence/_category_.yml +++ /dev/null @@ -1,2 +0,0 @@ -label: Cadence -position: 5 diff --git a/docs/cadence/anti-patterns.md b/docs/cadence/anti-patterns.md deleted file mode 100644 index ad9c763a7f..0000000000 --- a/docs/cadence/anti-patterns.md +++ /dev/null @@ -1,250 +0,0 @@ ---- -title: Cadence Anti-Patterns -sidebar_position: 2 -sidebar_label: Anti-Patterns ---- - -This is an opinionated list of issues that can be improved if they are found in Cadence code intended for production. - -## Avoid using authorized account references as a function parameter - -### Problem - -A developer may choose to authenticate or perform operations for their users by using the users' account addresses. -In order to do this, they might add a parameter to a function which has an authorized account reference type (`auth(...) &Account`), -as an authorized account reference can only be obtained by signing a transaction. - -This is problematic, as the authorized account reference allows access to some sensitive operations on the account, -for example, to write to storage, -which provides the opportunity for bad actors to take advantage of. - -### Example: - -```cadence -... -// BAD CODE -// DO NOT COPY - -// Imagine this code is in a contract that uses a `auth(Storage) &Account` parameter -// to authenticate users to transfer NFTs - -// They could deploy the contract with an Ethereum-style access control list functionality - -access(all) fun transferNFT(id: UInt64, owner: auth(Storage) &Account) { - assert(owner(id) == owner.address) - - transfer(id) -} - -// But they could upgrade the function to have the same signature -// so it looks like it is doing the same thing, but they could also drain a little bit -// of FLOW from the user's vault, a totally separate piece of the account that -// should not be accessible in this function -// BAD - -access(all) fun transferNFT(id: UInt64, owner: auth(Storage) &Account) { - assert(owner(id) == owner.address) - - transfer(id) - - // Sneakily borrow a reference to the user's Flow Token Vault - // and withdraw a bit of FLOW - // BAD - let vaultRef = owner.borrow<&FlowToken.Vault>(/storage/flowTokenVault)! - let stolenTokens <- vaultRef.withdraw(amount: 0.1) - - // deposit the stolen funds in the contract owners vault - // BAD - contractVault.deposit(from: <-stolenTokens) -} -... -``` - -### Solution - -Projects should find other ways to authenticate users, such as using resources and capabilities as authentication objects. -They should also expect to perform most storage and linking operations within transaction bodies -rather than inside contract utility functions. - -There are some scenarios where using an authorized account reference (`auth(...) &Account`) is necessary, -such as a cold storage multi-sig, -but those cases are rare and such usage should still be avoided unless absolutely necessary. - -## Public functions and fields should be avoided - -### Problem - -Be sure to keep track of access modifiers when structuring your code, and make public only what should be public. -Accidentally exposed fields can be a security hole. - -### Solution - -When writing your smart contract, look at every field and function and make sure -that require access through an [entitlement](./language/access-control.md#entitlements) (`access(E)`), -or use a non-public [access modifier](./language/access-control.md) like `access(self)`, `access(contract)`, or `access(account)`, -unless otherwise needed. - -## Capability-Typed public fields are a security hole - -This is a specific case of "Public Functions And Fields Should Be Avoided", above. - -### Problem - -The values of public fields can be copied. Capabilities are value types, -so if they are used as a public field, anyone can copy it from the field -and call the functions that it exposes. -This almost certainly is not what you want if a capability -has been stored as a field on a contract or resource in this way. - -### Solution - -For public access to a capability, place it in an accounts public area so this expectation is explicit. - -## Public admin resource creation functions are unsafe - -This is a specific case of "Public Functions And Fields Should Be Avoided", above. - -### Problem - -A public function on a contract that creates a resource can be called by any account. -If that resource provides access to admin functions then the creation function should not be public. - -### Solution - -To fix this, a single instance of that resource should be created in the contract's initializer, -and then a new creation function can be potentially included within the admin resource, if necessary. - -### Example - -```cadence -// Pseudo-code - -// BAD -access(all) contract Currency { - access(all) resource Admin { - access(all) fun mintTokens() - } - - // Anyone in the network can call this function - // And use the Admin resource to mint tokens - access(all) fun createAdmin(): @Admin { - return <-create Admin() - } -} - -// This contract makes the admin creation private and in the initializer -// so that only the one who controls the account can mint tokens -// GOOD -access(all) contract Currency { - access(all) resource Admin { - access(all) fun mintTokens() - - // Only an admin can create new Admins - access(all) fun createAdmin(): @Admin { - return <-create Admin() - } - } - - init() { - // Create a single admin resource - let firstAdmin <- create Admin() - - // Store it in private account storage, so only the admin can use it - self.account.storage.save(<-firstAdmin, to: /storage/currencyAdmin) - } -} -``` - -## Do not modify smart contract state or emit events in public struct initializers - -This is another example of the risks of having publicly accessible parts to your smart contract. - -### Problem - -Data structure definitions in Cadence currently must be declared as public so that they can be used by anyone. -Structs do not have the same restrictions that resources have on them, -which means that anyone can create a new instance of a struct without going through any authorization. - -### Solution - -Any contract state-modifying operations related to the creation of structs -should be contained in resources instead of the initializers of structs. - -### Example - -This used to be a bug in the NBA Top Shot smart contract, so we'll use that as an example. -Before, when it created a new play, -[it would initialize the play record with a struct,](https://github.com/dapperlabs/nba-smart-contracts/blob/55645478594858a6830e4ab095034068ef9753e9/contracts/TopShot.cdc#L155-L158) -which increments the number that tracks the play IDs and emits an event: - -```cadence -// Simplified Code -// BAD -// -access(all) contract TopShot { - - // The Record that is used to track every unique play ID - access(all) var nextPlayID: UInt32 - - access(all) struct Play { - - access(all) let playID: UInt32 - - init() { - - self.playID = TopShot.nextPlayID - - // Increment the ID so that it isn't used again - TopShot.nextPlayID = TopShot.nextPlayID + 1 - - emit PlayCreated(id: self.playID, metadata: metadata) - } - } -} -``` - -This is a risk because anyone can create the `Play` struct as many times as they want, -which could increment the `nextPlayID` field to the max `UInt32` value, -effectively preventing new plays from being created. It also would emit bogus events. - -This bug was fixed by -[instead updating the contract state in the admin function](https://github.com/dapperlabs/nba-smart-contracts/blob/master/contracts/TopShot.cdc#L682-L685) -that creates the plays. - - -```cadence -// Update contract state in admin resource functions -// GOOD -// -access(all) contract TopShot { - - // The Record that is used to track every unique play ID - access(all) var nextPlayID: UInt32 - - access(all) struct Play { - - access(all) let playID: UInt32 - - init() { - self.playID = TopShot.nextPlayID - } - } - - access(all) resource Admin { - - // Protected within the private admin resource - access(all) fun createPlay() { - // Create the new Play - var newPlay = Play() - - // Increment the ID so that it isn't used again - TopShot.nextPlayID = TopShot.nextPlayID + UInt32(1) - - emit PlayCreated(id: newPlay.playID, metadata: metadata) - - // Store it in the contract storage - TopShot.playDatas[newPlay.playID] = newPlay - } - } -} -``` diff --git a/docs/cadence/contract-upgrades.md b/docs/cadence/contract-upgrades.md deleted file mode 100644 index 749dccf551..0000000000 --- a/docs/cadence/contract-upgrades.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: Contract Upgrades with Incompatible Changes -sidebar_position: 4 ---- - -### Problem - -I have an incompatible upgrade for a contract. How can I deploy this? - -### Solution - -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](../cadence/language/contract-updatability.md) 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. - -⚠️ Flow identifies types relative to addresses, so you will also need to provide _upgrade transactions_ to exchange the old contract's resources for the new contract's ones. Make sure to inform users as soon as possible when and how they will need to perform this task. - -If you absolutely must keep the old address when making an incompatible upgrade, then you do so at your own risk. Make sure you perform the following actions in this exact order: - -1. Delete any resources used in the contract account, e.g. an Admin resource. -2. Delete the contract from the account. -3. Deploy the new contract to the account. - -⚠️ 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! diff --git a/docs/cadence/design-patterns.md b/docs/cadence/design-patterns.md deleted file mode 100644 index 5772a1c52a..0000000000 --- a/docs/cadence/design-patterns.md +++ /dev/null @@ -1,458 +0,0 @@ ---- -title: Cadence Design Patterns -sidebar_position: 1 -sidebar_label: Design Patterns ---- - -This is a selection of software design patterns developed by core Flow developers -while writing Cadence code for deployment to Flow Mainnet. - -Many of these design patters apply to most other programming languages, but some are specific to Cadence. - -[Design patterns](https://en.wikipedia.org/wiki/Software_design_pattern) are building blocks for software development. -They may provide a solution to a problem that you encounter when writing smart contracts in Cadence. -If they do not clearly fit, these patterns may not be the right solution for a given situation or problem. -They are not meant to be rules to be followed strictly, especially where a better solution presents itself. - -# General - -These are general patterns to follow when writing smart contracts. - -## Use named value fields for constants instead of hard-coding - -### Problem - -Your contracts, resources, and scripts all have to refer to the same value. -A number, a string, a storage path, etc. -Entering these values manually in transactions and scripts is a potential source of error. -See [Wikipedia's page on magic numbers](https://en.wikipedia.org/wiki/Magic_number_(programming)) - -### Solution - -Add a public (`access(all)`), constant (`let`) field, e.g. a `Path` , to the contract responsible for the value, -and set it in the contract's initializer. -Refer to that value via this public field rather than specifying it manually. - -Example Snippet: - -```cadence - -// BAD Practice: Do not hard code storage paths -access(all) contract NamedFields { - access(all) resource Test {} - - init() { - // BAD: Hard-coded storage path - self.account.storage.save(<-create Test(), to: /storage/testStorage) - } -} - -// GOOD practice: Instead, use a field -// -access(all) contract NamedFields { - access(all) resource Test {} - - // GOOD: field storage path - access(all) let TestStoragePath: StoragePath - - init() { - // assign and access the field here and in transactions - self.TestStoragePath = /storage/testStorage - self.account.storage.save(<-create Test(), to: self.TestStoragePath) - } -} - -``` - -[Example Code](https://github.com/onflow/flow-core-contracts/blob/master/contracts/LockedTokens.cdc#L718) - -## Script-Accessible public field/function - -Data availability is important in a blockchain environment. -It is useful to publicize information about your smart contract and the assets it controls -so other smart contracts and apps can easily query it. - -### Problem - -Your contract, resource, or struct has a field or resource that will need to be read and used on or off-chain, often in bulk. - -### Solution - -Make sure that the field can be accessed from a script. -This saves the time and fees required to read a property using a transaction. -Making the field or function `access(all)` and exposing it via a `/public/` capability will allow this. - -Be careful not to expose any data or functionality that should be kept private when doing so. - -Example: - -```cadence -// BAD: Field is private, so it cannot be read by the public -access(self) let totalSupply: UFix64 - -// GOOD: Field is public, so it can be read and used by anyone -access(all) let totalSupply: UFix64 -``` - -## Script-Accessible report - -### Problem - -Your contract has a resource that you wish to access fields of. -Resources are often stored in private places and are hard to access. -Additionally, scripts cannot return resources to the external context, -so a struct must be used to hold the data. - -### Solution - -Return a reference to a resource if the data from a single resource is all that is needed. -Otherwise, declare a struct to hold the data that you wish to return from the script. -Write a function that fills out the fields of this struct with the data -from the resource that you wish to access. -Then call this on the resource that you wish to access the fields of in a script, -and return the struct from the script. - -See [Script-Accessible public field/function](#script-accessible-public-fieldfunction), above, for how best to expose this capability. - -### Example - -```cadence -access(all) contract AContract { - access(all) let BResourceStoragePath: StoragePath - access(all) let BResourcePublicPath: PublicPath - - init() { - self.BResourceStoragePath = /storage/BResource - self.BResourcePublicPath = /public/BResource - } - - // Resource definition - access(all) resource BResource { - access(all) var c: UInt64 - access(all) var d: String - - - // Generate a struct with the same fields - // to return when a script wants to see the fields of the resource - // without having to return the actual resource - access(all) fun generateReport(): BReportStruct { - return BReportStruct(c: self.c, d: self.d) - } - - init(c: UInt64, d: String) { - self.c = c - self.d = d - } - } - - // Define a struct with the same fields as the resource - access(all) struct BReportStruct { - access(all) var c: UInt64 - access(all) var d: String - - init(c: UInt64, d: String) { - self.c = c - self.d = d - } - - } -} -... -// Transaction -import AContract from 0xAContract - -transaction { - prepare(acct: auth(IssueStorageCapabilityController, PublishCapability) &Account) { - //... - let cap = acct.capabilities.storage.issue<&AContract.BResource>(AContract.BResourceStoragePath) - acct.capabilities.publish(cap, at: AContract.BResourcePublicPath) - } -} -// Script -import AContract from 0xAContract - -// Return the struct with a script -access(all) fun main(account: Address): AContract.BReportStruct { - // borrow the resource - let b = getAccount(account).capabilities - .borrow<&AContract.BResource>(AContract.BResourcePublicPath) - // return the struct - return b.generateReport() -} -``` - -## Init singleton - -### Problem - -An admin resource must be created and delivered to a specified account. -There should not be a function to do this, as that would allow anyone to create an admin resource. - -### Solution - -Create any one-off resources in the contract's initializer -and deliver them to an address or `&Account` specified as an argument. - -See how this is done in the LockedTokens contract initializer: - -[LockedTokens.cdc](https://github.com/onflow/flow-core-contracts/blob/master/contracts/LockedTokens.cdc#L718) - -and in the transaction that is used to deploy it: - -[admin_deploy_contract.cdc](https://github.com/onflow/flow-core-contracts/blob/master/transactions/lockedTokens/admin/admin_deploy_contract.cdc) - - -## Use descriptive names for fields, paths, functions and variables - -### Problem - -Smart contracts often are vitally important pieces of a project and often have many other -smart contracts and applications that rely on them. -Therefore, they need to be clearly written and easy to understand. - -### Solution - -All fields, functions, types, variables, etc., need to have names that clearly describe what they are used for. - -`account` / `accounts` is better than `array` / `element`. - -`providerAccount` / `tokenRecipientAccount` is better than `acct1` / `acct2`. - -`/storage/bestPracticesDocsCollectionPath` is better than `/storage/collection` - -### Example - -```cadence -// BAD: Unclear naming -// -access(all) contract Tax { - // Do not use abbreviations unless absolutely necessary - access(all) var pcnt: UFix64 - - // Not clear what the function is calculating or what the parameter should be - access(all) fun calculate(num: UFix64): UFix64 { - // What total is this referring to? - let total = num + (num * self.pcnt) - - return total - } -} - -// GOOD: Clear naming -// -access(all) contract TaxUtilities { - // Clearly states what the field is for - access(all) var taxPercentage: UFix64 - - // Clearly states that this function calculates the - // total cost after tax - access(all) fun calculateTotalCostPlusTax(preTaxCost: UFix64): UFix64 { - let postTaxCost = preTaxCost + (preTaxCost * self.taxPercentage) - - return postTaxCost - } -} -``` - -## Plural names for arrays and maps are preferable - -For example, use `accounts` rather than `account` for an array of accounts. - -This signals that the field or variable is not scalar. -It also makes it easier to use the singular form for a variable name during iteration. - -## Use transaction post-conditions when applicable - -### Problem - -Transactions can contain any amount of valid Cadence code and access many contracts and accounts. -The power of resources and capabilities means that there may be some behaviors of programs that are not expected. - -### Solution - -It is usually safe to include post-conditions in transactions to verify the intended outcome. - -### Example - -This could be used when purchasing an NFT to verify that the NFT was deposited in your account's collection. - -```cadence -// Pseudo-code - -transaction { - - access(all) let buyerCollectionRef: &NonFungibleToken.Collection - - prepare(acct: auth(BorrowValue) &Account) { - - // Get tokens to buy and a collection to deposit the bought NFT to - let temporaryVault <- vaultRef.withdraw(amount: 10.0) - let self.buyerCollectionRef = acct.storage.borrow(from: /storage/Collection) - - // purchase, supplying the buyers collection reference - saleRef.purchase(tokenID: 1, recipient: self.buyerCollectionRef, buyTokens: <-temporaryVault) - - } - post { - // verify that the buyer now owns the NFT - self.buyerCollectionRef.idExists(1) == true: "Bought NFT ID was not deposited into the buyers collection" - } -} -``` - -## Avoid unnecessary load and save storage operations, prefer in-place mutations - -### Problem - -When modifying data in account storage, `load()` and `save()` are costly operations: -All data is unnecessarily moved out of the account, then moved back into the account. -This can quickly cause your transaction to reach its limits. - -This also applies to nested, stored in fields, arrays, and dictionaries: -Moving objects out of containers and moving them back into the container, -just to modify the object, is just as costly. - -For example, a collection contains a dictionary of NFTs. -There is no need to move the whole dictionary out of the field, -update the dictionary on the stack (e.g., adding or removing an NFT), -and then move the whole dictionary back to the field: -the dictionary can be updated in-place, which is easier and more efficient. -The same goes for a more complex data structure like a dictionary of nested resources: -Each resource can be updated in-place by taking a reference to the nested object instead of loading and saving. - -### Solution - -For making modifications to values in storage or accessing stored objects, -`borrow()` should always be used to access them instead of `load` or `save` unless absolutely necessary. -`borrow()` returns a reference to the object at the storage path instead of having to load the entire object. -This reference can be assigned to or can be used to access fields or call methods on stored objects. - -Fields and value in containers, such as in arrays and dictionaries, -can be borrowed using a reference expression (`&v as &T`). - -### Example - -```cadence -// BAD: Loads and stores a resource to use it -// -transaction { - - prepare(acct: auth(LoadValue, SaveValue) &Account) { - - // Removes the vault from storage, a costly operation - let vault <- acct.storage.load<@ExampleToken.Vault>(from: /storage/exampleToken) - - // Withdraws tokens - let burnVault <- vault.withdraw(amount: 10) - - destroy burnVault - - // Saves the used vault back to storage, another costly operation - acct.storage.save(to: /storage/exampleToken) - - } -} - -// GOOD: Uses borrow instead to avoid costly operations -// -transaction { - - prepare(acct: auth(BorrowValue) &Account) { - - // Borrows a reference to the stored vault, much less costly operation - let vault <- acct.storage.borrow<&ExampleToken.Vault>(from: /storage/exampleToken) - - let burnVault <- vault.withdraw(amount: 10) - - destroy burnVault - - // No `save` required because we only used a reference - } -} -``` - -# Capabilities - -## Capability bootstrapping - -### Problem - -An account must be given a [capability](./language/capabilities.md) to an object stored in another account. -To create (issue) the capability, the transaction must be signed by a key which has access to the target account. - -To transfer / deliver the capability to the other account, the transaction also needs write access to that one. -It is not as easy to produce a single transaction which is authorized by two accounts -as it is to produce a typical transaction which is authorized by one account. - -This prevents a single transaction from fetching the capability -from one account and delivering it to the other. - -### Solution - -The solution to the bootstrapping problem in Cadence is provided by the [Inbox API](./language/accounts/inbox.mdx). - -Account A (which we will call the provider) creates the capability they wish to send to B (which we will call the recipient), -and stores this capability on their account in a place where the recipient can access it using the `Inbox.publish` function on their account. -They choose a name for the capability that the recipient can later use to identify it, and specify the recipient's address when calling `publish`. -This call to `publish` will emit an `InboxValuePublished` event that the recipient can listen for off-chain to know that the Capability is ready for them to claim. - -The recipient then later can use the `Inbox.claim` function to securely grab the capability from the provider's account. -They must provide the name and type with which the capability was published, as well as the address of the provider's account -(all of this information is available in the `InboxValuePublished` event emitted on `publish`). -This will remove the capability from the provider's account and emit an `InboxValueClaimed` event that the provider can listen for off-chain. - -One important caveat to this is that the published capability is stored on the provider's account until the recipient claims it, -so the provider can also use the `Inbox.unpublish` function to remove the capability from their account if they no longer wish to pay for storage for it. -This also requires the name and type which the capability was published, -and emits an `InboxValueUnpublished` event that the recipient can listen for off-chain. - -It is also important to note that the recipient becomes the owner of the capability object once they have claimed it, -and can thus store it or copy it anywhere they have access to. -This means providers should only publish capabilities to recipients they trust to use them properly, -or limit the type with which the capability is authorized in order to only give recipients access to the functionality -that the provider is willing to allow them to copy. - - -## Capability revocation - -### Problem - -A capability provided by one account to a second account must able to be revoked -by the first account without the co-operation of the second. - -### Solution - -The first account should issue a _new_ capability -and use it only for the purpose of granting the second account access. - -Once the first account wants to revoke access to the resource in storage, -they can simply get the capability controller for that capability and delete it. - - -## Check for existing capability before publishing new one - -### Problem - -When publishing a capability, a capability might be already be published at the specified path. - -### Solution - -Check if a capability is already published at the given path. - -### Example - -```cadence -transaction { - prepare(signer: auth(Capabilities) &Account) { - let capability = signer.capabilities.storage - .issue<&ExampleToken.Vault>(/storage/exampleTokenVault) - - let publicPath = /public/exampleTokenReceiver - - if signer.capabilities.exits(publicPath) { - signer.capabilities.unpublish(publicPath) - } - signer.capabilities.publish(capability, at: publicPath) - } -} -``` diff --git a/docs/cadence/index.mdx b/docs/cadence/index.mdx deleted file mode 100644 index 89b1a6f181..0000000000 --- a/docs/cadence/index.mdx +++ /dev/null @@ -1,9 +0,0 @@ ---- -sidebar_position: 1 ---- - -import DocCardList from '@theme/DocCardList'; -import { useDocsSidebar, isSamePath } from '@docusaurus/theme-common/internal'; -import { useLocation } from '@docusaurus/router'; - - !isSamePath(item.href, useLocation().pathname))}/> diff --git a/docs/cadence/intro.md b/docs/cadence/intro.md deleted file mode 100644 index badebc2dee..0000000000 --- a/docs/cadence/intro.md +++ /dev/null @@ -1,190 +0,0 @@ ---- -title: Introduction to Cadence -sidebar_position: 1 -sidebar_label: Introduction ---- - -In a blockchain environment like Flow, programs that are stored on-chain in accounts are commonly referred to as smart contracts. -A smart contract is a program that verifies and executes the performance of a contract without the need for a trusted third party. -Programs that run on blockchains are commonly referred to as smart contracts because they mediate important functionality (such as currency) -without having to rely on a central authority (like a bank). - -## A New Programming Language - ---- - -Cadence is a resource-oriented programming language that introduces new features to smart contract programming -that help developers ensure that their code is safe, secure, clear, and approachable. Some of these features are: - -- Type safety and a strong static type system. -- Resource-oriented programming, a new paradigm that pairs linear types with object capabilities -to create a secure and declarative model for digital ownership by ensuring that resources (which are used to represent scarce digital assets) -can only exist in one location at a time, cannot be copied, and cannot be accidentally lost or deleted. -- Built-in pre-conditions and post-conditions for functions and transactions. -- The utilization of capability-based security, which enforces that access to objects -is restricted to only the owner of the object and those who have a valid reference to it. -This is Cadence's main form of access control. - -Cadence’s syntax is inspired by popular modern general-purpose programming languages -like [Swift](https://developer.apple.com/swift/), [Kotlin](https://kotlinlang.org/), and [Rust](https://www.rust-lang.org/). -Its use of resource types maps well to that of [Move](https://medium.com/coinmonks/overview-of-move-programming-language-a860ffd8f55d), -the programming language being developed by the Diem team. - -## Cadence's Programming Language Pillars - ---- - -Cadence, a new high-level programming language, observes the following requirements: - -- **Safety and Security:** Safety is the underlying reliability of any smart contract (i.e., it’s bug-free and performs its function). -Security is the prevention of attacks on the network or smart contracts (i.e., unauthorized actions by malicious actors). -Safety and security are critical in smart contracts because of the immutable nature of blockchains, -and because they often deal with high-value assets. While auditing and reviewing code will be a crucial part of smart contract development, -Cadence maximizes efficiency while maintaining the highest levels of safety and security at its foundation. -It accomplishes this via a strong static type system, design by contract, and ownership primitives inspired by linear types (which are useful when dealing with assets). -- **Clarity:** Code needs to be easy to read, and its meaning should be as unambiguous as possible. -It should also be suited for verification so that tooling can help with ensuring safety and security guarantees. -These guarantees can be achieved by making the code declarative and allowing the developer to express their intentions directly. -We make those intentions explicit by design, which, along with readability, make auditing and reviewing more efficient, at a small cost to verbosity. -- **Approachability:** Writing code and creating programs should be as approachable as possible. -Incorporating features from languages like Swift and Rust, developers should find Cadence’s syntax and semantics familiar. -Practical tooling, documentation, and examples enable developers to start creating programs quickly and effectively. -- **Developer Experience:** The developer should be supported throughout the entire development lifecycle, from initial application logic to on-chain bugfixes. -- **Intuiting Ownership with Resources:** Resources are a composite data type, similar to a struct, that expresses direct ownership of assets. -Cadence’s strong static type system ensures that resources can only exist in one location at a time and cannot be copied or lost because of a coding mistake. -Most smart contract languages currently use a ledger-style approach to record ownership, -where an asset like a fungible token is stored in the smart contract as an entry in a central ledger. -Cadence’s resources directly tie an asset’s ownership to the account that owns it by saving the resource in the account’s storage. -As a result, ownership isn’t centralized in a smart contract’s storage. Each account owns its assets, -and the assets can be transferred freely between accounts without the need for arbitration by a central smart contract. - -## Addressing Challenges with Existing Languages - ---- - -Other languages pioneered smart contract development, but they lack in areas that affect the long-term viability of next-generation applications. - -### Safety - -Safety is the reliability of a smart contract to perform its function as intended. -It is heavily influenced by the unchangeable-once-deployed nature of smart contracts: -Developers must take certain precautions in order to avoid introducing any potentially catastrophic vulnerabilities -prior to publishing a smart contract on the blockchain. -It is standard across many blockchains that modifying or updating a smart contract, even to fix a vulnerability, is not allowed. -Thus, any bugs that are present in the smart contract will exist forever. - -For example, in 2016, an overlooked vulnerability in an Ethereum DAO smart contract (Decentralized Autonomous Organization) -saw millions of dollars siphoned from a smart contract, -eventually leading to a fork in Ethereum and two separate active blockchains (Ethereum and Ethereum Classic). - -Bug fixes are only possible if a smart contract is designed to support changes, -a feature that introduces complexity and security issues. -Lengthy auditing and review processes can ensure a bug-free smart contract. -Still, they add substantial time to the already time-consuming task of getting the smart contract’s core logic working correctly. - -Overlooked mistakes cause the most damaging scenarios. -It is easy to lose or duplicate monetary value or assets in existing languages because they don’t check relevant invariants -or make it harder to express them. -For example, a plain number represents a transferred amount that can be accidentally (or maliciously) multiplied or ignored. - -Some languages also express behaviors that developers tend to forget about. -For example, a fixed-range type might express monetary value, without considerations for a potential overflow or underflow. -In Solidity, Ethereum's smart contract language, an overflow causes the value to wrap around, as shown [here](https://ethfiddle.com/CAp-kQrDUP). -Solidity also allows contracts to declare variables without initializing them. -If the developer forgets to add an initialization somewhere, -and then tries to read the variable somewhere else in the code expecting it to be a specific value, issues will occur. - -Cadence is type safe and has a strong static type system, -which prevents important classes of erroneous or undesirable program behavior at compile-time (i.e., before the program is run on-chain). -Types are checked statically and are not implicitly converted. Cadence also improves the safety of programs by preventing arithmetic underflow and overflow, -introduces optionals to make nil-cases explicit, and always requires variables to be initialized. -This helps ensure the behavior of these smart contracts is apparent and not dependent on context. - -### Security - -Security, in combination with safety, ensures the successful execution of a smart contract over time -by preventing unsanctioned access and guaranteeing that only authorized actions can be performed in the protocol. -In some languages, functions are public by default, creating vulnerabilities that allow malicious users to find attack vectors. -Cadence utilizes capability-based security, which allows the type system to enforce access control based on rules that users and developers have control over. - -Security is a consideration when interacting with other smart contracts. Any external call potentially allows malicious code to be executed. -For example, in Solidity, when the called function signature does not match any of the available ones, it triggers Solidity’s fallback functions. -These functions can be used in malicious ways. Language features such as multiple inheritances and overloading or dispatch can also make it difficult -to determine which code is invoked. - -In Cadence, the safety and security of programs are enhanced by **Design By Contract** and **Ownership Primitives.** -Design by contract allows developers to state pre-conditions and post-conditions for functions and interfaces in a declarative manner -so that callers can be certain about the behavior of called code. Ownership primitives are inspired by linear types and increase safety when working with assets. -They ensure that valuable assets are, for example, not accidentally or maliciously lost or duplicated. - -### Clarity and Approachability - -Implicitness, context-dependability, and expressiveness are language-based challenges that developers often encounter. -They affect the clarity (i.e. the readability of code and the ability to determine its intended function) -and the approachability (i.e. the ability to interpret or write code) of the language and the programs built using it. -For example, in Solidity, storage must be implemented in a low-level key-value manner, which obfuscates the developer’s intentions. -Syntax confusion is another example, with “=+” being legal syntax leading to an assignment instead of a probably-intended increment. -Solidity also has features with uncommon behaviors that can lead to unintended results. -[Multiple inheritance may lead to unexpected behaviours in the program](https://medium.com/consensys-diligence/a-case-against-inheritance-in-smart-contracts-d7f2c738f78e), -and testing and auditing the code is unlikely to identify this issue. - -The Ethereum blockchain’s code immutability showcases the need for considerations around extensibility and mechanisms that allow ad-hoc fixes. -Developers using custom-made approaches such as the 'data separation' approach to upgradability -may run into problems with the complexity of data structures, -while developers using ‘delegatecall-based proxies` may run into problems with the consistency of memory layouts. -Either way, these challenges compromise approachability and overall extensibility. -Cadence has [contract upgradability built in by default](./language/contract-updatability.md), -and contracts can be made immutable by removing all keys from an account. - -Cadence improves the clarity and extensibility of programs by utilizing interfaces to allow extensibility, code reuse, and interoperability between contracts. -Cadence modules also have configurable and transparent upgradeability built-in to enable projects to test and iterate before making their code immutable. - -Cadence allows the use of argument labels to describe the meaning of function arguments. -It also provides a rich standard library with useful data structures (e.g., dictionaries, sets) and data types for common use cases, -like fixed-point arithmetic, which helps when working with currencies. - -## Intuiting Ownership with Resources - -Most smart contract languages currently use a ledger-style approach to record ownership, -where an asset is stored in the smart contract as an entry in a central ledger, and this ledger is the source of truth around asset ownership. -There are many disadvantages to this design, especially when it comes to tracking the ownership of multiple assets belonging to a single account. -To find out all of the assets that an account owns, you would have to enumerate all the possible smart contracts that could potentially include this account -and search to see if the account owns these assets. - -In a resource-oriented language like Cadence, resources directly tie an asset to the account that owns it -by saving the resource in the account’s storage. As a result, ownership isn’t centralized in a single, central smart contract’s storage. -Instead, each account owns and stores its own assets, and the assets can be transferred freely between accounts without the need for arbitration by a central smart contract. - -Resources are inspired by linear types and increase safety when working with assets, which often have real, intrinsic value. -Resources, as enforced by Cadence’s type system, ensure that assets are correctly manipulated and not abused. - -- Every resource has exactly one owner. If a resource is used as a function parameter, an initial value for a variable, or something similar, the object is not copied. -Instead, it is moved to the new location, and the old location is immediately invalidated. -- The language will report an error if ownership of a resource was not properly transferred, i.e., -when the program attempts to introduce multiple owners for the resource or the resource ends up in a state where it does not have an owner. -For example, a resource can only be assigned to exactly one variable and cannot be passed to functions multiple times. -- Resources cannot go out of scope. If a function or transaction removes a resource from an account’s storage, -it either needs to end the transaction in an account's storage, or it needs to be explicitly and safely deleted. There is no “garbage collection” for resources. - -The special status of Resource objects must be enforced by the runtime; if they were just a compiler abstraction it would be easy for malicious code to break the value guarantees. - -Resources change how assets are used in a programming environment to better resemble assets in the real world. -Users store their currencies and assets in their own account, in their own wallet storage, and they can do with them as they wish. -Users can define custom logic and structures for resources that give them flexibility with how they are stored. -Additionally, because everyone stores their own assets, the calculation and charging of state rent is fair and balanced across all users in the network. - -## An Interpreted Language - ---- - -Currently, Cadence is an interpreted language, as opposed to a compiled language. This means that there is no Cadence Assembly, bytecode, compiler, or Cadence VM. - -The structure of the language lends itself well to compilation (for example, static typing), -but using an interpreter for the first version allows us to refine the language features more quickly as we define them. - -## Getting Started with Cadence - ---- - -Now that you've learned about the goals and design of Cadence and Flow, you're ready to get started with the Flow emulator and tools! -Go to the [Getting Started](./tutorial/01-first-steps.md) page to work through language fundamentals and tutorials. diff --git a/docs/cadence/json-cadence-spec.md b/docs/cadence/json-cadence-spec.md deleted file mode 100644 index 5e059bbb86..0000000000 --- a/docs/cadence/json-cadence-spec.md +++ /dev/null @@ -1,868 +0,0 @@ ---- -title: JSON-Cadence Data Interchange Format -sidebar_label: JSON-Cadence format ---- - -> Version 0.3.1 - -JSON-Cadence is a data interchange format used to represent Cadence values as language-independent JSON objects. - -This format includes less type information than a complete [ABI](https://en.wikipedia.org/wiki/Application_binary_interface), and instead promotes the following tenets: - -- **Human-readability** - JSON-Cadence is easy to read and comprehend, which speeds up development and debugging. -- **Compatibility** - JSON is a common format with built-in support in most high-level programming languages, making it easy to parse on a variety of platforms. -- **Portability** - JSON-Cadence is self-describing and thus can be transported and decoded without accompanying type definitions (i.e. an ABI). - -# Values - ---- - -## Void - -```json -{ - "type": "Void" -} -``` - -### Example - -```json -{ - "type": "Void" -} -``` - ---- - -## Optional - -```json -{ - "type": "Optional", - "value": null | -} -``` - -### Example - -```json -// Non-nil - -{ - "type": "Optional", - "value": { - "type": "UInt8", - "value": "123" - } -} - -// Nil - -{ - "type": "Optional", - "value": null -} -``` - ---- - -## Bool - -```json -{ - "type": "Bool", - "value": true | false -} -``` - -### Example - -```json -{ - "type": "Bool", - "value": true -} -``` - ---- - -## String - -```json -{ - "type": "String", - "value": "..." -} - -``` - -### Example - -```json -{ - "type": "String", - "value": "Hello, world!" -} -``` - ---- - -## Address - -```json -{ - "type": "Address", - "value": "0x0" // as hex-encoded string with 0x prefix -} -``` - -### Example - -```json -{ - "type": "Address", - "value": "0x1234" -} -``` - ---- - -## Integers - -`[U]Int`, `[U]Int8`, `[U]Int16`, `[U]Int32`,`[U]Int64`,`[U]Int128`, `[U]Int256`, `Word8`, `Word16`, `Word32`, or `Word64` - -Although JSON supports integer literals up to 64 bits, all integer types are encoded as strings for consistency. - -While the static type is not strictly required for decoding, it is provided to inform client of potential range. - -```json -{ - "type": "", - "value": "" -} -``` - -### Example - -```json -{ - "type": "UInt8", - "value": "123" -} -``` - ---- - -## Fixed Point Numbers - -`[U]Fix64` - -Although fixed point numbers are implemented as integers, JSON-Cadence uses a decimal string representation for readability. - -```json -{ - "type": "[U]Fix64", - "value": "." -} -``` - -### Example - -```json -{ - "type": "Fix64", - "value": "12.3" -} -``` - ---- - -## Array - -```json -{ - "type": "Array", - "value": [ - , - - // ... - ] -} -``` - -### Example - -```json -{ - "type": "Array", - "value": [ - { - "type": "Int16", - "value": "123" - }, - { - "type": "String", - "value": "test" - }, - { - "type": "Bool", - "value": true - } - ] -} -``` - ---- - -## Dictionary - -Dictionaries are encoded as a list of key-value pairs to preserve the deterministic ordering implemented by Cadence. - -```json -{ - "type": "Dictionary", - "value": [ - { - "key": "", - "value": - }, - ... - ] -} -``` - -### Example - -```json -{ - "type": "Dictionary", - "value": [ - { - "key": { - "type": "UInt8", - "value": "123" - }, - "value": { - "type": "String", - "value": "test" - } - } - ], - // ... -} -``` - ---- - -## Composites (Struct, Resource, Event, Contract, Enum) - -Composite fields are encoded as a list of name-value pairs in the order in which they appear in the composite type declaration. - -```json -{ - "type": "Struct" | "Resource" | "Event" | "Contract" | "Enum", - "value": { - "id": "", - "fields": [ - { - "name": "", - "value": - }, - // ... - ] - } -} -``` - -### Example - -```json -{ - "type": "Resource", - "value": { - "id": "0x3.GreatContract.GreatNFT", - "fields": [ - { - "name": "power", - "value": {"type": "Int", "value": "1"} - } - ] - } -} -``` - ---- - -## Path - -```json -{ - "type": "Path", - "value": { - "domain": "storage" | "private" | "public", - "identifier": "..." - } -} -``` - -### Example - -```json -{ - "type": "Path", - "value": { - "domain": "storage", - "identifier": "flowTokenVault" - } -} -``` - ---- - -## Type Value - -```json -{ - "type": "Type", - "value": { - "staticType": - } -} -``` - -### Example - -```json -{ - "type": "Type", - "value": { - "staticType": { - "kind": "Int", - } - } -} -``` - ---- - -## Capability - -```json -{ - "type": "Capability", - "value": { - "path": , - "address": "0x0", // as hex-encoded string with 0x prefix - "borrowType": , - } -} -``` - -### Example - -```json -{ - "type": "Capability", - "value": { - "path": { - "type": "Path", - "value": { - "domain": "public", - "identifier": "someInteger" - } - }, - "address": "0x1", - "borrowType": { - "kind": "Int" - } - } -} -``` - ---- - -## Functions - -```json -{ - "type": "Function", - "value": { - "functionType": - } -} -``` - -Function values can only be exported, they cannot be imported. - -### Example - -```json -{ - "type": "Function", - "value": { - "functionType": { - "kind": "Function", - "typeID": "fun():Void", - "parameters": [], - "return": { - "kind": "Void" - } - } - } -} -``` - ---- - -# Types - -## Simple Types - -These are basic types like `Int`, `String`, or `StoragePath`. - -```json -{ - "kind": "Any" | "AnyStruct" | "AnyResource" | "AnyStructAttachment" | "AnyResourceAttachment" | "Type" | - "Void" | "Never" | "Bool" | "String" | "Character" | - "Bytes" | "Address" | "Number" | "SignedNumber" | - "Integer" | "SignedInteger" | "FixedPoint" | - "SignedFixedPoint" | "Int" | "Int8" | "Int16" | - "Int32" | "Int64" | "Int128" | "Int256" | "UInt" | - "UInt8" | "UInt16" | "UInt32" | "UInt64" | "UInt128" | - "UInt256" | "Word8" | "Word16" | "Word32" | "Word64" | - "Fix64" | "UFix64" | "Path" | "CapabilityPath" | "StoragePath" | - "PublicPath" | "PrivatePath" | "AuthAccount" | "PublicAccount" | - "AuthAccount.Keys" | "PublicAccount.Keys" | "AuthAccount.Contracts" | - "PublicAccount.Contracts" | "DeployedContract" | "AccountKey" | "Block" -} -``` - -### Example - -```json -{ - "kind": "UInt8" -} -``` - ---- - -## Optional Types - -```json -{ - "kind": "Optional", - "type": -} -``` - -### Example - -```json -{ - "kind": "Optional", - "type": { - "kind": "String" - } -} -``` - ---- - -## Variable Sized Array Types - -```json -{ - "kind": "VariableSizedArray", - "type": -} -``` - -### Example - -```json -{ - "kind": "VariableSizedArray", - "type": { - "kind": "String" - } -} -``` - ---- - -## Constant Sized Array Types - -```json -{ - "kind": "ConstantSizedArray", - "type": , - "size": , -} -``` - -### Example - -```json -{ - "kind": "ConstantSizedArray", - "type": { - "kind": "String" - }, - "size":3 -} -``` - ---- - -## Dictionary Types - -```json -{ - "kind": "Dictionary", - "key": , - "value": -} -``` - -### Example - -```json -{ - "kind": "Dictionary", - "key": { - "kind": "String" - }, - "value": { - "kind": "UInt16" - }, -} -``` - ---- - -## Composite Types - -```json -{ - "kind": "Struct" | "Resource" | "Event" | "Contract" | "StructInterface" | "ResourceInterface" | "ContractInterface", - "type": "", // this field exists only to keep parity with the enum structure below; the value must be the empty string - "typeID": "", - "initializers": [ - , - - // ... - ], - "fields": [ - , - - // ... - ], -} -``` - -### Example - -```json -{ - "kind": "Resource", - "type": "", - "typeID": "0x3.GreatContract.GreatNFT", - "initializers":[ - [ - { - "label": "foo", - "id": "bar", - "type": { - "kind": "String" - } - } - ] - ], - "fields": [ - { - "id": "foo", - "type": { - "kind": "String" - } - } - ] -} -``` - ---- - -## Field Types - -```json -{ - "id": "", - "type": -} -``` - -### Example - -```json -{ - "id": "foo", - "type": { - "kind": "String" - } -} -``` - ---- - -## Parameter Types - -```json -{ - "label": "