+```
+
+Example using [Flow Go SDK](../../tools/clients/flow-go-sdk/index.md)
+```
+package main
+
+import (
+ "context"
+ "fmt"
+ "github.com/onflow/flow-go-sdk"
+ client "github.com/onflow/flow-go-sdk/access/grpc"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/credentials/insecure"
+)
+
+func main() {
+
+ // the Flow mainnet community Access node API endpoint
+ accessNodeAddress := "access.mainnet.nodes.onflow.org:9000"
+
+ maxGRPCMessageSize := 1024 * 1024 * 20 // to accommodate for the large transaction payload
+
+ // create a gRPC client for the Access node
+ accessNodeClient, err := client.NewClient(accessNodeAddress,
+ grpc.WithTransportCredentials(insecure.NewCredentials()),
+ grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(maxGRPCMessageSize)))
+ if err != nil {
+ fmt.Println("err:", err.Error())
+ panic(err)
+ }
+
+ ctx := context.Background()
+
+ txID := flow.HexToID("84eca4ff612ef70047d60510710cca872c8a17c1bd9f63686e74852b6382cc84")
+
+ rewardsTxResult, err := accessNodeClient.GetTransactionResult(ctx, txID)
+ if err != nil {
+ panic(err)
+ }
+
+ for _, event := range rewardsTxResult.Events {
+ fmt.Println("Event type: " + event.Type)
+ fmt.Println("Event: " + event.Value.String())
+ fmt.Println("Event payload: " + string(event.Payload))
+ }
+}
+```
+
+=== networks/staking/07-staking-scripts-events.md ===
+---
+title: Query Staking Info with Scripts or Events
+sidebar_label: Staking Scripts and Events
+---
+
+# Introduction
+
+The staking contract stores a lot of different state, and the state is constantly changing.
+As an external party, there are two ways to keep track of these state changes.
+You can either use Cadence scripts to query the state of the contract at any given time,
+or you can monitor events that are emitted by the staking contract to be notified of any important occurances.
+
+# Query Information with Scripts
+
+## Get the list of proposed nodes for the next epoch:
+
+`FlowIDTableStaking.getProposedNodeIDs()`: Returns an array of node IDs for proposed nodes.
+Proposed nodes are nodes that have enough staked and committed for the next epoch
+to be above the minimum requirement and have been selected to participate in the next epoch.
+This means that new access nodes that have not been selected with the random slot selection algorithm
+will not be included in this list.
+
+You can use the **Get Proposed Table**([SC.05](../../build/core-contracts/06-staking-contract-reference.md#getting-staking-info-with-scripts)) script for retrieving this info.
+
+This script requires no arguments.
+
+## Get the list of all nodes that are currently staked:
+
+`FlowIDTableStaking.getStakedNodeIDs()` and ``FlowIDTableStaking.getParticipantNodeList()`:
+Returns an array of nodeIDs that are currently staked.
+Staked nodes are nodes that are staked and participating in the current epoch.
+
+You can use the **Get Current Table**([SC.04](../../build/core-contracts/06-staking-contract-reference.md#getting-staking-info-with-scripts)) script for retrieving this info.
+
+This script requires no arguments.
+
+## Get the list of all Candidate Nodes
+
+`getCandidateNodeList(): {UInt8: {String: Bool}}`:
+Returns a dictionary of nodes that are candidates to stake in the next epoch
+but are not staked in the current epoch.
+
+You can use the [**Get Candidate Node List**](https://github.com/onflow/flow-core-contracts/blob/master/contracts/FlowIDTableStaking.cdc#L1762) script for retrieving this info.
+
+This script requires no arguments.
+
+## Get all of the info associated with a single node staker:
+
+`FlowIDTableStaking.NodeInfo(nodeID: String)`: Returns a `NodeInfo` struct with all of the metadata
+associated with the specified node ID. You can see the `NodeInfo` definition in the [FlowIDTableStaking
+smart contract.](https://github.com/onflow/flow-core-contracts/blob/master/contracts/FlowIDTableStaking.cdc#L254)
+
+You can use the **Get Node Info**([SC.08](../../build/core-contracts/06-staking-contract-reference.md#getting-staking-info-with-scripts)) script
+with the following arguments:
+
+| Argument | Type | Description |
+| ---------- | -------- | -------------------------------------- |
+| **nodeID** | `String` | The node ID of the node to search for. |
+
+You can also query the info from an address that uses the staking collection by using the **Get Node Info From Address**([SCO.15](../../build/core-contracts/11-staking-collection.md#scripts)) script
+with the following arguments:
+
+| Argument | Type | Description |
+| ----------- | --------- | ------------------------------------------------- |
+| **address** | `Address` | The address of the account that manages the nodes. |
+
+## Get the total committed balance of a node (with delegators):
+
+`FlowIDTableStaking.NodeInfo(_ nodeID: String).totalCommittedWithDelegators()`: Returns the total committed balance for a node,
+which is their total tokens staked + committed, plus all of the staked + committed tokens of all their delegators.
+
+You can use the **Get Node Total Commitment**([SC.09](../../build/core-contracts/06-staking-contract-reference.md#getting-staking-info-with-scripts)) script
+with the following argument:
+
+| Argument | Type | Description |
+| ---------- | -------- | -------------------------------------- |
+| **nodeID** | `String` | The node ID of the node to search for. |
+
+## Get the total committed balance of a node (without delegators):
+
+`FlowIDTableStaking.NodeInfo(_ nodeID: String).totalCommittedWithoutDelegators()`: Returns the total committed balance for a node,
+which is their total tokens staked + committed, plus all of the staked + committed tokens of all their delegators.
+
+You can use the **Get Only Node Total Commitment**([SC.11](../../build/core-contracts/06-staking-contract-reference.md#getting-staking-info-with-scripts)) script
+with the following argument:
+
+| Argument | Type | Description |
+| ---------- | -------- | -------------------------------------- |
+| **nodeID** | `String` | The node ID of the node to search for. |
+
+## Get all the info associated with a single delegator:
+
+`FlowIDTableStaking.DelegatorInfo(nodeID: String, delegatorID: UInt32)`: Returns a `DelegatorInfo` struct with all of the metadata
+associated with the specified node ID and delegator ID. You can see the `DelegatorInfo` definition in the [FlowIDTableStaking
+smart contract.](https://github.com/onflow/flow-core-contracts/blob/master/contracts/FlowIDTableStaking.cdc#L375)
+
+You can use the **Get Delegator Info**([SC.10](../../build/core-contracts/06-staking-contract-reference.md#getting-staking-info-with-scripts))
+script with the following arguments:
+
+| Argument | Type | Description |
+| --------------- | -------- | -------------------------------------------- |
+| **nodeID** | `String` | The node ID that the delegator delegates to. |
+| **delegatorID** | `String` | The ID of the delegator to search for. |
+
+You can also query the info from an address by using the **Get Delegator Info From Address**([SCO.16](../../build/core-contracts/11-staking-collection.md#scripts)) script
+with the following arguments:
+
+| Argument | Type | Description |
+| ----------- | --------- | ------------------------------------------------------ |
+| **address** | `Address` | The address of the account that manages the delegator. |
+
+## Get the delegation cut percentage:
+
+`FlowIDTableStaking.getRewardCutPercentage(): UFix64`: Returns a `UFix64` number for the cut of delegator rewards that each node operator takes.
+
+You can use the **Get Cut Percentage**([SC.01](../../build/core-contracts/06-staking-contract-reference.md#getting-staking-info-with-scripts)) script to retrieve this info.
+
+This script requires no arguments.
+
+## Get the minimum stake requirements:
+
+`FlowIDTableStaking.getMinimumStakeRequirements(): {UInt8: UFix64}`: Returns a mapping
+for the stake requirements for each node type.
+
+You can use the **Get stake requirements**([SC.02](../../build/core-contracts/06-staking-contract-reference.md#getting-staking-info-with-scripts)) script to retrieve this info.
+
+This script requires no arguments.
+
+## Get the total weekly reward payout:
+
+`FlowIDTableStaking.getEpochTokenPayout(): UFix64`: Returns a `UFix64` value for the total number of FLOW paid out each epoch (week).
+
+You can use the **Get weekly payout**([SC.03](../../build/core-contracts/06-staking-contract-reference.md#getting-staking-info-with-scripts)) script to retrieve this info.
+
+This script requires no arguments.
+
+## Get the total FLOW staked:
+
+You can use the **Get total FLOW staked**([SC.06](../../build/core-contracts/06-staking-contract-reference.md#getting-staking-info-with-scripts)) script to retrieve this info.
+
+This script requires no arguments.
+
+## Get the total FLOW staked by all the nodes of a single node role:
+
+You can use the **Get total FLOW staked by node type**([SC.07](../../build/core-contracts/06-staking-contract-reference.md#getting-staking-info-with-scripts)) script
+with the following arguments:
+
+| Argument | Type | Description |
+| ------------ | ------- | ------------------------------- |
+| **nodeType** | `UInt8` | The type of node to search for. |
+
+
+# Staking Events
+
+Staking events can be queried using the Go or JavaScript SDKs to extract useful notifications and information about the
+state of the staking process.
+
+## Global Staking and Epoch Events
+
+### NewEpoch
+
+```cadence
+access(all) event NewEpoch(totalStaked: UFix64, totalRewardPayout: UFix64, newEpochCounter: UInt64)
+```
+
+| Field | Type | Description |
+| ---- | ---- | ----- |
+| totalStaked | UFix64 | The total number of tokens staked for the new Epoch |
+| totalRewardPayout | UFix64 | The total number of tokens that will be paid as rewards for this epoch |
+| newEpochCounter | UInt64 | The epoch counter for this new epoch |
+
+Emitted by `FlowIDTableStaking.Admin.moveTokens()` when the tokens are moved between pools, which signals a new epoch.
+
+### NewWeeklyPayout
+
+```cadence
+access(all) event NewWeeklyPayout(newPayout: UFix64)
+```
+
+| Field | Type | Description |
+| --------- | ------ | ------------------------------------------------------------------ |
+| newPayout | UFix64 | The new number of tokens that will be paid at the end of the epoch |
+
+Emitted by `FlowIDTableStaking.Admin.setEpochTokenPayout()` when the Admin changes the total tokens paid at the end of the epoch.
+
+After this event the `epochTokenPayout` is equal to the new value.
+
+## Node Events
+
+These are events that concern the operation of a node.
+
+### NewNodeCreated
+
+```cadence
+access(all) event NewNodeCreated(nodeID: String, role: UInt8, amountCommitted: UFix64)
+```
+
+| Field | Type | Description |
+| ---- | ------ | ------- |
+| nodeID | String | The unique ID string for the node. 32 bytes. Usually the hash of the node's public key. |
+| role | UInt8 | The node's role type. From 1 to 5 inclusive. |
+| amountCommitted | UFix64 | The amount of FLOW tokens staked to register the node. This is determined by the `role`. |
+
+Emitted by `FlowIDTableStaking.NodeRecord.init()` when a new node is successfully created.
+
+After this event is emitted for your node, you can begin to perform staking transactions using it.
+
+### NodeRemovedAndRefunded
+
+```cadence
+access(all) event NodeRemovedAndRefunded(nodeID: String, amount: UFix64)
+```
+
+| Field | Type | Description |
+| ------ | ------ | --------------------------------------------------------------------------------------------------------------- |
+| nodeID | String | The unique ID string for the node. 32 bytes. The same value emitted in the `NewNodeCreated` event for the node. |
+| amount | UFix64 | The amount of FLOW tokens returned to the node. |
+
+Emitted by `FlowIDTableStaking.Admin.endStakingAuction()` if the node is being removed from the next epoch
+due to a failure to meet the minimum requirements of committed tokens for the next epoch.
+
+After this event, the refunded FLOW tokens will be part of the node's `tokensUnstaked` balance.
+
+## Token Events
+
+These are events that concern the direct usage of FLOW tokens - staking or unstaking locked tokens, withdrawing rewards, etc.
+
+Events emitted when using delegation are described in the next section.
+
+### TokensCommitted
+
+```cadence
+access(all) event TokensCommitted(nodeID: String, amount: UFix64)
+```
+
+| Field | Type | Description |
+| ------ | ------ | ----------- |
+| nodeID | String | The unique ID string for the node. 32 bytes. The same value emitted in the `NewNodeCreated` event for the node. |
+| amount | UFix64 | The amount of additional FLOW tokens committed to the node. |
+
+Emitted whenever additional tokens are staked on the node for the following epoch. Specifically:
+
+1. By `FlowIDTableStaking.NodeStaker.stakeNewTokens()` when new tokens (tokens that have not previously been staked) are added to the system
+ to stake on the node during the next epoch.
+2. By `FlowIDTableStaking.NodeStaker.stakeUnstakedTokens()` when unstaked tokens (tokens that were previously staked and then unstaked)
+ are staked again with the node for the next epoch.
+3. By `FlowIDTableStaking.NodeStaker.stakeRewardedTokens()` when reward tokens (tokens paid in return for previous staking)
+ are staked with the node for the next epoch.
+
+After this event, the FLOW tokens will be part of the node's `tokensCommitted` balance.
+
+### TokensStaked
+
+```cadence
+access(all) event TokensStaked(nodeID: String, amount: UFix64)
+```
+
+| Field | Type | Description |
+| ------ | ------ | ---------- |
+| nodeID | String | The unique ID string for the node. 32 bytes. The same value emitted in the `NewNodeCreated` event for the node. |
+| amount | UFix64 | The amount of FLOW tokens staked to the node. |
+
+Emitted by `FlowIDTableStaking.Admin.moveTokens()` at the end of an epoch if committed tokens are being added to the node's tokensStaked balance.
+
+After this event, the tokens will be part of the node's staked balance.
+
+### TokensUnstaking
+
+```cadence
+access(all) event TokensUnstaking(nodeID: String, amount: UFix64)
+```
+
+| Field | Type | Description |
+| ------ | ------ | --------- |
+| nodeID | String | The unique ID string for the node. 32 bytes. The same value emitted in the `NewNodeCreated` event for the node. |
+| amount | UFix64 | The amount of FLOW tokens unstaked from the node. |
+
+Emitted by `FlowIDTableStaking.Admin.moveTokens()` at the end of an epoch if
+a node operator's staked tokens are being unstaked in response to a request from the node operator.
+After this event, the tokens will be a part of the node operator's `tokensUnstaking` balance, where they are held for a whole epoch "unstaking period" with no rewards.
+
+### TokensUnstaked
+
+```cadence
+access(all) event TokensUnstaked(nodeID: String, amount: UFix64)
+```
+
+| Field | Type | Description |
+| ------ | ------ | ---------- |
+| nodeID | String | The unique ID string for the node. 32 bytes. The same value emitted in the `NewNodeCreated` event for the node. |
+| amount | UFix64 | The amount of FLOW tokens unstaked from the node. |
+
+Emitted by `FlowIDTableStaking.NodeStaker.requestUnstaking()` and `FlowIDTableStaking.Admin.moveTokens()`
+when tokens are deposited into the `tokensUnstaked` pool:
+
+### RewardsPaid
+
+```cadence
+access(all) event RewardsPaid(nodeID: String, amount: UFix64)
+```
+
+| Field | Type | Description |
+| ------ | ------ | ---------- |
+| nodeID | String | The unique ID string for the node. 32 bytes. The same value emitted in the `NewNodeCreated` event for the node. |
+| amount | UFix64 | The amount of FLOW tokens paid to the node this epoch as a reward. |
+
+Emitted by `FlowIDTableStaking.Admin.payRewards()` at the end of the epoch to pay rewards to node operators based on the tokens that they have staked.
+
+After this event, the reward tokens will be part of the node's tokensRewarded balance.
+
+The Delegator rewards are paid at the same time, see `DelegatorRewardsPaid` below.
+
+### UnstakedTokensWithdrawn
+
+```cadence
+access(all) event UnstakedTokensWithdrawn(nodeID: String, amount: UFix64)
+```
+
+| Field | Type | Description |
+| ------ | ------ | ---------- |
+| nodeID | String | The unique ID string for the node. 32 bytes. The same value emitted in the `NewNodeCreated` event for the node. |
+| amount | UFix64 | The amount of unstaked FLOW tokens that the node operator is withdrawing. |
+
+Emitted by `FlowIDTableStaking.NodeStaker.withdrawUnstakedTokens()` when the node operator calls that function to withdraw part or all of their
+unstaked tokens balance.
+
+After this event, the FLOW tokens will be withdrawn to a newly created `FungibleToken.Vault` which the caller can deposit to the vault of their choice.
+
+### RewardTokensWithdrawn
+
+```cadence
+access(all) event RewardTokensWithdrawn(nodeID: String, amount: UFix64)
+```
+
+| Field | Type | Description |
+| ------ | ------ | ---------- |
+| nodeID | String | The unique ID string for the node. 32 bytes. The same value emitted in the `NewNodeCreated` event for the node. |
+| amount | UFix64 | The amount of rewarded FLOW tokens that the node operator is withdrawing. |
+
+Emitted by `FlowIDTableStaking.NodeStaker.withdrawRewardedTokens()` when the node operator calls that function to withdraw part or all of their
+reward tokens balance.
+
+After this event, the FLOW tokens will be withdrawn to a newly created `FungibleToken.Vault` which the caller can deposit to the vault of their choice.
+
+## Delegator Events
+
+These are events that concern FLOW token delegation.
+
+### NewDelegatorCreated
+
+```cadence
+access(all) event NewDelegatorCreated(nodeID: String, delegatorID: UInt32)
+```
+
+| Field | Type | Description |
+| ----------- | ------ | ---------- |
+| nodeID | String | The unique ID string for the node. 32 bytes. The same value emitted in the `NewNodeCreated` event for the node. |
+| delegatorID | UFix64 | The ID for the new delegator. Unique within the node but not globally. |
+
+Emitted by `FlowIDTableStaking.Admin.registerNewDelegator()` when the node operator registers a new delegator for the node.
+
+Note that the delegatorID is unique within the node but is not globally unique.
+
+After this event, the new delegator is registered with the node.
+
+### DelegatorTokensCommitted
+
+```cadence
+access(all) event DelegatorTokensCommitted(nodeID: String, delegatorID: UInt32, amount: UFix64)
+```
+
+| Field | Type | Description |
+| ----------- | ------ | ---------- |
+| nodeID | String | The unique ID string for the node. 32 bytes. The same value emitted in the `NewNodeCreated` event for the node. |
+| delegatorID | UInt32 | The ID for the delegator. |
+| amount | UFix64 | The amount of additional FLOW tokens committed to the node. |
+
+Emitted whenever additional tokens are committed for a delegator for the following epoch. Specifically:
+
+1. By `FlowIDTableStaking.NodeDelegator.delegateNewTokens()` when new tokens (tokens that have not previously been staked) are added to the system
+ to stake with the delegator during the next epoch.
+2. By `FlowIDTableStaking.NodeDelegator.delegateUnstakedTokens()` when unstaked tokens (tokens that were previously staked and then unstaked)
+ are staked again with the delegator for the next epoch.
+3. By `FlowIDTableStaking.NodeDelegator.delegateRewardedTokens()` when reward tokens (tokens paid in return for previous staking)
+ are staked with the delegator for the next epoch.
+
+After this event, the FLOW tokens will be part of the delegator's `tokensCommitted` balance.
+
+### DelegatorTokensStaked
+
+```cadence
+access(all) event DelegatorTokensStaked(nodeID: String, delegatorID: UInt32, amount: UFix64)
+```
+
+| Field | Type | Description |
+| ----------- | ------ | --------- |
+| nodeID | String | The unique ID string for the node. 32 bytes. The same value emitted in the `NewNodeCreated` event for the node. |
+| delegatorID | UInt32 | The ID for the delegator. |
+| amount | UFix64 | The amount of FLOW tokens staked to the node. |
+
+Emitted by `FlowIDTableStaking.Admin.moveTokens()` at the end of an epoch if committed tokens are being added to the delegator's tokensStaked balance.
+
+After this event, the tokens will be part of the delegator's staked balance.
+
+### DelegatorTokensUnstaking
+
+```cadence
+access(all) event DelegatorTokensUnstaking(nodeID: String, delegatorID: UInt32, amount: UFix64)
+```
+
+| Field | Type | Description |
+| ----------- | ------ | -----------|
+| nodeID | String | The unique ID string for the node. 32 bytes. The same value emitted in the `NewNodeCreated` event for the node. |
+| delegatorID | UInt32 | The ID for the delegator. |
+| amount | UFix64 | The amount of FLOW tokens unstaked from the node. |
+
+Emitted by `FlowIDTableStaking.Admin.moveTokens()` at the end of an epoch if
+a delegator's staked tokens are being unstaked in response to a request from the delegator.
+After this event, the tokens will be a part of the delegator's `tokensUnstaking` balance, where they are held for a whole epoch "unstaking period" with no rewards.
+
+### DelegatorTokensUnstaked
+
+```cadence
+access(all) event DelegatorTokensUnstaked(nodeID: String, delegatorID: UInt32, amount: UFix64)
+```
+
+| Field | Type | Description |
+| ----------- | ------ | ---------- |
+| nodeID | String | The unique ID string for the node. 32 bytes. The same value emitted in the `NewNodeCreated` event for the node. |
+| delegatorID | UInt32 | The ID for the delegator. |
+| amount | UFix64 | The amount of FLOW tokens unstaked from the node. |
+
+Emitted by `FlowIDTableStaking.NodeDelegator.requestUnstaking()` and `FlowIDTableStaking.Admin.moveTokens()`
+when tokens are deposited into the delegator's `tokensUnstaked` pool:
+
+### DelegatorRewardsPaid
+
+```cadence
+access(all) event DelegatorRewardsPaid(nodeID: String, delegatorID: UInt32, amount: UFix64)
+```
+
+| Field | Type | Description |
+| ----------- | ------ | ---------- |
+| nodeID | String | The unique ID string for the node. 32 bytes. The same value emitted in the `NewNodeCreated` event for the node. |
+| delegatorID | UFix64 | The ID for the delegator. Unique within the node but not globally. |
+| amount | UFix64 | The amount of rewarded FLOW tokens that the delegator is paid. |
+
+Emitted by `FlowIDTableStaking.Admin.payRewards()` at the end of an epoch when rewards are being paid.
+
+After this event is emitted, the reward tokens will be part of the delegator's tokensRewarded balance.
+
+The Node rewards are paid at the same time, see `RewardsPaid` above.
+
+### DelegatorUnstakedTokensWithdrawn
+
+```cadence
+access(all) event DelegatorUnstakedTokensWithdrawn(nodeID: String, delegatorID: UInt32, amount: UFix64)
+```
+
+| Field | Type | Description |
+| ----------- | ------ | ---------- |
+| nodeID | String | The unique ID string for the node. 32 bytes. The same value emitted in the `NewNodeCreated` event for the node. |
+| delegatorID | UFix64 | The ID for the delegator. Unique within the node but not globally. |
+| amount | UFix64 | The amount of unstaked FLOW tokens that the delegator is withdrawing. |
+
+Emitted by `FlowIDTableStaking.NodeDelegator.withdrawUnstakedTokens()` when the delegator calls that function to withdraw part or all of their
+unstaked tokens balance.
+
+After this event, the FLOW tokens will be withdrawn to a newly created `FungibleToken.Vault` which the caller can deposit to the vault of their choice.
+
+### DelegatorRewardTokensWithdrawn
+
+```cadence
+access(all) event DelegatorRewardTokensWithdrawn(nodeID: String, delegatorID: UInt32, amount: UFix64)
+```
+
+| Field | Type | Description |
+| ----------- | ------ | ---------- |
+| nodeID | String | The unique ID string for the node. 32 bytes. The same value emitted in the `NewNodeCreated` event for the node. |
+| delegatorID | UFix64 | The ID for the delegator. Unique within the node but not globally. |
+| amount | UFix64 | The amount of rewarded FLOW tokens that the delegator is withdrawing. |
+
+Emitted by `FlowIDTableStaking.NodeDelegator.withdrawRewardedTokens()` when the delegator calls that function to withdraw part or all of their
+unstaked tokens balance.
+
+After this event, the FLOW tokens will be withdrawn to a newly created `FungibleToken.Vault` which the caller can deposit to the vault of their choice.
+
+
+=== networks/staking/06-technical-overview.md ===
+---
+title: Staking Technical Overview
+sidebar_label: Staking Technical Overview
+description: Technical Overview of the Flow Staking Auction Phase
+---
+
+
+ If you haven't read the Introduction, please read that first. That document
+ provides a non-technical overview of staking on Flow for all users and is a
+ necessary prerequisite to this document.
+
+
+ This document assumes you have some technical knowledge about the Flow
+ blockchain and programming environment.
+
+
+# Staking
+
+This document describes the functionality of the
+[core identity table and staking smart contract](https://github.com/onflow/flow-core-contracts/blob/master/contracts/FlowIDTableStaking.cdc).
+It gives an overview of the process of epochs, staking as a node, and delegation. It is an important prerequisite
+to understand before proceeding with any other technical integration or interaction with the Flow Protocol,
+but does not provide step-by-step instructions for how to perform specific actions. See the
+[Staking Collection Docs for instructions](./14-staking-collection.md)
+
+This document also describes how to read public staking data from the contract.
+Anyone can read public data from the staking smart contract with these instructions.
+
+The transactions described in this document are contained in the
+[`flow-core-contracts/transactions/idTableStaking/`](https://github.com/onflow/flow-core-contracts/tree/master/transactions/idTableStaking)
+directory. You can see the text of all the transactions used to interact with the smart contract there.
+
+## Smart Contract Summary
+
+The Flow staking smart contract manages a record of stakers who have staked tokens for the network.
+Users who want to stake can register with the staking contract at any time during the staking auction,
+and their tokens will be locked for staking until they request to unstake them.
+
+You should already understand from reading the [epoch documentation](./04-epoch-preparation.md)
+that an epoch lasts roughly a week. The `FlowIDTableStaking` contract focuses on the identity table
+and staking part of the epoch schedule.
+
+Epoch Schedule from the perspective of the `FlowIDTableStaking` contract:
+
+1. **Start of Epoch:** Generic metadata about the current epoch is updated and shared
+ and the staking auction is enabled.
+2. **Staking Auction:** Stakers can perform any action they want to manage their stake, like
+ initially registering, staking new tokens, unstaking tokens, or withdrawing rewards.
+ This phase takes up the vast majority of time in the epoch.
+3. **End Staking Auction:** Stakers cannot perform any more staking actions
+ until the start of the next epoch/staking auction.
+4. **Remove Insufficiently Staked Nodes:** All node operators who don't meet the minimum
+ or are not operating their node properly will be removed.
+5. **Randomly Assign Nodes to New Slots:** Each node type has a configurable
+ number of nodes that can operate during any given epoch.
+ The contract will randomly select nodes from the list of newly staked and approved nodes
+ to add them to the ID table. Once all the slots have been filled, the remaining nodes are refunded
+ and can apply again for the next epoch if there are slots available.
+6. **Rewards Calculation:** Calculate rewards for all the node operators staked in the current epoch.
+7. **Move tokens between pools.** (See the token pools section for the order of movements)
+8. **End Epoch:** Set the reward payout for the upcoming epoch and go to the top of this list.
+9. **Rewards Payout:** Pay rewards to all the node operators staked
+ from the previous epoch using the calculation from earlier in the epoch.
+
+The `FlowIDTableStaking` contract manages the identity table, and all of these phases.
+Control of these phases is controlled by the `FlowIDTableStaking.Admin` resource
+object stored in the Flow Epoch account storage.
+The `FlowEpoch` smart contract uses this resource to autonomously manage the functioning of the network. It is decentralized and managed by the node software, smart contracts,
+and democratically by all the stakers in the network.
+
+## Staking as a Node Operator
+
+For a node to stake, node operators first need to generate their staking key,
+staking key proof-of-possesion, networking address, and networking key.
+
+The [node operation guide](../node-ops/index.md)
+describes how to run a node and generate node information.
+
+To generate a node ID, simply hash the staking key.
+
+Node operators need to determine the role of node they will be running
+(Collection, Consensus, Execution, Verification, or Access).
+
+
+ NOTE: Access Nodes are eligible to stake and have a staking minimum of 100 FLOW,
+ but will not receive rewards for their stake.
+ Please register as a different node type if you would like to receive rewards.
+
+
+Once the info has been determined:
+
+- Node role: `UInt8` (1 = Collection, 2 = Consensus, 3 = Execution, 4 = Verification, 5 = Access)
+- Node ID: 32 byte `String` (64 hex characters)
+- Networking Address: `String` (Length must be less than 510 characters and be a properly formatted IP address or hostname)
+- Networking Key: 64 byte `String` (128 hex characters, must be a valid ECDSA-P256 Key)
+- Staking Key: 96 byte `String` (192 hex characters, must be a valid BLS key)
+- Staking Key Proof of Possesion: (48 byte (96 hex characters) string)
+
+The node operator is ready to register their node.
+
+
+ NOTE: The staking smart contract validates that the strings for the keys are
+ valid public keys. The staking admin and node software also checks the keys
+ and networking address to make sure they are valid and if they are not, the
+ registered node will not be eligible to stake.
+
+
+To register a node, the node operator calls the
+[`addNodeRecord` function](https://github.com/onflow/flow-core-contracts/blob/master/contracts/FlowIDTableStaking.cdc#L1552)
+on the staking contract, providing all the node info and the tokens that they want to immediately stake, if any.
+
+This registers the node in the Flow node identity table
+and commits the specified tokens to stake during the next epoch.
+This also returns a special node operator object that is stored in the node operator's account.
+This object is used for staking, unstaking, and withdrawing rewards.
+
+Consensus and Collection nodes also need to create a separate machine account
+for use in the DKG and QC processes, respectively. This machine account creation
+is handled automatically by the staking collection smart contract.
+More information is in the [machine account documentation](./11-machine-account.md#creation).
+
+
+ The register node transaction only needs to be submitted once per node. A node
+ does not need to register every epoch. A registration cannot be used to manage
+ multiple nodes. Multiple nodes need to be registered separately (with the
+ Staking Collection).
+
+
+
+ Once a node operator has registered their node and its metadata, the metadata
+ cannot be modified. The only exception is the networking address, which can me
+ modified with the Update Networking Address transaction. If a node operator
+ wants to update any of their other metadata such as ID, keys, or role, they
+ need to unstake, withdraw their tokens, and register a completely new node.
+
+
+Once node operators have registered and have the special node object, they will be able
+to perform any of the valid staking options with it, assuming that they have
+the required amount of tokens to perform each operation.
+
+When the staking auction ends, if a node operator has committed less than the minimum stake required,
+[or if their node information is invalid and they haven't been approved by the network,](https://github.com/onflow/flow-core-contracts/blob/master/contracts/FlowIDTableStaking.cdc#L788)
+their committed tokens are moved to their unstaked pool, which they can withdraw from at any time.
+
+Nodes who did have enough tokens committed and are approved will have their
+[committed tokens moved to the staked state](https://github.com/onflow/flow-core-contracts/blob/master/contracts/FlowIDTableStaking.cdc#L923-L927)
+at the end of the epoch if they are selected as a node operator
+by the random node slot filling algorithm.
+There is a configurable cap on the number of nodes of each type,
+so if the number of selected nodes equals the cap, than newly registered nodes
+will not be added to the network until the cap is raised or other nodes unstake.
+
+If a node operator has users delegating to them, they cannot withdraw their own tokens
+such that their own staked tokens would fall below the minimum requirement for that node type.
+If they have delegators and try to submit [an unstaking transaction](https://github.com/onflow/flow-core-contracts/blob/master/contracts/FlowIDTableStaking.cdc#L510-L514)
+that would put their stake below the minimum, it will fail.
+
+If they want to unstake below the minimum, they must unstake all of their tokens using the special
+[`unstakeAll` method,](https://github.com/onflow/flow-core-contracts/blob/master/contracts/FlowIDTableStaking.cdc#L538)
+which also unstakes all of the tokens that have been delegated to them.
+
+Consequently, a node operator cannot accept delegation unless [their own stake is above the minimum.](https://github.com/onflow/flow-core-contracts/blob/master/contracts/FlowIDTableStaking.cdc#L1066)
+
+## Staking as a Delegator
+
+Every staked non-access node in the Flow network is eligible for delegation by any other user.
+The user only needs to know the node ID of the node they want to delegate to.
+
+To register as a delegator, the delegator submits a **Register Delegator**
+transaction that calls the [`registerNewDelegator function`](https://github.com/onflow/flow-core-contracts/blob/master/contracts/FlowIDTableStaking.cdc#L1590),
+providing the ID of the node operator they want to delegate to.
+This transaction should store the `NodeDelegator` object
+in the user's account, which is what they use to perform staking operations.
+
+Users are able to get a list of possible node IDs to delegate to via on-chain scripts.
+This information will also be provided off-chain, directly from the node operators or via
+third-party services. [Available node IDs are listed in a public repo.](https://github.com/onflow/flow/blob/master/nodeoperators/NodeOperatorList.md)
+
+The fee that node operators take from the rewards their delegators receive is 8%.
+A node operator cannot be delegated to unless the total tokens they have committed to stake
+are above the minimum requirement for their node types.
+
+The delegation logic keeps track of the amount of tokens each delegator has delegated for the node operator.
+When rewards are paid, the protocol [automatically takes the 8% cut](https://github.com/onflow/flow-core-contracts/blob/master/contracts/FlowIDTableStaking.cdc#L888-L898)
+of the delegator's rewards for the node operator
+and the delegator's rewards are deposited in the delegator's reward pool.
+
+## Staking Operations Available to All Stakers
+
+Regardless of whether they are a node operator or delegator, a staker has access
+to all the same staking operations, outlined below.
+Specific implementations of these transactions are detailed in the [Staking Collection Docs](./14-staking-collection.md)
+
+### Stake More Tokens
+
+A staker can commit more tokens to stake for the next epoch at any time during the staking auction,
+and there are three different ways to do it.
+
+1. They can commit new tokens to stake by submitting a **stake_new_tokens** transaction,
+ which withdraws tokens from their account's flow token vault and commits them.
+2. They can commit tokens that are in their unstaked token pool, which holds the tokens
+ that they have unstaked. Submit a **stake_unstaked_tokens**
+ transaction to move the tokens from the unstaked pool to the committed pool.
+3. They can commit tokens that are in their rewarded token pool, which holds the tokens
+ they have been awarded. They submit a **stake_rewarded_tokens**
+ transaction to move the tokens from the rewards pool to the committed pool.
+
+### Cancel Committed Stake / Unstake Tokens
+
+At any time during the staking auction, a staker can submit a request to unstake tokens with a **request_unstaking** transaction.
+If there are tokens that have been committed but are not staked yet,
+they are moved to the unstaked pool and are available to withdraw.
+
+If the requested tokens are in the staked pool,
+it marks the specified amount of tokens to be unstaked at the end of the epoch.
+At the end of the epoch, the tokens are moved to the unstaking pool.
+They will sit in this pool for one (1) additional epoch,
+at which point they will be moved to the unstaked tokens pool.
+
+### Cancel an Unstake Request
+
+Unstaking requests are not fulfilled until the end of the epoch where they are submitted,
+so a staker can cancel the unstaking request before it is carried out.
+A staker can do this by submitting a **stake_unstaked_tokens** transaction, specifying
+the number of tokens of their unstake request they would like to cancel.
+If the specified number of tokens have been requested to unstake, the request will be canceled.
+
+### Withdraw Unstaked Tokens
+
+At any time, stakers are able to freely withdraw from their unstaked tokens pool
+with the **withdraw_unstaked** transaction.
+
+### Withdraw Rewarded Tokens
+
+Staking rewards are paid out at the end of every epoch based on how many tokens
+are in a users `tokensStaked` pool. Every staker's rewards
+are deposited into their rewarded tokens pool. Rewards can be withdrawn
+at any time by submitting a **withdraw_reward_tokens** transaction.
+
+These tokens are unlocked and can be transferred on-chain if desired, or re-staked.
+
+The source code for the staking contract and more transactions
+can be found in the [Flow Core Contracts GitHub Repository](https://github.com/onflow/flow-core-contracts).
+
+# Monitor Events from the Identity Table and Staking Contract
+
+See the [staking events document](./07-staking-scripts-events.md)
+for information about the events that can be emitted by the staking contract.
+
+# Appendix
+
+## Token Pools
+
+Each node operator has five token pools allocated to them:
+
+- **Committed Tokens:** Tokens that are committed for the next epoch.
+ They are automatically moved to the staked pool when the next epoch starts.
+- **Staked Tokens:** Tokens that are staked by the node operator for the current epoch.
+ They are only moved at the end of an epoch and if the staker
+ has submitted an unstaking request.
+- **Unstaking Tokens:** Tokens that have been unstaked,
+ but are not free to withdraw until the following epoch.
+- **Unstaked Tokens:** Tokens that are freely available to withdraw or re-stake.
+ Unstaked tokens go to this pool.
+- **Rewarded Tokens:** Tokens that are freely available to withdraw or re-stake.
+ Rewards are paid and deposited to the rewarded Pool after each epoch.
+
+At the end of every epoch, tokens are moved between pools in this order:
+
+1. All committed tokens will get moved either to the staked tokens pool,
+ or to the unstaked tokens pool (depending on if the registered node has met the minimum stake requirements).
+2. All committed tokens get moved to staked tokens pool.
+3. All unstaking tokens get moved to the unstaked tokens pool.
+4. All requested unstaking tokens get moved from the staked pool to the unstaking pool.
+
+
+=== networks/staking/05-epoch-scripts-events.md ===
+---
+title: Query Epoch Info with Scripts or Events
+sidebar_label: Epoch Scripts and Events
+toc_max_heading_level: 4
+---
+
+## Introduction
+
+The epoch contract stores a lot of different state, and the state is constantly changing.
+As an external party, there are two ways to keep track of these state changes.
+You can either use Cadence scripts to query the state of the contract at any given time,
+or you can monitor events that are emitted by the epoch contract to be notified of any important occurrences.
+
+## Monitor Epoch Service Events
+
+These events can be queried using the Go or JavaScript SDKs to extract useful notifications and information about the
+state of the epoch preparation protocol.
+
+### What is a Service Event?
+
+Service events are special messages that are generated by smart contracts and included in execution results.
+They enable communication between system smart contracts and the Flow protocol.
+In other words, they serve as a communication mechanism between the execution state and the protocol state.
+
+Concretely, service events are defined and emitted as events like any other in Cadence. An event is considered a service event when it is:
+
+- emitted within the service chunk
+- emitted from a smart contract deployed to the service account
+- conformant to an event allowlist
+
+Each block contains a system chunk. For each system chunk,
+all service events emitted are included in the corresponding execution result.
+
+When verifying the system chunk, verifier nodes will only produce result approvals
+when the system chunks included in the execution result are correct.
+Thus, the security of this communication mechanism is enforced by the verification system.
+
+When sealing a block containing a service event, the consensus committee will update the protocol state accordingly,
+depending on the semantics of the event.
+
+For example, a service event may indicate that a node's stake has diminished to the point where they should be ejected,
+in which case the consensus committee would mark that node as ejected in the protocol state.
+
+Service events are fundamentally asynchronous, due the lag between block execution and sealing.
+Consequently they are handled slightly differently than other protocol state updates.
+
+The diagram below illustrates the steps each service event goes through to be included in the protocol state.
+
+
+
+For conciseness, we say a service event is `sealed` when the block in which it was emitted is sealed,
+and we say a service event is `finalized` when the block containing the seal is finalized.
+
+### Event Descriptions
+
+#### `FlowEpoch.EpochStart`
+
+The Epoch Start service event is emitted by `FlowEpoch.startNewEpoch()`
+when the epoch commit phase ends and the Epoch Smart Contracts transition
+to the staking auction phase.
+It contains the relevant metadata for the new epoch that was generated during the last epoch:
+
+```cadence
+ access(all) event EpochStart (
+
+ /// The counter for the current epoch that is beginning
+ counter: UInt64,
+
+ /// The first view (inclusive) of the current epoch.
+ firstView: UInt64,
+
+ /// The last view (inclusive) of the current epoch's staking auction.
+ stakingAuctionEndView: UInt64,
+
+ /// The last view (inclusive) of the current epoch.
+ finalView: UInt64,
+
+ /// Total FLOW staked by all nodes and delegators for the current epoch.
+ totalStaked: UFix64,
+
+ /// Total supply of all FLOW for the current epoch
+ /// Includes the rewards that will be paid for the previous epoch
+ totalFlowSupply: UFix64,
+
+ /// The total rewards that will be paid out at the end of the current epoch.
+ totalRewards: UFix64,
+ )
+```
+
+#### `FlowEpoch.EpochSetup`
+
+The Epoch Setup service event is emitted by `FlowEpoch.startEpochSetup()`
+when the staking auction phase ends and the Epoch Smart Contracts transition to the Epoch Setup phase.
+It contains the finalized identity table for the upcoming epoch,
+as well as timing information for phase changes.
+
+```cadence
+access(all) event EpochSetup (
+
+ /// The counter for the upcoming epoch. Must be one greater than the
+ /// counter for the current epoch.
+ counter: UInt64,
+
+ /// Identity table for the upcoming epoch with all node information.
+ /// Includes:
+ /// nodeID, staking key, networking key, networking address, role,
+ /// staking information, weight, and more.
+ nodeInfo: [FlowIDTableStaking.NodeInfo],
+
+ /// The first view (inclusive) of the upcoming epoch.
+ firstView: UInt64,
+
+ /// The last view (inclusive) of the upcoming epoch.
+ finalView: UInt64,
+
+ /// The cluster assignment for the upcoming epoch. Each element in the list
+ /// represents one cluster and contains all the node IDs assigned to that
+ /// cluster, with their weights and votes
+ collectorClusters: [FlowClusterQC.Cluster],
+
+ /// The source of randomness to seed the leader selection algorithm with
+ /// for the upcoming epoch.
+ randomSource: String,
+
+ /// The deadlines of each phase in the DKG protocol to be completed in the upcoming
+ /// EpochSetup phase. Deadlines are specified in terms of a consensus view number.
+ /// When a DKG participant observes a finalized and sealed block with view greater
+ /// than the given deadline, it can safely transition to the next phase.
+ DKGPhase1FinalView: UInt64,
+ DKGPhase2FinalView: UInt64,
+ DKGPhase3FinalView: UInt64
+)
+```
+
+#### `FlowEpoch.EpochCommit`
+
+The `EpochCommit` service event is emitted when the Epoch Smart Contracts transition
+from the Epoch Setup phase to the Epoch Commit phase.
+It is emitted only when all preparation for the upcoming epoch (QC and DKG) has been completed.
+
+```cadence
+access(all) event EpochCommit (
+
+ /// The counter for the upcoming epoch. Must be equal to the counter in the
+ /// previous EpochSetup event.
+ counter: UInt64,
+
+ /// The result of the QC aggregation process. Each element contains
+ /// all the nodes and votes received for a particular cluster
+ /// QC stands for quorum certificate that each cluster generates.
+ clusterQCs: [FlowClusterQC.ClusterQC],
+
+ /// The resulting public keys from the DKG process, encoded as by the flow-go
+ /// crypto library, then hex-encoded.
+ /// Group public key is the first element, followed by the individual keys
+ dkgPubKeys: [String],
+)
+```
+
+
+## Query Information with Scripts
+
+The `FlowEpoch` smart contract stores important metadata about the current, proposed,
+and previous epochs. Metadata for all historical epochs is stored permanently
+in the Epoch Smart Contract's storage.
+
+```cadence
+access(all) struct EpochMetadata {
+
+ /// The identifier for the epoch
+ access(all) let counter: UInt64
+
+ /// The seed used for generating the epoch setup
+ access(all) let seed: String
+
+ /// The first view of this epoch
+ access(all) let startView: UInt64
+
+ /// The last view of this epoch
+ access(all) let endView: UInt64
+
+ /// The last view of the staking auction
+ access(all) let stakingEndView: UInt64
+
+ /// The total rewards that are paid out for the epoch
+ access(all) var totalRewards: UFix64
+
+ /// The reward amounts that are paid to each individual node and its delegators
+ access(all) var rewardAmounts: [FlowIDTableStaking.RewardsBreakdown]
+
+ /// Tracks if rewards have been paid for this epoch
+ access(all) var rewardsPaid: Bool
+
+ /// The organization of collector node IDs into clusters
+ /// determined by a round robin sorting algorithm
+ access(all) let collectorClusters: [FlowClusterQC.Cluster]
+
+ /// The Quorum Certificates from the ClusterQC contract
+ access(all) var clusterQCs: [FlowClusterQC.ClusterQC]
+
+ /// The public keys associated with the Distributed Key Generation
+ /// process that consensus nodes participate in
+ /// Group key is the last element at index: length - 1
+ access(all) var dkgKeys: [String]
+}
+```
+
+#### Get Epoch Metadata
+
+The `FlowEpoch` smart contract provides a public function, `FlowEpoch.getEpochMetadata()`
+to query the metadata for a particular epoch.
+
+You can use the **Get Epoch Metadata**([EP.01](../../build/core-contracts/07-epoch-contract-reference.md#getting-epoch-info)) script
+with the following arguments:
+
+| Argument | Type | Description |
+| ---------------- | ---------| --------------------------------------------- |
+| **epochCounter** | `UInt64` | The counter of the epoch to get metadata for. |
+
+#### Get Configurable Metadata
+
+The `FlowEpoch` smart contract also has a set of metadata that is configurable by the admin
+for phase lengths, number of collector clusters, and inflation percentage.
+
+```cadence
+access(all) struct Config {
+ /// The number of views in an entire epoch
+ access(all) var numViewsInEpoch: UInt64
+
+ /// The number of views in the staking auction
+ access(all) var numViewsInStakingAuction: UInt64
+
+ /// The number of views in each dkg phase
+ access(all) var numViewsInDKGPhase: UInt64
+
+ /// The number of collector clusters in each epoch
+ access(all) var numCollectorClusters: UInt16
+
+ /// Tracks the annualized percentage of FLOW total supply that is minted as rewards at the end of an epoch
+ /// Calculation for a single epoch would be (totalSupply * FLOWsupplyIncreasePercentage) / 52
+ access(all) var FLOWsupplyIncreasePercentage: UFix64
+}
+```
+
+You can use the **Get Configurable Metadata**([EP.02](../../build/core-contracts/07-epoch-contract-reference.md#getting-epoch-info)) script
+to get the list of configurable metadata:
+
+This script does not require any arguments.
+
+#### Get Epoch Counter
+
+The `FlowEpoch` smart contract always tracks the counter of the current epoch.
+
+You can use the **Get Epoch Counter**([EP.03](../../build/core-contracts/07-epoch-contract-reference.md#getting-epoch-info)) script
+to get the current epoch counter.
+
+This script does not require any arguments.
+
+#### Get Epoch Phase
+
+The `FlowEpoch` smart contract always tracks the active phase of the current epoch.
+
+```cadence
+access(all) enum EpochPhase: UInt8 {
+ access(all) case STAKINGAUCTION
+ access(all) case EPOCHSETUP
+ access(all) case EPOCHCOMMIT
+}
+```
+
+You can use the **Get Epoch Phase**([EP.04](../../build/core-contracts/07-epoch-contract-reference.md#getting-epoch-info)) script
+to get the current epoch phase.
+
+This script does not require any arguments.
+
+=== networks/staking/04-stake-slashing.md ===
+---
+title: Stake Slashing
+sidebar_position: 4
+description: How Flow enforces honest node behaviour
+---
+
+Flow slashes nodes only for acts that directly impact
+the security and integrity of the network and its shared execution state.
+Nodes are not slashed for liveness infractions.
+The protocol reserves slashing for maintaining the security of the protocol rather than its liveness.
+
+You can find more details on the conditions under which a node is slashed
+in the [Flow whitepapers](https://www.onflow.org/technical-paper).
+
+Direct stake slashing is not currently enforced by the protocol and staking contract.
+It will be handled on a case-by-case basis for the foreseeable future
+to ensure network participants have time to participate in the testing and rollout of slashing.
+
+There is a very basic form of slashing that is currently used, where
+nodes who have liveness issues during an epoch may have their rewards
+and their delegators' rewards reduced by a pre-determinded amount based on
+the severity of the liveness infractions. This amount is often 50%
+and is only taken from the stakers' rewards for a given epoch.
+Their staked FLOW is not touched at all.
+
+When slashing is enforced, slashable protocol violations must be adjudicated by a supermajority
+of more than 2/3 of the staked consensus nodes in order to take effect.
+If a node is found guilty of committing a slashable protocol violation,
+the consensus nodes directly deduct a fine from the node's stake.
+
+It is still TBD where the slashed tokens will be deposited.
+
+The remaining un-slashed stake is deposited back into node's unstaked pool
+at the end of the unstaking period.
+
+
+=== networks/staking/04-epoch-preparation.md ===
+---
+title: Epoch Preparation Protocol
+sidebar_label: Epoch Preparation Protocol
+description: Technical Overview of the Flow Epoch Protocol
+---
+
+
+ If you haven't read the staking introduction, please read that
+ first. That document provides a non-technical overview of staking on Flow for
+ all users and is a necessary prerequisite to this document.
+
+
+ This document assumes you have some technical knowledge about the Flow
+ blockchain and programming environment.
+
+
+# Epochs
+
+The epoch preparation protocol defines how information about the next epoch
+is determined and propagated to the protocol state.
+
+There are two primary actors in this protocol, the Epoch Smart Contracts, and the Consensus Committee:
+
+- [`Epoch Smart Contracts`](https://github.com/onflow/flow-core-contracts/blob/master/contracts/epochs) - the smart contracts that manage epochs:
+ - `FlowClusterQC` : Manages the quorum certificate generation for bootstrapping
+ the hotstuff consensus algorithm for each collector cluster.
+ - `FlowDKG` : Manages the Distributed Key Generation that consensus nodes participate
+ in to initialize the random beacon for each epoch.
+ - `FlowIDTableStaking` : Manages the source of truth for the identity table,
+ and enforces rules related to staking FLOW, delegating, paying rewards, and allocating token movements between epochs.
+ - `FlowEpoch` : Ties all of the previously mentioned contracts together to manage
+ the high level epoch lifecycle. `FlowEpoch` acts as a state machine that transitions
+ between different epoch phases when specific conditions from the other contracts are met and triggers important operations in the other smart contracts when phase changes happen.
+- `Consensus Committee` - the committee of consensus nodes for the current epoch
+
+This document describes the communication protocol between these two actors and the impact on the protocol state.
+
+It gives an overview of the process of epochs, the staking auction, and the epoch setup and commit phases.
+It is an important prerequisite to understand before proceeding with any other technical integration or interaction with the Flow Protocol,
+but does not provide step-by-step instructions for how to perform specific actions.
+
+The transactions described in this document are contained in the [`flow-core-contracts/transactions/epoch/`](https://github.com/onflow/flow-core-contracts/tree/master/transactions/epoch)
+directory. You can see the text of all the transactions used to interact with the smart contracts there.
+
+## Epochs Overview
+
+Only a pre-determined set of nodes is authorized to participate in the protocol at any given time.
+The set of authorized nodes is a-priori known to all network participants.
+This set is referred to as the **Identity Table**. An **Epoch** is defined as a period of time
+where the set of authorized nodes is constant (or can only shrink due to ejection of malicious nodes).
+
+At an Epoch switchover, which is the time when the network transitions from one epoch to the next,
+the set of authorized nodes can change. For each of Flow's node roles, the Flow protocol admits a protocol-determined number of nodes.
+
+For each Epoch, there is a [Staking Auction](./06-technical-overview.md) in which new potential node operators may submit Staking Commitments.
+All this is completely smart-contract based and handled through conventional transactions.
+
+After the Staking Auction is over, the protocol determines which commitments to accept and which to reject.
+The node operators whose staking commitments were accepted are added to the Identity Table for the next epoch,
+and become authorized participants at the next epoch switchover.
+Staked Nodes also can submit other operations to modify their existing stake, which are all carried out at the end of the current epoch.
+
+The smart contract that determines the nodes for the next Epoch has special privileges.
+Specifically, it is allowed to emit [Service Events](./05-epoch-scripts-events.md#monitor-epoch-service-events),
+which are how the execution state updates the consensus node-based protocol state.
+
+At the end of the staking auction, the epoch smart contracts conclude that they have now determined
+the set of nodes which will be running the network for the next Epoch, and the amount of FLOW that all the nodes have staked.
+The smart contract then emits a service event with this information.
+
+When processing the block with seat assignment, all network nodes (including future ones which are supposed to monitor the chain in anticipation)
+are thereby informed about the upcoming change.
+
+
+Note: At this point in the epoch (end of the staking auction),
+there is no change in participating nodes.
+The change in participating nodes happens at the end of the epoch.
+
+
+After the staking auction, there is an interim period of time until the new Epoch starts for the following tasks to be completed:
+- The epoch smart contract runs the cluster assignment algorithm for all the collector nodes
+and each collector node will vote for the root block of their respective clusters
+- The Random Beacon Committee for the next Epoch (currently all consensus nodes)
+will run the Distributed Key Generation (DKG),
+- When completing the QC generation and DKG, the smart contracts will emit a service event.
+After consensus nodes have collected all relevant information (public keys for the random beacon and cluster quorum certificates),
+they can update the identity table to include the information for the next Epoch.
+
+If preparation for the next Epoch is not completed before the current Epoch ends,
+the network goes into epoch fallback mode (EFM) and a special transaction, sometimes including
+a spork, is required to transition to the next Epoch.
+
+## Epoch Length
+
+The length of an Epoch is measured in terms of consensus views.
+The number of views in an epoch and in the various epoch phases are determined before
+the Epoch begins and stored as a field in the main epoch smart contract (`FlowEpoch`).
+
+Generally, there is not a block for every view, so the view number will not change at the same rate as the block height.
+
+Because the length of a consensus view can vary depending on many different factors,
+the wall-clock time of an epoch is expected to vary from week to week.
+Under typical network conditions we expect the variance in epoch length to be less than 2 hours for a 1-week epoch (~1%).
+Under adverse network conditions the variance in epoch length will increase (typically this will result in longer epochs).
+
+As the average view rate changes over time, the Service Account can change the epoch length to
+target a 1 week wall-clock epoch length.
+
+# Phases
+
+The preparation for the next epoch is separated into distinct phases.
+Each phase occurs completely within the current epoch.
+
+
+
+The Epoch Smart Contract acts as a state machine. The smart contract keeps a record of the current phase,
+the number of views in the current phase, and the conditions that need to be met in order to advance to the next phase, or next epoch.
+A special `Heartbeat` resource is used to call the `advanceBlock()` method during every single new block in Flow.
+During these regular method calls, if all of the conditions are met to advance to the next phase,
+the smart contract performs any relevant retrieval and storage of information, emits a Service Event,
+and transitions to the next phase, which often involves setting certain metadata
+or enabling one of the connected smart contracts to begin its work.
+
+From the perspective of the consensus committee, the phase transitions within epochs
+occur as a result of including a service event in a block,
+thus the phase transition only applies to the fork containing the block with the service event.
+
+At the end of Phase 0 and beginning of Phase 1, the `EpochSetup` service event is emitted
+that contains the identity table and other initial metadata for the upcoming epoch.
+
+At the end of Phase 1 and beginning of Phase 2, the `EpochCommit` service event
+is emitted that contains the results of the Epoch Setup phase.
+
+The start of a new epoch is the first block with its view > the last view of the previous epoch,
+and its parent view ≤ the last view of the last epoch.
+
+## Phase Transitions
+
+The **Consensus Committee** triggers the **phase transition coinciding with the Epoch switchover**
+by publishing the block of the next Epoch.
+This block's execution state will also detect the the end view of an epoch has arrived
+and trigger the start of the new epoch.
+The transition to a new epoch is also marked by the emission of [an event](https://github.com/onflow/flow-core-contracts/blob/master/contracts/epochs/FlowEpoch.cdc#L62) (`EpochStart`)
+from the epoch smart contract.
+
+-
+The state of the smart contracts reflect the latest epoch's new identity table and metadata.
+
+For the **Epoch-*internal* Phase transitions**, meaning the phase transitions within an epoch,
+the **Epoch Smart Contract** provides the trigger by emitting a respective service event:
+
+- The `EpochSetup` service event triggers the phase transition
+`Staking Auction Phase` → `Epoch Setup Phase`
+- The `EpochCommit` service event triggers the phase transition
+`Epoch Setup Phase` → `Epoch Committed Phase`
+
+Only one of each service event may be emitted each epoch, for a given fork.
+`EpochCommit` may only be emitted after `EpochSetup` has been generated in the respective given fork.
+
+The `FlowEpoch` contract manages all of these phases, the `FlowIDTableStaking` contract
+manages the identity table and staking auction, the `FlowClusterQC` contract manages
+the Quorum Certificate generation for collector clusters, and the `FlowDKG` contract manages
+the Distributed Key Generation protocol for the consensus nodes.
+
+Initially, control of these phases and contracts will be managed manually by the Flow Token Admin,
+but control will eventually be completely decentralized and managed by the node software, smart contracts,
+and democratically by all the stakers in the network.
+
+## Phase 0: Staking Auction
+
+**Purpose:** During the staking auction phase, operators can put up stake
+in exchange for being a part of the upcoming epoch.
+All voluntary commitments to register a new node, increase, or decrease stake for the next epoch
+must occur before the end of this phase.
+
+**Duration:** The staking auction phase begins with the first block of the current Epoch
+Its last block is the block in which the `EpochSetup` service event is emitted.
+
+### **Protocol Directives:**
+
+Epoch Smart Contract
+
+- The `FlowEpoch` Smart Contract is responsible for ensuring that staking, un-staking,
+and stake-modification transactions for the next epoch are
+are only executed during the staking auction and fail otherwise.
+The contract enforces this by setting a `stakingEnabled` field in the staking contract.
+Every staking method checks to see if this is set before executing.
+
+- The `FlowEpoch` Smart Contract must ensure that the subsequent phases
+are sufficiently long to perform all required tasks before the epoch ends.
+- As part of the execution result for the last block of the staking auction,
+the `Epoch Smart Contract` computes the seat assignment information for the next epoch,
+and emits a specialized service event, the `EpochSetup` event,
+with the timing and identity table information about the next epoch.
+See the [Epoch Setup Event Documentation](./05-epoch-scripts-events.md#flowepochepochsetup)
+for a detailed breakdown of the epoch setup event.
+
+## Phase 1: Epoch Setup
+
+**Purpose:** During the epoch setup phase, all nodes participating in the upcoming epoch
+must perform setup tasks in preparation for the upcoming epoch.
+
+**Duration:** The epoch setup phase begins right after the `EpochSetup` service event is emitted.
+It ends with the block where `EpochCommit` service event is emitted.
+
+### **Protocol Directives:**
+
+Consensus:
+
+- When a primary constructs a block that seals the `EpochSetup` service event,
+the primary includes an update to the protocol state in the block.
+Specifically, it adds the nodes for the `PendingEpoch` to the list of authorized nodes.
+When this block is propagated, all staked nodes will know about the participants
+in the next epoch and can communicate with them.
+
+- Based on the `RandSeed` field in the `EpochSetup` event, all nodes compute:
+ - The seed to initialize the consensus node's primary selection algorithm for the next epoch
+ - The seeds to initialize the collector clusters' primary selection algorithm for the next epoch
+
+- The collector nodes generate the root block for their respective clusters
+in the next Epoch and submit a vote for the root block to a specialized smart contract, `FlowClusterQC`.
+- The Random Beacon Committee for the next Epoch (currently all consensus nodes)
+will run the DKG through a specialized smart contract, `FlowDKG`.
+
+Epoch Smart Contract:
+
+- The `FlowEpoch` Smart Contract is responsible for ensuring that Epoch Setup transactions
+are only executed during the Epoch Setup phase and fail otherwise.
+The contract enforces this by setting an `enabled` field in the `FlowClusterQC` and `FlowDKG` contracts.
+Every state-changing method from these contracts checks to see if this is set before executing.
+
+- The `FlowEpoch` Smart Contract must ensure that the subsequent phase
+is sufficiently long to perform all required tasks before the epoch ends.
+
+- As part of the execution of the last block of the Epoch Setup phase,
+the `FlowEpoch` Smart Contract computes the public key shares generated by the DKG
+and the `QC`s for the collector clusters and publishes these as `EpochCommit` service event.
+The `FlowEpoch` Smart Contract should emit this event as soon as the artifacts are determined.
+
+See the [Epoch Commit Event Documentation](./05-epoch-scripts-events.md#flowepochepochcommit)
+for a detailed breakdown of the epoch commit event.
+
+## Phase 2: Epoch Committed
+
+**Purpose:** When the epoch committed phase starts, the precise role of each node is fully specified.
+From a protocol-perspective, all information is available for each node
+to start its operation for the next Epoch.
+This phase provides some time for nodes to establish the communication channels
+and synchronize with the network to seamlessly switch over to the next epoch.
+
+**Duration:** The epoch committed phase begins right *after* the `EpochCommit` service event
+has been emitted. It ends when the epoch ends.
+
+### **Protocol Directives:**
+
+Consensus
+
+- When a primary constructs a block that seals the `EpochCommit` service event,
+the primary includes an update to the protocol state in the block. Specifically, it:
+ - adds the information generated in the setup phase to the Protocol State and
+ - marks the updated Protocol State as `committed` in this respective fork.
+
+# Query Information from the Epoch Contract
+
+See the [epoch scripts and events document](./05-epoch-scripts-events.md#introduction) for detailed documentation about
+you can use scripts events to learn information about the state of the epoch contracts.
+
+
+=== networks/staking/03-schedule.md ===
+---
+title: Epoch and Reward Schedule
+sidebar_label: Epoch and Reward Schedule
+description: How the Flow protocol manages the schedule of an epoch and rewards payments
+---
+
+
+
+This information covers the current state of how epoch phases are ran and how
+rewards are calculated and distributed to node operators and delegators.
+All of the information in the document is still being designed and is subject to change
+based on research and discussion by the Flow core team and community.
+If any changes are proposed, the Flow community will be notified in advance.
+
+
+# Schedule
+
+
+
+An Epoch is a period of time when the node operators in the network are constant. At epoch
+boundaries, newly staked node operators are able to join the network and existing node operators
+which have unstaked may exit the network.
+
+Each epoch lasts approximately a week, and the **Epoch Switchover** is defined as the point in time
+when one epoch ends and the next epoch begins, marking a possible change in the list of valid nodes.
+
+
+
+The exact timing of each epoch end is influenced by the number of blocks proposed during the epoch.
+Therefore, epoch phase timing can very and will likely drift over time.
+
+**All quoted epoch end times are estimates and subject to some variance (up to several hours)**.
+See [Epoch Preparation Protocol](./04-epoch-preparation.md#epoch-length) for details.
+
+
+
+**Staking Operations are disabled for approximately the last 6-12 hours of an epoch**,
+typically around 00:00 US Pacific Daylight Time (07:00 UTC) on Wednesday every week until around 12:00 US Pacific Daylight Time (19:00 UTC).
+See [Epoch Setup](./04-epoch-preparation.md#phase-1-epoch-setup) for more information on this phase.
+
+**Epoch Switchovers will happen around 12:00 pm PT on Wednesday (7:00 pm UTC)** every week.
+Please note exact epoch ending time vary based on the performance of the network
+& all staking operations that interact with staked tokens will be processed
+by the protocol at the start of each epoch.
+
+## Rewards
+
+**Rewards are usually paid around 12 pm PT on Wednesday (7:00 pm UTC)**, every week,
+to all users that have tokens staked.
+This is close to the same time as the Epoch Switchover. See the Rewards Distribution section below
+for more information about rewards calculation and schedule.
+
+## Staking Auction
+
+The first, and longest phase of an epoch is the [staking auction](./04-epoch-preparation.md#phase-0-staking-auction).
+This phase is when nodes and delegators can register to stake and perform other staking operations
+such as staking more tokens or unstaking their existing tokens.
+None of these operations are fully executed until the **Epoch Switchover** though.
+
+**The Staking Auction lasts for at least the first 90% of the length of an Epoch**
+
+## Epoch Setup and Epoch Commit
+
+The [Epoch Setup](./04-epoch-preparation.md#phase-1-epoch-setup)
+and [Epoch Commit](./04-epoch-preparation.md#phase-2-epoch-committed)
+phases are the final phases of the epoch, when node operators who have been included
+in the next epoch perform important setup functionality to prepare for the next epoch.
+
+**The Epoch Setup and Epoch Committed phases usually last less than 10% of the time of an epoch.**
+
+**Staking Operations will be rejected during the Epoch Setup and Epoch Commit phases.**
+This is because the staking information has been finalized in preparation for the next epoch
+and cannot be changed because these final phases rely on the staking information being constant.
+
+**The Staking Auction Ends every Wednesday near 00:00 PDT (07:00 UTC).**
+**This means that staking operations will be disabled for ALL users**
+**in the period between the end of the staking auction and the beginning of the next epoch, currently 6-12hrs.**
+
+## Rewards Distribution
+
+The rewards distribution schedule has been designed to ensure
+there is enough liquid supply of FLOW available in the ecosystem
+to empower a wide variety of use cases and promote fair and diverse participation in the Flow ecosystem.
+
+The numbers in this table represent the total amount of tokens that are paid
+as staking rewards at each epoch to the entire pool of participants in the Flow network.
+While the total staking reward amount is known and fixed per epoch,
+rewards that individual stakers receive are variable depending on many factors.
+
+The total rewards for each epoch are fixed for that epoch, but where those rewards come from can change.
+When the protocol pays rewards, it first pulls from the central pool of all the transaction fees
+that have been paid by every user in the network since the last rewards payment.
+Once that pool has been depleted, the protocol mints new tokens that are used as rewards.
+
+Please see the next section on how to calculate an individual staking reward.
+
+| | Dec 22, 2020 | Dec 29, Jan 5, 12, 19, 26 (2021) | Feb 2, 2021 weekly on Wednesdays indefinitely |
+| ----------------------------- | ------------------- | -------------------------------- | --------------------------------------------- |
+| Total Rewards % (Annual) | 5% | 20% | 5% |
+| Total Rewards Amount Per Week | ~1.2M FLOW | ~4.4M FLOW | ~1.3M FLOW |
+
+## Individual Calculation
+
+Each user gets a percentage of the total rewards during each epoch
+that is proportional to their percentage of all the tokens that are staked by all participants.
+
+The full reward calculation on a per-user basis is equal to:
+
+```
+New Reward(user) = Tr * (Sn / St)
+```
+
+where:
+- `Tr` = Total staking rewards to be paid out during the current epoch. (See table above)
+- `Sn` = Amount of FLOW Staked by the target user for the current Epoch. (Different for each staker)
+- `St` = Sum of all the FLOW staked by all the participants in the network. (Changes every epoch)
+
+Rewards for delegators are also calculated in the exact same way that rewards for node operators are calculated,
+with one difference in that 8% of the calculated reward amount is given to the node operator being delegated to
+(effected as a protocol layer fee, which is the same for all node operators).
+The remaining 92% is awarded to the delegator.
+Note: the 8% fee is only applied to the staking reward, not to the tokens delegated.
+
+With this calculation, the node you choose to run or delegate to
+DOES NOT affect the amount of rewards you receive every week.
+The only variable that you can control is the number of tokens you have staked.
+The more tokens you stake, the more rewards you will receive.
+
+Because of the variable nature of the rewards calculation, we cannot provide an expected weekly/yearly return
+for a single staker. You can plug your own numbers into the formula to see some sample calculations,
+but you won't be able to know exactly what you will earn until the beginning
+of the epoch in which you are participating in staking or delegation.
+
+## Rewards History
+
+For the first two years of its existence, the staking rewards payments
+were handled with manual transactions. You can find the history of those transactions
+including their arguments and IDs in the
+[Pay Rewards Section](https://github.com/onflow/service-account/tree/main/transactions/pay-rewards)
+of the Flow Service Account Repo. The dates correspond to the date when the
+rewards were paid at the end of an epoch and the network transitioned to a new epoch.
+
+Future rewards payments and epoch switchovers happen automatically via a system chunk transaction,
+which does not create regular transaction IDs.
+
+=== networks/staking/02-epoch-terminology.md ===
+---
+title: Epoch and Staking Terminology
+sidebar_label: Epoch and Staking Terminology
+description: Important Definitions for Epochs
+---
+
+
+ If you haven't read the staking introduction, please read that
+ first. That document provides a non-technical overview of staking on Flow for
+ all users and is a necessary prerequisite to this document.
+
+
+ This document assumes you have some technical knowledge about the Flow
+ blockchain and programming environment.
+
+
+## Terminology
+
+If any of the definitions are confusing, you can find more detail in the other sections of the technical docs.
+
+**Staker:** Any user who has staked tokens for the Flow network.
+A node operator is a staker, and a delegator is a staker as well.
+
+**Node Operator:** A user who operates a node on the Flow network. Each node operator has a unique node resource
+object they store in their account to perform staking operations.
+
+**Node Operator Metadata:** This information is tracked for each node operator in the Flow network.
+ - **Node ID:** 32 byte identifier for the node. Usually a hash of the node public key.
+ - **Role:** Indicates what role the node operator is. (Collection, Consensus, Execution, Verification, Access)
+ - **Networking Address:** The address that the node operator uses for networking. Using a hostname is highly encouraged.
+ - **Networking Key:** The 64 byte ECDSA-P256 node operator public key for networking.
+ - **Staking Key:** The 96 byte BLS12-381 public key for the node.
+ Used to sign node messages and votes for Quorum Certificate generation.
+ - **Proof of Possession:** A 48 byte (96 hex characters) string that acts as cryptographic
+ proof of ownership of the node's staking key.
+
+**Delegator:** A user who delegates tokens to a node operator and receives rewards for their staked tokens, minus a fee
+taken by the node operator. Each delegator stores a unique delegator resource object in their account
+that allows them to perform staking operations.
+
+- **Delegator Metadata:** This information is tracked for all delegators in the network.
+ - **id:** The ID associated with a delegator. These IDs are assigned to delegators automatically
+ by the staking contract and are only unique within an individual node operators' record.
+ - **nodeID:** The ID of the node operator a user delegates to.
+
+**Node Identity Table:** The record of all the nodes in the network, and their delegators.
+The identity table keeps separate lists for the info about node operators and delegators.
+
+
+ NOTE: The staking smart contract does not associate a node or delegator with
+ an account address. It associates it with the assigned resource object that
+ corresponds to that entry in the contract. There can be any number of these
+ objects stored in the same account, and they can be moved to different
+ accounts if the owner chooses.
+
+
+**Epoch:** The period of time between changes in the identity table and reward payments.
+(Initially a week, measured in consensus views)
+At the end of every epoch, insufficiently staked node operators are refunded their stake,
+rewards are paid to those who are currently staked, committed tokens are marked as staked,
+unstaking tokens are marked as unstaked, and unstaking requests are changed from staked to unstaking.
+
+**Consensus View:** A internal detail that the Flow consensus algorithm, HotStuff, uses to measure time.
+Views count the number of rounds in the consensus algorithm.
+Each round/view the counter is incremented and a new block may be proposed.
+
+**Seat/Slot:** The right to participate in the network as a node of a certain type
+for a specific Epoch. There are a limited number of seats/slots for each node type per epoch.
+Current Slot Limits (may be slightly different than what is shown here):
+- Access Nodes: 167
+- Collection Nodes: 156
+- Consensus Nodes: 149
+- Execution Nodes: 10
+- Verification Nodes: 105
+
+**Candidate:** A node that has committed tokens for the next epoch but has not been accepted yet.
+There is a limited number of node slots per epoch and candidate nodes are selected randomly,
+so there is a chance that a candidate node will not be chosen to participate in the next epoch
+because there aren't enough slots even if they meet all the other regular requirements
+
+**Staking Auction Phase:** The period of time when nodes and delegators are able to submit staking operations
+in preparation for the upcoming epoch. This phase is expected to take over 90% of the time of an epoch.
+
+**Epoch Setup Phase:** The period of time after the staking auction, where nodes have to perform certain processes
+to initialize the state and communication with other nodes for the next epoch.
+These processes are called **Cluster Quorum Certificate Generation (QC)**, and **Distributed Key Generation (DKG)**.
+If any node does not perform this initialization properly, it is not included in the next epoch's Identity Table.
+This phase is expected to take less than 10% of the time of an epoch, near the end.
+
+**Cluster Quorum Certificate Generation (QC):** A process by which nodes using the HotStuff consensus algorithm
+submit signed messages in order to generate a certificate for bootstrapping HotStuff. Each collector cluster runs
+a mini-version of HotStuff, and since clusters are randomized each epoch, a new quorum certificate is required
+for each cluster each epoch.
+
+**Distributed Key Generation (DKG):** Process for generating a shared public key to initialize the random beacon.
+Consensus nodes use a shared whiteboard to communicate and submit final key vectors to generate a shared key.
+
+**Epoch Commit Phase:** The final phase of an epoch, after the Epoch Setup Phase. In this phase, the identity table
+has been finalized for the next epoch, all setup has been completed, and the network
+is simply waiting for the next epoch to start.
+
+**Service Event:** Special messages that are generated by the epoch smart contracts and included in execution results.
+They enable communication between system smart contracts and the Flow protocol.
+In other words, they serve as a communication mechanism between the execution state and the protocol state.
+Service events are not any different that other Cadence events, except in the fact that
+Flow nodes treat them differently because they are being emitted by the service account.
+
+**Node and Delegator Staked Token Tracking Terms:**
+ - **Tokens Committed:** The tokens that a user has committed to stake in the next epoch, but that aren't currently staked.
+ - **Tokens Staked:** The tokens that a user has staked in the current epoch.
+ - **Tokens Requested to Unstake:** The amount of tokens that a user has requested to be unstaked
+ at the end of the current epoch (to be removed from the **tokens staked** pool).
+ - **Tokens Unstaking:** The tokens that were unstaked at the beginning of the current epoch and
+ are being held for an additional epoch holding period before being released.
+ - **Tokens Unstaked:** Tokens that used to be committed or staked and have been unstaked.
+ - **Tokens Rewarded:** Tokens that the user has received via staking rewards.
+
+**Delegation Rewards Cut:** The percentage of a delegator's rewards that the node operators take. Initially set to 8%.
+
+**Epoch Payout:** The total amount of tokens paid in rewards at the end of an epoch.
+This value will change as the supply of FLOW changes. See the [rewards page](./03-schedule.md) for more details.
+
+**Minimum Stake Requirement:** Each node type AND delegator has a requirement for the minimum number of FLOW
+they have to commit to stake to be considered a valid staker and receive rewards.
+If a node operator or delegator does not meet the minimum stake,
+they will not be included in the next epoch and will not receive any rewards.
+
+- Access Nodes: 100 FLOW
+- Collection Nodes: 250,000 FLOW
+- Consensus Nodes: 500,000 FLOW
+- Execution Nodes: 1,250,000 FLOW
+- Verification Nodes: 135,000 FLOW
+- Delegators: 50 FLOW
+
+There is no maximum stake limit.
+
+
+
+=== networks/node-ops/index.md ===
+---
+title: Node Operations
+sidebar_position: 1
+---
+
+# Hello Node Operator!
+
+Flow nodes are vital components of the Flow blockchain. These nodes are responsible for a variety of network operations to maintain the distributed ledger.
+
+## Why Run a Node?
+
+---
+
+By running your own node, you have direct access to the evolving state of the network, without having to rely on third parties.
+This increases privacy and security, reduces reliance on external servers, and helps balance load distribution.
+By running a node, you also directly contribute to the security and decentralization of the whole network.
+
+Flow multirole architecture makes it more scalable and provides several node types that you as a node operator can pick and choose from.
+
+
+## Which Node Should You Run?
+
+---
+
+The different types of nodes are described [here](./node-operation/node-roles.md). As node operator, you can choose to run any of the different types of node that best fits your needs.
+
+The nodes are classified as follows,
+
+
+
+## Light Node A.K.A. Observer Node
+
+---
+
+The light node is one of the easiest nodes to spin up and can be run by Dapp developers who need the latest block data available locally, e.g. a wallet application that needs to track the latest block ID and height.
+In addition to supporting dapps, an observer node can also be run by access node operators who want to scale their access nodes' endpoints. Access node operators can spin up geographically dispersed observer nodes which can talk to their staked access nodes and to each other.
+
+The observer node is not staked but still provides the same API as the access node.
+
+:::info
+
+To run a light node, follow this [guide](./light-nodes/observer-node.md)
+
+:::
+
+## Full Node
+
+---
+
+In a nutshell, Full Nodes are staked network participants that drive network progress, e.g. by creating and executing new blocks. They are the primary contributors to network safety (all of them validate the correctness of the consensus process and secure the network additionally through their role-specific tasks). In comparison, Light Nodes don't contribute to the networks progress. Though, they help to secure the network by also validating the integrity of the consensus process.
+- The Access node is a full node that serves as an RPC node and acts as a gateway node for the network.
+- The Validator node (Collection, Consensus, Verification and Execution) is a full node that plays a role in block generation.
+
+
+### Access Node
+
+---
+
+If you want local access to the protocol state data (blocks, collections, transactions) and do not want to use one of the community access nodes you can run an access node.
+Dapp developers, chain explorers, chain analytics and others who want exclusive access to chain data and not be subject to the rate-limits on the community access node can choose to run an access node.
+
+An access node is minimally staked for network security.
+The central goal for Access Nodes is to provide RPC functionality to its node operator.
+In comparison, contributing to protocol progress (e.g. routing transactions to collector clusters, relaying blocks to the unstaked peer-to-peer network, etc.) should only take up a marginal fraction an Access Node's computational resources.
+Furthermore, Access Node operators can freely rate-limit the amount of resources their Access Node dedicates to supporting the broader ecosystem. Therefore, Access Nodes do not receive staking rewards.
+
+:::info
+
+Launch an access node using QuickNode
+
+[https://www.quicknode.com/chains/flow](https://www.quicknode.com/chains/flow)
+
+:::
+
+
+:::info
+
+To run a self-hosted access node, follow this [guide](./access-nodes/access-node-setup.md)
+
+:::
+
+:::tip
+
+Alternately, instead of running an access node, you can use the [Flow community](../access-onchain-data/index.md) access nodes or the ones run by any of the other node operators.
+
+:::
+
+### Validator Node
+
+---
+
+You can also be a core participant in running the Flow network and contribute to securing it. Depending on your preference, you could run one or any combination of the following node roles:
+- Collection Nodes collaboratively create batches of transactions (in Flow terminology collections).
+- Consensus Nodes create blocks, schedule them for asynchronous execution, and commit execution results once they are verified (so called sealing). In addition, they orchestrate the Flow protocol and enforce protocol compliance.
+- Execution Nodes asynchronously execute blocks. They are the power-houses in the protocol, providing the vast computational resources available to Flow transactions.
+- Verification Nodes check the execution results in a distributed manner.
+
+Nodes with these roles are staked and also receive staking rewards.
+
+### Running a Staked Node
+
+---
+
+To run a staked node (node type access, collection, consensus, verification or execution) the node must:
+* be registered with sufficient stake
+* be authorized by the governance working group
+
+Before proceeding, ensure you have the stake required for your new node and that your node will be authorized by the governance working group (apply [here](https://github.com/onflow/flow-validator)).
+
+To set up a new staked node after it has been authorized by the Flow governance working group, you will need to complete the following steps:
+
+1. [Provision](./node-operation/node-setup.md) the machine on which your node will run.
+
+2. [Generate and register](./node-operation/node-bootstrap.md) your node identity.
+
+3. [Start](./node-operation/node-bootstrap.md#step-3---start-your-flow-node) your node!
+
+
+=== networks/node-ops/node-operation/upcoming-sporks.md ===
+---
+title: Upcoming Sporks
+description: Information about upcoming Mainnet & Testnet sporks
+sidebar_position: 16
+---
+
+The following are the upcoming Spork dates. These dates indicate the intention to Spork. Announcements will be made regarding any delays or changes to these dates in our developer [Discord server](https://discord.gg/flow).
+
+
+
+| Mainnet Spork Date | Spork Info | Testnet Spork Date | Spork Info |
+|:----------------------------|:---------------------------------------|------------------------------------------|------------|
+| ~Q3 2024 (exact date tbd) | | Q3 2024 (exact date tbd) | |
+ | | | May 20, 2024 | Devnet50 |
+| Nov 8, 2023 | Mainnet 24 | Nov 2, 2023 | Devnet49 |
+| | | Aug 4, 2023 | Devnet48 |
+| | | Aug 4, 2023 | Devnet47 |
+| June 21, 2023 | Mainnet 23 | Jun 8, 2023 | Devnet46 |
+| | | Jun 7, 2023 | Devnet45 |
+| | | Apr 24, 2023 | Devnet44 |
+| | | Apr 12, 2023 | Devnet43 |
+| | | Apr 12, 2023 | Devnet42 |
+| Feb 22, 2023 | Mainnet 22 | Jan 30, 2023 —> Feb 22, 2023 | Devnet41 |
+| | | Jan 23, 2023 | Devnet40 |
+| Jan 18, 2023 | Mainnet 21 | Jan 4, 2023 —> Jan 18, 2023 | Devnet39 |
+| Nov 2, 2022 | Mainnet 20 | Oct 19, 2022 —> Nov 2, 2022 | Devnet38 |
+| Aug 24, 2022 | Mainnet 19 | Aug 10, 2022 —> Aug 24, 2022 | Devnet37 |
+| | | Jul 27, 2022 | Devnet36 |
+| June 15, 2022 | [Mainnet 18](./past-upgrades#mainnet-18) | June 9, 2022 —> June 15, 2022 | Devnet35 |
+| April 6, 2022 | [Mainnet 17](./past-upgrades#mainnet-17) | April 4, 2022 —> April 6, 2022 | Devnet34 |
+| February 9, 2022 | [Mainnet 16](./past-upgrades#mainnet-16) | February 7, 2022 —> February 9, 2022 | Devnet33 |
+| December 8, 2021 | [Mainnet 15](./past-upgrades#mainnet-15) | December 7, 2021 —> December 8, 2021 | Devnet32 |
+| November 10, 2021 | Cancelled | November 9, 2021 —> November 10, 2021 | Devnet31 |
+| October 6, 2021 | [Mainnet 14](./past-upgrades#mainnet-14) | October 5, 2021 —> October 6, 2021 | Devnet30 |
+| September 15, 2021 | [Mainnet 13](./past-upgrades#mainnet-13) | September 14, 2021 —> September 15, 2021 | Devnet27 |
+| August 18, 2021 | [Mainnet 12](./past-upgrades#mainnet-12) | August 12, 2021 —> August 18, 2021 | Devnet26 |
+| July 21, 2021 | [Mainnet 11](./past-upgrades#mainnet-11) | July 20, 2021 —> July 21, 2021 | Devnet25 |
+| June 23, 2021 | [Mainnet 10](./past-upgrades#mainnet-10) | June 22, 2021 —> June 23, 2021 | Devnet24 |
+| May 26, 2021 | [Mainnet 9](./past-upgrades#mainnet-9) | May 25, 2021 —> May 26, 2021 | Devnet23 |
+| April 28, 2021 | [Mainnet 8](./past-upgrades#mainnet-8) | April 27, 2021 —> April 28, 2021 | Devnet22 |
+| April 7, 2021 | [Mainnet 7](./past-upgrades#mainnet-7) | March 30, 2021 —> March 31, 2021 | Devnet21 |
+| March 10, 2021 | [Mainnet 6](./past-upgrades#mainnet-6) | March 9, 2021 —> March 10, 2021 | Devnet20 |
+
+
+
+
+=== networks/node-ops/node-operation/spork.md ===
+---
+title: Network Upgrade (Spork) Process
+description: Steps to be carried out by node operators during a network upgrade.
+sidebar_position: 15
+---
+
+## Overview
+
+A spork is a coordinated network upgrade process where node operators upgrade their node software and
+re-initialize with a consolidated representation of the previous spork's state. This enables rapid development
+on the Flow Protocol and minimizes the impact of breaking changes.
+
+The Flow network sporks approximately once every year. Upcoming sporks
+are announced in advance on the `#flow-validators-announcements` **Discord** channel
+and in [Upcoming Sporks](./upcoming-sporks.md). The `#flow-validators-announcements` channel is
+also used to coordinate during the spork process.
+
+This guide is for existing operators participating in a spork. See [Node Bootstrap](./node-bootstrap.md)
+for a guide to joining the network for the first time.
+
+## Step 1 - Cleaning Up Previous Spork State
+
+Once the spork start has been announced on, stop your node and clear your database. The node should stay stopped for the duration of the spork.
+
+
+ You can skip this step if it is your first time running a node on Flow.
+
+
+1. Stop your Flow node
+2. Clear the contents of your `data` directory that you have previously created. The default location is `/var/flow/data`. The `data` directory contains the Flow chain state.
+
+## Step 2 - Start Your Node
+
+Once you receive an announcement that the spork process is complete (via Discord), you will need to fetch the genesis info, update your runtime configuration and then boot your Flow node up!
+
+
+
+If you had set the [dynamic bootstrap arguments](https://developers.flow.com/networks/node-ops/node-operation/protocol-state-bootstrap) command line arguments (`--dynamic-startup-access-address`, `--dynamic-startup-access-publickey`, `--dynamic-startup-epoch-phase`) please remove them.
+
+
+
+1. Run the transit script to fetch the new genesis info:
+ `./boot-tools/transit pull -b ./bootstrap -t ${PULL_TOKEN} -r ${YOUR_NODE_TYPE} --concurrency 10 --timeout 15m`
+
+- `PULL_TOKEN` will be provided by the Flow team.
+ - For `collection`, `consensus`, `verification` node type it will generally be `testnet-x` or `mainnet-x` where x is the latest number of respective network upgrade. e.g. `testnet-52`, `mainnet-26`.
+ - For `execution` node type it will generally be `testnet-x-execution` or `mainnet-x-execution`.
+ - For `access` node:
+ - It will generally be `testnet-x` or `mainnet-x` if execution data indexing is not enabled.
+ - It will generally be `testnet-x-execution` or `mainnet-x-execution` if execution data indexing is enabled.
+
+- `YOUR_NODE_TYPE` should be one of `collection`, `consensus`, `execution`, `verification`, `access` based on the node(s) that you are running.
+
+```shell Example
+$ ./boot-tools/transit pull -b ./bootstrap -t mainnet-16 -r consensus
+Transit script Commit: a9f6522855e119ad832a97f8b7bce555a163e490
+2020/11/25 01:02:53 Running pull
+2020/11/25 01:02:53 Downloading bootstrap/public-root-information/node-infos.pub.json
+2020/11/25 01:02:54 Downloading bootstrap/public-root-information/root-protocol-snapshot.json
+2020/11/25 01:02:54 Downloading bootstrap/random-beacon.priv.json.39fa54984b8eaa463e129919464f61c8cec3a4389478df79c44eb9bfbf30799a.enc
+2020/11/25 01:02:54 SHA256 of the root block is: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
+
+$ tree ./bootstrap/
+ ./bootstrap/
+ ├── private-root-information
+ │ └── private-node-info_39fa54984b8eaa463e129919464f61c8cec3a4389478df79c44eb9bfbf30799a
+ │ └── node-info.priv.json
+ ├── public-root-information
+ │ ├── node-id
+ │ ├── node-info.pub.39fa54984b8eaa463e129919464f61c8cec3a4389478df79c44eb9bfbf30799a.json
+ │ ├── node-infos.pub.json
+ │ └── root-protocol-snapshot.json
+ └── random-beacon.priv.json.39fa54984b8eaa463e129919464f61c8cec3a4389478df79c44eb9bfbf30799a
+```
+
+2. Pull the latest changes from [flow-go repository](https://github.com/onflow/flow-go)
+3. Get your `node-id`, you can find it at `/path/to/bootstrap/public-genesis-information/node-id`
+4. Update the `FLOW_GO_NODE_ID` inside [runtime-conf.env](https://github.com/onflow/flow-go/blob/master/deploy/systemd-docker/runtime-conf.env) to the `node-id` that you got from the previous step
+5. Start your Flow node via `docker` or `systemd`
+
+See [Node Bootstrap](./node-bootstrap.md) for detailed information on Docker/Systemd configuration.
+
+## Common Issues
+
+### Error: cannot create connection
+
+```shell
+20T18:34:21Z","message":"could not create connection"}
+{"level":"error","node_role":"consensus","node_id":"6d3fac8675a1df96f4bb7a27305ae531b6f4d0d2bc13a233e37bb07ab6b852dc","target":"QmVcSQaCdhmk1CMeMN7HTgGiUY1i2KqgVE2vvEmQXK4gAA","error":"failed to dial : all dials failed
+ * [/ip4/155.138.151.101/tcp/3569] dial tcp4 155.138.151.101:3569: connect: connection refused","retry_attempt":2,"time":"2020-05-20T18:34:21Z","message":"could not create connection"}
+```
+
+This error is OK. Your fellow node operators have not turned on/joined the network yet. So no need to worry about it!
+
+
+=== networks/node-ops/node-operation/slashing.md ===
+---
+title: Slashing Conditions
+sidebar_position: 17
+---
+
+## Introduction
+
+Flow is a proof-of-stake system, which means holders of FLOW can earn inflationary rewards
+by staking their FLOW tokens to secure and operate the network.
+A node can participate in the Flow network by depositing a specific amount of stake
+(based on role types) thereby making a bonded pledge to participate
+in the Flow protocol during the upcoming epoch.
+(An epoch is a finite amount of time defined by the protocol, approximately one week,
+during which the nodes participate to run the protocol and are responsible for their operations.)
+
+See the [Staking and Epochs section of the documentation](../../staking/index.md) to learn more
+about the design and functionality of this part of the protocol.
+
+Flow nodes follow the procedures defined in the protocol (based on their role)
+in order to receive rewards. Any deviation (see Slashing Challenges below)
+from the protocol can result in decreased reward payments or punishments.
+Severe infractions, which undermine the safety of the network,
+can lead to “slashing”, where some or all of the staked tokens are confiscated from the offending node(s).
+
+This reward and punishment structure is designed to guarantee the security
+of the protocol and optimize performance over time.
+This document outlines the most severe infractions against the protocol
+which result in some portion of a node’s stake being taken from them (“slashing conditions”).
+Enforcing these slashing conditions is critical to ensure the cryptoeconomic security of the protocol.
+Future documents will describe an incentive structure that encourages system-wide efficiency and speed,
+by providing bonuses to the most performant nodes and withholding payments to nodes that are unresponsive.
+
+This document assumes a working understanding of the high-level architecture of the Flow blockchain.
+Readers who are new to Flow or those looking for a refresher are encouraged
+to read the Protocol Summary [here](../node-operation/node-roles.md) and the staking documentation.
+
+## Slashing Conditions
+
+Any violation of the Flow protocol that could result in staked tokens being seized
+from the offending nodes is called **Slashable Behaviour.**
+In order for the tokens to be seized, the data necessary to prove the occurrence of Slashable Behaviour
+must be combined with the data necessary to attribute the behaviour
+to the node(s) responsible into a **Slashing Witness**.
+(A reduction of rewards, e.g. due to lack of active participation,
+is not formally included in our definition of slashing.)
+The Flow protocol considers only server threats to safety and liveness
+to be slashable conditions and as such, there are no performance related slashing penalties.
+The one exception is in the case of missing Collections (see the section on MCC below),
+where a widespread failure to respond by a large number of nodes is presumed
+to be coordinated and therefore punishable with slashing.
+
+Most Slashable Behaviour in Flow can be detected and attributed to the offender
+by a single honest node observing that behaviour.
+(In other words, one node can generate a Slashing Witness without coordinating with other nodes.)
+However, some Slashable Behaviour can only be detected and attributed
+by combining information from multiple nodes. In those situations,
+the node that first detects the potential infraction raises a **Slashing Challenge**.
+When a challenge is raised, other nodes are expected to provide additional information
+which can be combined with the original challenge into a definitive Slashing Witness
+that is used to adjudicate the challenge. Each type of Slashing Challenge depends
+on different information provided from a different subset of nodes,
+the details of which are provided below.
+
+Flow adheres to a number of principles in the design of its slashing rules:
+
+- Only Consensus Nodes can perform slashing, and only by following the BFT consensus mechanism
+defined in the protocol. As such, a super-majority of Consensus Nodes must inspect
+and confirm a Slashing Witness before any punishment is levied.
+
+- All Slashing Witnesses are objectively decidable.
+Given the current protocol state (maintained by the Consensus Nodes)
+and a well-formed Slashing Witness, all non-Byzantine Consensus Nodes will deterministically come
+to the same conclusion as to which node or nodes should be slashed (if any)
+and the amount of stake to be seized.
+
+- All Slashing Behaviour in Flow requires active malfeasance on the part of the offending node.
+In other words, a node will only be slashed if it takes an action against the rules of the protocol,
+and it will not be slashed if it fails to take an action prescribed by the protocol.
+(“If your machine is crashed, you won’t get slashed.”) The one exception
+is in the case of missing Collections (see the section on MCC below),
+where a widespread failure to respond by a large number of nodes is presumed
+to be coordinated and therefore punishable with slashing.
+
+- Flow makes no attempt to detect and punish liveness failures within the protocol.
+A liveness failure across the network functionally slashes the stake of any participants
+excluded from participating in the reboot (since their stake is locked in a non-functional network).
+Community analysis can determine which nodes were responsible for the failure
+and exclude those Byzantine actors from the new instance.
+
+- Any staked node of Flow can submit a Slashing Witness for any Slashable Behaviour,
+regardless of its role. (For example, a Collection Node could submit a Slashing Witness
+for an invalid execution receipt, even though the protocol doesn’t require Collection Nodes
+to verify execution receipts.)
+
+- Submitting an invalid Slashing Witness is Slashable Behaviour.
+We treat the invalid Slashing Witness itself as the Slashing Witness for that case.
+
+## Stages of Slashing
+
+Transitioning to a rigorous staking protocol in which all slashable conditions are checked,
+enforced, and punished will take place over three phases.
+The Slashing Challenges section below outlines the various challenges
+which may be submitted against an offending node but these challenges
+will not be fully enforced until Phase 3 of the network.
+
+### Phase 1: Beta
+
+- In the beta phase of the network, the expectation is that nodes are running error detection
+and logging but not submitting formal challenges. Any errors found may be submitted
+to the Flow team for additional testing and security improvements.
+
+### Phase 2: Testing Slashing Mechanics
+
+- At this time the slashing mechanisms will be implemented and require testing.
+Formal challenges should be raised and the protocol will follow the complete,
+formal mechanics for arbitrating challenges and slashing perpetrators,
+but no real slashing will take place.
+
+### Phase 3: BFT
+
+- By now, the network has been security-hardened and tested and valid challenges
+result in real slashing of the offending node.
+
+## Slashing Challenges
+
+### 0. All Nodes
+
+**Invalid Report Witness (IRW): **if any nodes report an invalid/inaccurate witness,
+an invalid report witness will be reported by the Consensus Nodes,
+and the node(s) reporting the witness get slashed.
+
+### 1. Collection Nodes
+
+**1.1 Missing Collection Challenge (MCC): ** Collection nodes are responsible
+for storing collection content (all transactions) for any collection which they guarantee
+during the current epoch and the first 1000 blocks of the next epoch.
+During this time they have to respond to any collection request from staked execution,
+verification and Consensus Nodes and should respond in a timely manner (specific timeout).
+If an Execution Node or a Verification Node doesn't receive the response from any
+of the collection guarantors (Collection Nodes who signed a collection),
+they can raise a Missing Collection Challenge and broadcast it to the Consensus Nodes to evaluate.
+
+**Adjudication: **Consensus nodes randomly contact some of the guarantors.
+If Collection Nodes don't respond, a portion of their stakes will be seized.
+If the amount of their stake goes to less than half, they will be fully slashed.
+Then the Consensus Nodes notify all the Execution Nodes to skip that collection.
+If any of the Collection Nodes respond, Consensus Nodes redirect the collection content
+to the Execution Nodes but will also set small penalties both
+for all the guarantors and that Execution Node (according to their revenue ratio).
+
+**1.2 Invalid Collection Witness (ICW):** Collection nodes are responsible for responding
+to collection content queries by collection hash from any staked nodes.
+The collection hash is the hash of an ordered list of transaction hashes.
+If a collection content sent by the Collection Node turns out to be invalid,
+any staked node can report an Invalid Collection Witness. This includes cases where:
+
+- the content is malformed or incomplete,
+- there exists an invalid transaction inside the collection, or
+- the collection hash doesn't match (inside collection guarantee).
+
+**Adjudication:** Consensus nodes evaluate the content of the collection,
+if the collection is found invalid, the Collection Node who signed the content is slashed.
+
+**1.3 Double Collection Proposal Witness (DCPW):** Collection nodes of a cluster run a mini consensus
+inside the cluster to decide on a collection, which requires Collection nodes to propose
+the collection and aggregate votes from others. During the collection consensus,
+if a Collection Node proposes more than one proposal, any other Collection Node
+inside the cluster can report a Double Collection Proposal Witness (including both proposals).
+
+**Adjudication: **Consensus nodes evaluate the content and signatures of these two proposals,
+and if the witness turns out to be valid, the Collection Node who proposed two collections will get slashed.
+
+**1.4 Double Collection Voting Witness (DCVW):** Collection nodes of a cluster
+run a mini consensus inside the cluster to decide on a collection,
+which requires Collection nodes to propose the collection and aggregate votes from others.
+During the collection consensus, if a Collection Node votes for more than one collection proposal
+with identical collection number and size, any other Collection Node inside the cluster
+can report a Double Collection Voting Witness (including both votes).
+
+**Adjudication: **Consensus nodes evaluate the signatures of these two votes and evaluate them,
+and if the witness turns out to be valid, the Collection Node who voted two times will get slashed.
+
+### 2. Consensus Nodes
+
+**2.1 Double Block Proposal Witness (DBPW):** Consensus nodes run the consensus (HotStuff algorithm) over blocks.
+During these consensus steps, if a Consensus Node proposes more than one variation of a block proposal,
+any other Consensus Node can report a Double Block Proposal Witness (including both proposals).
+This report will be broadcasted to all other Consensus Nodes.
+
+**Adjudication: **Consensus nodes evaluate content and signatures of both proposals.
+If the witness turns out to be valid, the Consensus Node who submitted both proposals will get slashed.
+
+**2.2 Double Block Voting Witness (DBVW): ** Consensus nodes run the consensus (HotStuff algorithm)
+over blocks. During the consensus steps, if a Consensus Node votes for
+more than one block proposal with the same height, any other Consensus Node can report
+a Double Block Voting Witness (including both votes).
+This report will be broadcasted to all other Consensus Nodes.
+
+**Adjudication: **Consensus nodes evaluate content and signatures of both votes
+and If the witness turns out to be valid, the Consensus Node who submitted both votes will get slashed.
+
+**2.3 Invalid Block Vote Witness (IBVW):** If a Consensus Node votes for an invalid block
+or the content of the vote itself is invalid (e.g. vote for non-existing block),
+any other Consensus Nodes can report an Invalid Block Vote Witness.
+
+**Adjudication: **Consensus nodes evaluate the vote content and signature.
+If the witness turns out to be valid, the Consensus Node who submitted the faulty vote will get slashed.
+
+**2.4 Invalid Block Proposal Witness (IBPW):** If a Consensus Node proposes
+an invalid block proposal (e.g. quorum certificate without 2/3 vote),
+any other Consensus Nodes can raise an Invalid Block Proposal Witness.
+
+**Adjudication: **Consensus nodes evaluate the proposal content and signature,
+If the witness turns out to be valid, the Consensus Node who submitted the invalid proposal
+will get slashed.
+
+**2.5 Invalid Block Witness (IBW):** If the block contents returned by any Consensus Node is invalid,
+any node can raise the Invalid Block Witness:
+
+- It is malformed or incomplete
+- It doesn't match the payload hash provided by the block header
+
+**Adjudication: **Consensus nodes evaluate the block content and signatures.
+If the witness turns out to be valid, the Consensus Node who signed the block content will get slashed.
+
+**2.6 Invalid Random Beacon Signature Witness (IRBSW):**
+If any participant of the random beacon returns an invalid signature,
+an Invalid Random Beacon Signature Witness can be reported by other Consensus Nodes.
+
+**Adjudication:** Consensus nodes evaluate the random beacon signature.
+If the witness turns out to be valid, the Consensus Node who signed the invalid random beacon part
+will get slashed.
+
+### 3. Execution Nodes
+
+**3.1 Faulty Computation Challenge (FCC): ** If any of the Verification Nodes
+find a fault in the execution of transactions by an Execution Node it can raise an FCC challenge.
+An FCC challenge includes a faulty chunk and all the evidence.
+
+**Adjudication: **Consensus nodes evaluate the challenge, by sending requests
+for collection contents and chunk data needed to run the faulty chunk and comparing
+the results against the expected state commitment. If Consensus Nodes detect any fault
+in the execution of that chunk, the Execution Node(s) who signed the faulty execution receipts
+will get slashed. If no fault is found, the Verification Node who raised the challenge will get slashed.
+
+**3.2 Conflicting Execution Results Challenge (CERC): **
+If two or more variations of execution results are reported by Execution Nodes for a given block.
+Since only one can be valid, Consensus Nodes raise a conflicting execution results challenge.
+
+**Adjudication: **As soon as this challenge is raised, all the Verification Nodes
+go into full check mode (checks all the chunks). The first execution result
+that receives result approval from at least 2/3 of Verification Nodes is the accurate one,
+and the other execution results will be considered faulty and Execution Nodes generating those
+will get slashed. If none of the execution results receive majority approval
+from Verification Nodes after a very long timeout,
+all the Consensus Nodes start executing chunks to determine the correct output.
+
+**3.3 Invalid Chunk Data Package Witness (ICDPW):** If the contents of a chunk data package
+doesn't match the hash provided inside the execution result, or the contents is invalid,
+the Verification Nodes can report an Invalid Chunk Data Package Witness.
+
+**Adjudication: **Consensus nodes evaluate the content of the chunk data package.
+If the witness turns out to be valid, the Execution Node(s)
+who signed the faulty chunk data package will get slashed.
+
+**3.4 Missing Chunk Data Package Challenge (MCDPC):**
+If an Execution Node doesn't respond to the chunk data package request by any staked Verification Node,
+a Missing Chunk Data Package Challenge can be raised by the Verification Node.
+
+**Adjudication: **When this challenge is received by the Consensus Nodes,
+they contact Execution Nodes and ask for the chunk data package.
+If none of the Execution Nodes respond after a long timeout, all of them get slashed.
+If any of the Execution Nodes responds with a valid chunk data package,
+Consensus Nodes redirect the chunk data package to the Verification Nodes
+but will also set small penalties both for all the Execution Nodes and the challenge raiser
+(Verification Node) according to their revenue ratio.
+
+**3.5 Execution Results Timeout Challenge (ERTC):**
+If no execution receipt received in X number of blocks after the submission of each block,
+the liveness of the system is compromised and Consensus Nodes can raise
+an Execution Results Timeout Challenge for all the Execution Nodes.
+
+**Adjudication: **When this challenge is received by the Consensus Nodes,
+they contact Execution Nodes and ask for an update. If none of the Execution Nodes respond
+after a long timeout, all of them get slashed.
+If any of the Execution Nodes return the execution receipt, the case is dismissed.
+
+**3.6 Invalid Execution Receipt Witness (IERW):**
+If an Execution Node provides an execution receipt that is not valid,
+the Consensus Nodes can report an Invalid Execution Receipt Witness.
+
+**Adjudication: **Consensus nodes evaluate the content of the execution receipt.
+If the witness turns out to be valid, the Execution Node(s)
+who signed the invalid execution receipt will get slashed.
+
+**3.7 Non-Matching SPoCKs Challenge (NMSC): **
+If the SPoCKs provided by the Execution Node don't match the ones provided by the Verification Node,
+the Consensus Nodes can raise a Non-Matching SPoCKs challenge.
+
+**Adjudication: **Consensus nodes have to re-execute the chunk
+to be able to compute the accurate SPoCKs secret to be able to adjudicate the challenge.
+This requires requesting the collection and all other data needed for execution from other nodes.
+Any node which provided invalid SPoCKs will be slashed.
+
+### 4. Verification Nodes
+
+**4.1 Non-Matching SPoCKs Challenge (NMSC):**
+If the SPoCKs provided by the Execution Node don't match the ones provided by the Verification Node,
+the Consensus Nodes can raise a Non-Matching SPoCKs challenge.
+
+**Adjudication: **Consensus nodes have to re-execute the chunk to determine the accurate SPoCKs secret
+which is needed to adjudicate the challenge. This requires requesting the collection
+and all other data needed for execution from the other nodes.
+Any node which provided invalid SPoCKs will be slashed.
+
+**4.2 Invalid Result Approval Witness (IRAW):**
+If a Verification Node provides an invalid result approval,
+the Consensus Nodes can report this witness.
+This includes cases that a Verification Node sends a result approval
+for a chunk that was not assigned to the Verification Node (excluding full check mode)
+or if the SPoCK’s signature doesn't match the public key of the Verification Node.
+
+**Adjudication: **Consensus nodes evaluate the content and signatures of the result approval.
+If the witness turns out to be valid, the Verification Node who signed that result approval be slashed.
+
+
+=== networks/node-ops/node-operation/reclaim-disk.md ===
+---
+title: Managing disk space
+description: How to manage the node disk space
+---
+
+As the chain advances, nodes receive chain data and store it on disk.
+Hence, the disk usage of a node keeps increasing gradually over time.
+
+In addition to this, currently nodes also experience an intermittent 30-35% spike in disk usage caused by the compaction process of the Badger database used by the node software.
+
+> The spikes will be eliminated once the Badger database is replaced by the Pebble database in the future.
+
+
+Hence, as a node operator, please make sure to do the following:
+
+1. Provision enough disk space as per the node role (see: [node-provisioning](./node-provisioning.md))
+
+
+2. Setup disk usage monitoring and ensure that the node has enough room to grow and to also accommodate those intermittent spikes.
+
+
+3. If needed, please add more disk space to the node from time to time.
+
+> It highly recommended to setup alerting around disk usage to facilitate timely action and avoid any downtime and subsequent reward slashing for the node.
+
+
+## Reclaiming disk space
+
+### Access, Collection, Consensus and Verification node
+
+If you are running any node other than an execution node and the node is close to running out of disk space or has already exhausted all of its disk, you can re-bootstrap the node's database. This frees up disk space by discarding historical data past a certain threshold.
+
+1. Stop the node.
+
+2. Back up the data folder to a tmp folder in case it is required to revert this change. The default location of the data folder is `/var/flow/data` unless overridden by the `--datadir` flag.
+```sh
+mv /var/flow/data /var/flow/data_backup
+```
+
+3. Configure the node to bootstrap from a new, more recent Root Snapshot. You may use either of the two methods described [here](./protocol-state-bootstrap.md) to configure your node.
+
+4. Start the node. The node should now recreate the data folder and start fetching blocks.
+
+5. If the node is up and running OK, delete the `data_backup` folder created in step 2.
+```sh
+rm -rf /var/flow/data_backup
+```
+
+#### Limitation for Access Node
+
+Re-bootstrapping allows the node to be restarted at a particular block height by deleting all the previous state.
+
+For an **Access Node**, this results in the node not being able to serve any API request before the height at which the node was re-bootstrapped.
+
+_Hence, if you require the access node to serve data from the start of the last network upgrade (spork), do not use this method of reclaiming disk space. Instead provision more disk for the node._
+
+### Execution node
+
+For an execution node, the chunk data directory is the one that takes up most of the space. To reclaim space on an execution, do the following:
+
+1. Stop the Execution Node.
+
+
+2. Remove the Chunk Data Pack Directory. The default is `/var/flow/data/chunk_data_pack` unless overridden by the `chunk-data-pack-dir` parameter.
+
+ Do **not** delete the bootstrap folder.
+
+ ``` rm -rf /var/flow/data/chunk_data_pack```
+
+
+3. Start the Execution Node.
+
+Upon restart, the chunk data pack directory will be automatically recreated.
+
+
+> Note: Always exercise caution when performing system operations, and make sure you have a backup of important data before making any changes.
+
+=== networks/node-ops/node-operation/protocol-state-bootstrap.md ===
+---
+title: Protocol State Bootstrapping
+description: How to bootstrap a new or existing node
+---
+
+When a node joins the network, it bootstraps its local database using a trusted initialization file, called a Root Snapshot.
+Most node operators will use the `Spork Root Snapshot` file distributed during the [spork process](./spork.md).
+This page will explain how the bootstrapping process works and how to use it in general.
+
+For guides covering specific bootstrapping workflows, see:
+- [Node Bootstrap](./node-bootstrap.md) for bootstrapping a newly joined node.
+- [Reclaim Disk](./reclaim-disk.md) for bootstrapping from a recent snapshot to recover disk space.
+
+
+ This page covers only Protocol State bootstrapping and applies to Access, Collection, Consensus, & Verification Nodes.
+ Execution Nodes also need to bootstrap an Execution State database, which is not covered here.
+
+
+## Node Startup
+
+When a node starts up, it will first check its database status.
+If its local database is already bootstrapped, it will start up and begin operating.
+If its local database is not already bootstrapped, it will attempt to bootstrap using a Root Snapshot.
+
+There are two sources for a non-bootstrapped node to obtain a Root Snapshot:
+1. Root Snapshot file in the `bootstrap` folder
+2. Dynamic Startup flags, which will cause the node to download a Root Snapshot from a specified Access Node
+
+The node software requires that only one of the above options is provided.
+
+## Using a Root Snapshot File
+
+
+ If your node already has a bootstrapped database, the Root Snapshot file will be ignored. If both a Root Snapshot and Dynamic Startup flags are present, the node will not startup.
+
+
+Using a Root Snapshot file is more flexible but more involved for operators compared to Dynamic Startup.
+
+A file in `$BOOTDIR/public-root-information` named `root-protocol-state-snapshot.json` will be read and used as the Root Snapshot for bootstrapping the database.
+
+### Instructions
+
+1. Obtain a Root Snapshot file (see below for options)
+2. Ensure your node is stopped and does not already have a bootstrapped database.
+3. Move the Root Snapshot file to `$BOOTDIR/public-root-information/root-protocol-state-snapshot.json`, where `$BOOTDIR` is the value passed to the `--bootstrapdir` flag.
+4. Start your node.
+
+### Obtain Root Snapshot File using Flow CLI
+
+[Flow CLI](../../../tools/flow-cli/index.md) supports downloading the most recently sealed Root Snapshot from an Access Node using the [`flow snapshot save`](../../../tools/flow-cli/utils/snapshot-save.md) command.
+
+When using this method:
+- ensure you connect to an Access Node you operate or trust
+- ensure you use the [`--network-key`](../../../tools/flow-cli/utils/snapshot-save#network-key) flag so the connection is encrypted
+
+### Obtain Root Snapshot File from Protocol database
+
+If you have an existing node actively participating in the network, you can obtain a Root Snapshot using its database.
+
+1. Obtain a copy of the Flow `util` tool and ensure it is in your `$PATH`. This tool is distributed during sporks, or you can build a copy from [here](https://github.com/onflow/flow-go/tree/master/cmd/util).
+2. Stop the existing node.
+3. Construct a Root Snapshot using the `util` tool. The tool will print the JSON representation to STDOUT, so you can redirect the output to a file.
+
+Replace `$DATADIR` with the value passed to the `--datadir` flag. You can specify the desired reference block for the snapshot.
+
+Retrieve the snapshot for the latest finalized block:
+```sh
+util read-protocol-state snapshot -d $DATADIR --final > latest-finalized-snapshot.json
+```
+
+Retrieve the snapshot for a specific finalized block height:
+```sh
+util read-protocol-state snapshot -d $DATADIR --height 12345 > specific-height-snapshot.json
+```
+
+## Using Dynamic Startup
+
+Dynamic Startup is a startup configuration where your node will download a Root Snapshot and use it to bootstrap its local database.
+Dynamic Startup is designed for nodes which are newly joining the network and need to [bootstrap from within a specific epoch phase](./node-bootstrap#timing), but can be used for other use-cases.
+
+
+ If your node already has a bootstrapped database, Dynamic Startup flags will be ignored. If both a Root Snapshot and Dynamic Startup flags are present, the node will not startup.
+
+
+When using Dynamic Startup, we specify:
+1. An Access Node to retrieve the snapshot from.
+2. A target epoch counter and phase to wait for.
+
+After startup, your node will periodically download a candidate Root Snapshot from the specified Access Node.
+If the Root Snapshot's reference block is either **within or after** the specified epoch phase, the node will bootstrap using that snapshot.
+Otherwise the node will continue polling until it receives a valid Root Snapshot.
+
+See the [Epochs Schedule](./../../staking/03-schedule.md) for additional context on epoch phases.
+
+### Specifying an Access Node
+
+Two flags are used to specify which Access Node to connect to:
+- `--dynamic-startup-access-address` - the Access Node's secure GRPC server address
+- `--dynamic-startup-access-publickey` - the Access Node's networking public key
+
+Select an Access Node you operate or trust to provide the Root Snapshot, and populate these two flags.
+
+For example, to use the Access Node maintained by the Flow Foundation for Dynamic Startup, specify the following flags:
+```shell ExampleDynamicStartupFlags
+ ... \
+ --dynamic-startup-access-address=secure.mainnet.nodes.onflow.org:9001 \
+ --dynamic-startup-access-publickey=28a0d9edd0de3f15866dfe4aea1560c4504fe313fc6ca3f63a63e4f98d0e295144692a58ebe7f7894349198613f65b2d960abf99ec2625e247b1c78ba5bf2eae
+```
+
+### Specifying an Epoch Phase
+
+Two flags are used to specify when to bootstrap:
+- `--dynamic-startup-epoch-phase` - the epoch phase to start up in (default `EpochPhaseSetup`)
+- `--dynamic-startup-epoch` - the epoch counter to start up in (default `current`)
+
+> You can check the current epoch phase of the network by running [this](https://github.com/onflow/flow-core-contracts/blob/master/transactions/epoch/scripts/get_epoch_phase.cdc) script. Alternatively, you can also check the current epoch phase [here](https://dashboard.flow.com/) under Epoch Phase.
+
+#### Bootstrapping Immediately
+
+If you would like to bootstrap immediately, using the first Root Snapshot you receive, then specify a past epoch counter:
+```shell ExampleDynamicStartupFlags
+ ... \
+ --dynamic-startup-epoch-phase=1
+```
+You may omit the `--dynamic-startup-epoch-phase` flag.
+
+### Instructions
+
+#### Example 1
+Use Dynamic Startup to bootstrap your node at the `Epoch Setup Phase` of the current epoch (desired behaviour for newly joining nodes):
+1. Ensure your database is not already bootstrapped, and no Root Snapshot file is present in the `$BOOTSTRAPDIR` folder.
+2. Add necessary flags to node startup command.
+For example, using the Flow Foundation Access Node:
+```sh
+ ... \
+ --dynamic-startup-access-address=secure.mainnet.nodes.onflow.org:9001 \
+ --dynamic-startup-access-publickey=28a0d9edd0de3f15866dfe4aea1560c4504fe313fc6ca3f63a63e4f98d0e295144692a58ebe7f7894349198613f65b2d960abf99ec2625e247b1c78ba5bf2eae
+```
+3. Start your node.
+
+#### Example 2
+Use Dynamic Startup to bootstrap your node immediately, using the most recent Root Snapshot:
+1. Ensure your database is not already bootstrapped, and no Root Snapshot file is present in the `$BOOTSTRAPDIR` folder.
+2. Add necessary flags to node startup command.
+For example, using the Flow Foundation Access Node:
+```sh
+ ... \
+ --dynamic-startup-access-address=secure.mainnet.nodes.onflow.org:9001 \
+ --dynamic-startup-access-publickey=28a0d9edd0de3f15866dfe4aea1560c4504fe313fc6ca3f63a63e4f98d0e295144692a58ebe7f7894349198613f65b2d960abf99ec2625e247b1c78ba5bf2eae \
+ --dynamic-startup-epoch=1
+```
+3. Start your node.
+
+
+=== networks/node-ops/node-operation/past-upgrades.md ===
+---
+title: Past Network Upgrades
+description: Information about Flow Mainnet and Testnet network upgrades.
+sidebar_position: 14
+---
+
+A JSON version of the information below can be found in [onflow/flow/sporks.json](https://github.com/onflow/flow/blob/master/sporks.json)
+
+## Mainnet Upgrades
+
+> Currently only includes HCUs from 2025.
+
+## Height Coordinated Upgrade 7
+
+| HCU Info |
+|:--------------------------------------------------------------------------------------|
+| **Date**: April 10, 2025 |
+| **Block Height**: 109384800 |
+| **Git Commit**: 86c40b1ff20b3b7f17c4017bde083d26303c508d |
+| **Branch/Tag**: v0.40.0 |
+| **Docker Image Tag**: v0.40.0 |
+| **Release Notes**: [v0.40.0](https://github.com/onflow/flow-go/releases/tag/v0.40.0) |
+
+## Rolling Upgrade 1
+
+| RU Info |
+|:-------------------------------------------------------------------------------------|
+| **Date**: April 3, 2025 |
+| **Block Height**: 108630638 |
+| **Block View **: 20504725 |
+| **Git Commit**: ad1076f0a36bb2d20cc36295d3573989edc15c6c |
+| **Branch/Tag**: v0.39.0 |
+| **Docker Image Tag**: v0.39.0 |
+| **Release Notes**: [v0.39.0](https://github.com/onflow/flow-go/releases/tag/v0.39.0) |
+
+## Height Coordinated Upgrade 6
+
+| HCU Info |
+|:-------------------------------------------------------------------------------------|
+| **Date**: Feb 18, 2025 |
+| **Block Height**: 103983000 |
+| **Git Commit**: 4e7e56b3a92e5772279f1304d88dd445c0ea5016 |
+| **Branch/Tag**: v0.38.3 |
+| **Docker Image Tag**: v0.38.3 |
+| **Release Notes**: [v0.38.3](https://github.com/onflow/flow-go/releases/tag/v0.38.3) |
+
+## Height Coordinated Upgrade 5
+
+| HCU Info |
+|:-------------------------------------------------------------------------------------|
+| **Date**: Feb 18, 2025 |
+| **Block Height**: 103957477 |
+| **Git Commit**: bcb8a2264fcde9dcd4c997f6b28d8184af19160b |
+| **Branch/Tag**: v0.38.2 |
+| **Docker Image Tag**: v0.38.2 |
+| **Release Notes**: [v0.38.2](https://github.com/onflow/flow-go/releases/tag/v0.38.2) |
+
+## Height Coordinated Upgrade 4
+
+| HCU Info |
+|:---------------------------------------------------------------------------------------|
+| **Date**: Jan 27, 2025 |
+| **Block Height**: 101584244 |
+| **Git Commit**: 5f6b25bd02257e3239341c4be0134b007f3deb49 |
+| **Branch/Tag**: v0.37.26 |
+| **Docker Image Tag**: v0.37.26 |
+| **Release Notes**: [v0.37.26](https://github.com/onflow/flow-go/releases/tag/v0.37.26) |
+
+## Mainnet 26
+
+| Spork Info |
+|:----------------------------------------------------------------------------------------|
+| **Access Node**: access.mainnet.nodes.onflow.org:9000 |
+| **Date**: Sep 25, 2024 |
+| **Root Height**: 88226267 |
+| **Root Parent ID**: 71052eb6e774ae5065b31c604a85af47fa16d5c53e54b9a992581c1ecf0ecfac |
+| **Root State Commit**: 3bba639062a723af1b44b1dfe07e795d158482f02f807f1df0b7c39edd6a8cca |
+| **Git Commit**: 25d9c2a9b89bac8fa003ca67928eb79b1427ea17 |
+| **Branch/Tag**: v0.37.16-patch.1 |
+| **Docker Image Tag**: v0.37.16-patch.1 |
+
+## Mainnet 25
+
+| Spork Info |
+|:----------------------------------------------------------------------------------------|
+| **Access Node**: access-001.mainnet25.nodes.onflow.org:9000 |
+| **Date**: Sep 4, 2024 |
+| **Root Height**: 85981135 |
+| **Root Parent ID**: bc16d37060cb408163a04afe406b9c9398a31663c839de35b92e3c3b10bcf834 |
+| **Root State Commit**: dead79e8f86d20ea3214735d4247b7fac1b4408e93e9b092fe0566cf40cecb9e |
+| **Git Commit**: feabd3a4f9baaa5d7770a312e5b8dc1bd94b1edb |
+| **Branch/Tag**: [v0.37.10](https://github.com/onflow/flow-go/releases/tag/v0.37.10) |
+| **Docker Image Tag**: v0.37.10 |
+
+## Mainnet 24
+
+| Spork Info |
+|:----------------------------------------------------------------------------------------|
+| **Access Node**: access-001.mainnet24.nodes.onflow.org:9000 |
+| **Date**: Nov 8, 2023 |
+| **Root Height**: 65264619 |
+| **Root Parent ID**: aace2d9b6e66067989d0f71c2efff38fe30d88da61e3d80946c7e7b4ee2bbc2f |
+| **Root State Commit**: 709530929e4968daff19c303ef1fc5f0a7649b3a1ce7d5ee5202056969524c94 |
+| **Git Commit**: e63117642e34b215993d14d36622d45df249016c |
+| **Branch/Tag**: [v0.32.7](https://github.com/onflow/flow-go/releases/tag/v0.32.7) |
+| **Docker Image Tag**: v0.32.7 |
+
+## Mainnet 23
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.mainnet23.nodes.onflow.org:9000 |
+| **Date**: Jun 20, 2023 |
+| **Root Height**: 55114467 |
+| **Root Parent ID**: dcaa1469c6cd67154942c70b594bdff407ea28eda1fc9c4a81a814f02dc2efc9 |
+| **Root State Commit**: 5586f6b9af7c0d8efa7b403dbd3a894d71a18faad5a1abda48d3dfb7dcd4b017 |
+| **Git Commit**: 0f6ea38efc91b7d27736b8b2c94091076c624796 |
+| **Branch/Tag**: [v0.31.9](https://github.com/onflow/flow-go/releases/tag/v0.31.9) |
+| **Docker Image Tag**: v0.31.9 |
+
+## Mainnet 22
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.mainnet22.nodes.onflow.org:9000 |
+| **Date**: Feb 22, 2023 |
+| **Root Height**: 47169687 |
+| **Root Parent ID**: 60a976d4cc36d0a5150d3f81ede85809916d4af9eb791d9190af0a12c1fd8a17 |
+| **Root State Commit**: c9c9d3da3fe059a616b13768da2374275bd1a35f94d753ee8e41c538a3cc92d8 |
+| **Git Commit**: e644427a8e83e8cd2a307c40e4c8fd3066008cae |
+| **Branch/Tag**: [v0.29.13](https://github.com/onflow/flow-go/releases/tag/v0.29.13) |
+| **Docker Image Tag**: v0.29.13 |
+
+## Mainnet 21
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.mainnet21.nodes.onflow.org:9000 |
+| **Date**: Jan 18, 2023 |
+| **Root Height**: 44950207 |
+| **Root Parent ID**: 52004adfa7854b1a515d0d905dd5317dc7f77a8dbb56058e04dde01e53e80a92 |
+| **Root State Commit**: 905c5e9a576ba2cbe49b5fe5f64ae84c2dee1bc26a3e81932e573e06a722d08a |
+| **Git Commit**: 7f02a642bb437b45326c4ace54a7f033b32832f8 |
+| **Branch/Tag**: [v0.29.6](https://github.com/onflow/flow-go/releases/tag/v0.29.6) |
+| **Docker Image Tag**: v0.29.6 |
+
+## Mainnet 20
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.mainnet20.nodes.onflow.org:9000 |
+| **Date**: Nov 2, 2022 |
+| **Root Height**: 40171634 |
+| **Root Parent ID**: f66302ac43623a87d29dfdeb08fce5d19e3af7be2e4283d468f74ee10468f248 |
+| **Root State Commit**: ec1e1cd34bb05b5abb3c4701a7f365d1dde46d9d908dc57420bde8b4a53d940a |
+| **Git Commit**: b9b941db9a3949db0e299a40264d852980d35ddd |
+| **Branch/Tag**: [v0.28.6](https://github.com/onflow/flow-go/releases/tag/v0.28.6) |
+| **Docker Image Tag**: v0.28.6 |
+
+## Mainnet 19
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.mainnet19.nodes.onflow.org:9000 |
+| **Date**: Aug 24, 2022 |
+| **Root Height**: 35858811 |
+| **Root Parent ID**: 5c030d4125f8ace0e0ab8255880143190d58aca4ddb7c4720c28eaf497adcae1 |
+| **Root State Commit**: 96ff0d9a2b7d8264ea8727d4a104d7372efcfe18dc0c9111aff5c46b688eff04 |
+| **Git Commit**: b6e9a988514d13e1e1ecd0802d7e02f9e9b1415b |
+| **Branch/Tag**: [v0.27.4](https://github.com/onflow/flow-go/releases/tag/v0.27.4) |
+| **Docker Image Tag**: v0.27.4 |
+
+## Mainnet 18
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.mainnet18.nodes.onflow.org:9000 |
+| **Date**: Jun 15, 2022 |
+| **Root Height**: 31735955 |
+| **Root Parent ID**: 716d54edbb3d9b2ad290709a516f1ffe4290c7b7b33a49bd0480e0b193a45884 |
+| **Root State Commit**: 5bdae9f5fb4cc5d63075547df5502e2bc3cb20707452389fb89ebbe71ecf7b68 |
+| **Git Commit**: fdc732183233f1c577a9e529da6b453364431301 |
+| **Branch/Tag**: [v0.26.9](https://github.com/onflow/flow-go/releases/tag/v0.26.9) |
+| **Docker Image Tag**: v0.26.9 |
+
+## Mainnet 17
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.mainnet17.nodes.onflow.org:9000 |
+| **Date**: Apr 6, 2022 |
+| **Root Height**: 27341470 |
+| **Root Parent ID**: dd7ed04e14559ed47ecc92896a5cb3dbb6b234065d9be7f816d99602238762aa |
+| **Root State Commit**: 113e752ec0619b63187630b4fae308ec5405a00f56f25c2de0b139e283a95b14 |
+| **Git Commit**: 5226c35eb14890db024b9193793b0c49d1b5ad04 |
+| **Branch/Tag**: [v0.25.7](https://github.com/onflow/flow-go/releases/tag/v0.25.7) |
+| **Docker Image Tag**: v0.25.7 |
+
+## Mainnet 16
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.mainnet16.nodes.onflow.org:9000 |
+| **Date**: Feb 9, 2022 |
+| **Root Height**: 23830813 |
+| **Root Parent ID**: b0e7a891682dce277a41e87e2cef52af344ac614bf70c82a5a3a801e63960e88 |
+| **Root State Commit**: 8964d1f74c2bed2d0fbb4a366fff1fd3c39b71653e9de4d4512090798631e5f8 |
+| **Git Commit**: c78cac3573e0548611f29df7cfa2db92203554c1 |
+| **Branch/Tag**: [v0.24.4](https://github.com/onflow/flow-go/releases/tag/v0.24.4) |
+| **Docker Image Tag**: v0.24.4 |
+
+## Mainnet 15
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.mainnet15.nodes.onflow.org:9000 |
+| **Date**: Dec 8, 2021 |
+| **Root Height**: 21291692 |
+| **Root Parent ID**: 8a28ddc6653a8991435dfbc95103d6be1a3b653cda3d664681215ee93112a203 |
+| **Root State Commit**: 84d9b325d3f48f7f075eea0db6c246cb5adc759a2dd8561e461477a7ca1f7f22 |
+| **Git Commit**: bfde54ae3324db5d18ebeaa22c70b5574a114f2e |
+| **Branch/Tag**: [v0.23.4](https://github.com/onflow/flow-go/releases/tag/v0.23.4) |
+| **Docker Image Tag**: v0.23.4 |
+
+## Mainnet 14
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.mainnet14.nodes.onflow.org:9000 |
+| **Date**: Oct 6, 2021 |
+| **Root Height**: 19050753 |
+| **Root Parent ID**: ac4dbf344ce96e39e15081f1dc3fbbf6dc80532e402de9a57af847d3b35df596 |
+| **Root State Commit**: 641eb088e3ce1a01ff56df2d3a14372c65a7fef44c08799eb92cd7759d1d1d2a |
+| **Git Commit**: f019c1dbd778ce9f92dea61349ca36003678a9ad |
+| **Branch/Tag**: [v0.22.9-patch-1-epoch-view-check-hotfix](https://github.com/onflow/flow-go/releases/tag/v0.22.9-patch-1-epoch-view-check-hotfix) |
+| **Docker Image Tag**: v0.22.9-patch-1-epoch-view-check-hotfix |
+
+## Mainnet 13
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.mainnet13.nodes.onflow.org:9000 |
+| **Date**: Sept 15, 2021 |
+| **Root Height**: 18587478 |
+| **Root Parent ID**: 2f708745fff4f66db88fac8f2f41d496edd341a2837d3e990e87679266e9bdb8 |
+| **Root State Commit**: 51e3098d327df22fd005d960cb73167c83cb438c53e6c4363c07d8611ae44528 |
+| **Git Commit**: 9535540110a4452231d044aceabab0e60f67708c |
+| **Branch/Tag**: [v0.21.3](https://github.com/onflow/flow-go/releases/tag/v0.21.3) |
+| **Docker Image Tag**: v0.21.3 |
+
+## Mainnet 12
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.mainnet12.nodes.onflow.org:9000 |
+| **Date**: Aug 18, 2021 |
+| **Root Height**: 17544523 |
+| **Root Parent ID**: f6ca04ba5c6fa6ba690a77202a9fad8d3ec30c67762ae065f0f0f53e8fed84d0 |
+| **Root State Commit**: b5cf1977b12de699d0e777af5be25095653735a153d1993f97ff07804b070917 |
+| **Git Commit**: 4a0c10d74f1bcaadfdfec8c325efa411acd1a084 |
+| **Branch/Tag**: [v0.20.5](https://github.com/onflow/flow-go/releases/tag/v0.20.5) |
+| **Docker Image Tag**: v0.20.5 |
+
+## Mainnet 11
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.mainnet11.nodes.onflow.org:9000 |
+| **Date**: July 21, 2021 |
+| **Root Height**: 16755602 |
+| **Root Parent ID**: de15461988000eddc6e507dc7b159dcd192ee3aa72f3bd3b0e31ae9c6538399f |
+| **Root State Commit**: 4eb91bf34cb65b7537a6a95806f444f409308b2eaaa0ad28d1924b6cb8afa140 |
+| **Git Commit**: 2644560c0562412a3c2209820be07f8f3f8b1846 |
+| **Branch/Tag**: [v0.19.2](https://github.com/onflow/flow-go/releases/tag/v0.19.2) |
+| **Docker Image Tag**: v0.19.2 |
+
+## Mainnet 10
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.mainnet10.nodes.onflow.org:9000 |
+| **Date**: June 23, 2021 |
+| **Root Height**: 15791891 |
+| **Root Parent ID**: 1d4109bbb364d5cdd94640546dd1c423d792d962284665233d541e4ade921726 |
+| **Root State Commit**: 9b6a1a5ab52fd3d5a19ea22f09cb607bba63671311f157b3e604dd265efb851a |
+| **Git Commit**: 01f53ebd7df3101e337d9212736cff6ab1e0056d |
+| **Branch/Tag**: [v0.18.4](https://github.com/onflow/flow-go/releases/tag/v0.18.4) |
+| **Docker Image Tag**: v0.18.4 |
+
+## Mainnet 9
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.mainnet9.nodes.onflow.org:9000 |
+| **Date**: May 26, 2021 |
+| **Root Height**: 14892104 |
+| **Root Parent ID**: 265d10ba3e36ed6539fd4d7f4322735aad4997c0378d75783e471437dd83ef33 |
+| **Root State Commit**: fcc30a6664337ef534ad544ad7b17c5cc3b5470a8ef0d93f18573fddf6b25c4a |
+| **Git Commit**: 2d81520c49a8865fa686c32c508d2261155c86bc |
+| **Branch/Tag**: [v0.17.4](https://github.com/onflow/flow-go/releases/tag/v0.17.4) |
+| **Docker Image Tag**: v0.17.4 |
+
+## Mainnet 8
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.mainnet8.nodes.onflow.org:9000 |
+| **Date**: April 28, 2021 |
+| **Root Height**: 13950742 |
+| **Root Parent ID**: faa2a3a996c6efcc3ef562fe03d797e4b19dbe00f6beab082d6d37a447044abd |
+| **Root State Commit**: 259836c7f74e6bbb803c9cfb516044bc701d99c2840e9b9f89609464867e7f0f |
+| **Git Commit**: 4e733ba2038512e9d80bcd955e67e88ba6e3ecf2 |
+| **Branch/Tag**: v0.16.2 |
+| **Docker Image Tag**: v0.16.2 |
+
+## Mainnet 7
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.mainnet7.nodes.onflow.org:9000 |
+| **Date**: April 7, 2021 |
+| **Root Height**: 13404174 |
+| **Root Parent ID**: 8b969d0babbb7d2043957b3d55a811f2c13344faa76565096d4ad901a466ecaa |
+| **Root State Commit**: 1247d74449a0252ccfe4fd0f8c6dd98e049417b3bffc3554646d92f810e11542 |
+| **Git Commit**: b6f47fd23ffe31e2fe714c6bff0b17d901e210b4 |
+| **Branch/Tag**: v0.15.3-patch.4 |
+| **Docker Image Tag**: v0.15.3-patch.4 |
+
+Releases compatible with Mainnet 7: No change from Mainnet 6
+
+## Mainnet 6
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.mainnet6.nodes.onflow.org:9000 |
+| **Date**: Mar 10, 2021 |
+| **Root Height**: 12609237 |
+| **Root Parent ID**: c68e63ca5b6f7ff61ef2b28d7da528c5b677b0f81f2782f067679c108d77932b |
+| **Root State Commit**: ddfedbfaa2d858e6a8e3b142381a91b289f50e45622f5b5a86ac5c00ce61bf11 |
+| **Git Commit**: c887bd343ca7db6351690007b87bec40d39d7b86 |
+| **Branch/Tag**: v0.14.9 |
+| **Docker Image Tag**: v0.14.9 |
+
+Releases compatible with Mainnet 6:
+
+### Network Implementations
+
+Flow Go: https://github.com/onflow/flow-go/releases/tag/v0.14.9
+Emulator: https://github.com/onflow/flow-emulator/releases/tag/v0.16.1
+
+Emulator v0.16.1 is distributed in Flow CLI v0.15.0: https://github.com/onflow/flow-cli/releases/tag/v0.15.0
+
+### SDK Compatibility
+
+#### Flow Go SDK
+
+Minimum version: https://github.com/onflow/flow-go-sdk/releases/tag/v0.16.1
+Recommended version: https://github.com/onflow/flow-go-sdk/releases/tag/v0.16.1
+
+#### FCL (Flow Client Library)
+
+Minimum version: [v0.0.66](https://github.com/onflow/fcl-js/blob/master/packages/fcl/CHANGELOG.md#0066---2020-11-09)
+Recommended version: [v0.0.67](https://github.com/onflow/fcl-js/blob/master/packages/fcl/CHANGELOG.md#0067-alpha0---2020-11-17)
+
+While FCL v0.0.67 is not strictly necessary to use Mainnet 6, we strongly recommend upgrading in order to adapt to wallet improvements that were introduced in v0.0.67.
+
+---
+
+## Mainnet 5
+
+| Spork Info |
+| :--------------------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.mainnet5.nodes.onflow.org:9000 |
+| **Date**: Feb 17, 2021 |
+| **Root Height**: 12020337 |
+| **Root Parent ID**: 9131733835702b0d6321088bddb4642a4964bb5c630440ccb0de47bdbc371d1a |
+| **Root State Commit**: 54bef048a6c5574ef4eb452dd2698aeb2fe5eca6edd536aca6d0bc631c2daaa9 |
+| **Git Commit**: 027569a9d76e41b1140b189fa1b9187c711ab241 |
+| **Branch/Tag**: v0.14.1 for Access, Verification, Collection and v0.14.2 for Consensus and Execution |
+| **Docker Image Tag**: v0.14.1 / v0.14.2 |
+
+---
+
+## Mainnet 4
+
+| Spork Info |
+| :------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.mainnet4.nodes.onflow.org:9000 |
+| **Date**: Dec 16, 2020 |
+| **Root Height**: 9992020 |
+| **Root Parent ID**: 691e35a4ac4d0d47e1be1ec81512ac9f6cdd04545b908fad1d6ceea58c76b560 |
+| **Root State Commit**: 0011fda57f2f3aaa8e6bcc1e1deea9778a9543252f8b65bbd4ebca3687789420 |
+| **Git Commit**: f4a73c7f20109209e9e2e999cf50fcf1ec41241b |
+| **Branch/Tag**: v0.13.1 |
+| **Docker Image Tag**: v0.13.1 |
+
+---
+
+## Mainnet 3
+
+| Spork Info |
+| :------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.mainnet3.nodes.onflow.org:9000 |
+| **Date**: Dec 9, 2020 |
+| **Root Height**: 9737133 |
+| **Root Parent ID**: 116751c904a7f868cd6e8c90522fdbd70fe826db6886b830338c68c6339df3e7 |
+| **Root State Commit**: 1d2c91e801d0560024848a0c981e03120efc372436ada5f7909c4d44d4600f04 |
+| **Git Commit**: badd5887512b955e7aa18b4e73dae980ca72fa22 |
+| **Branch/Tag**: v0.12.6 |
+| **Docker Image Tag**: v0.12.6 |
+
+---
+
+## Mainnet 2
+
+| Spork Info |
+| :------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.mainnet2.nodes.onflow.org:9000 |
+| **Date**: Nov 13, 2020 |
+| **Root Height**: 8742959 |
+| **Root Parent ID**: b35fdb189d21a95df7f19f941786f748d9854a8b93b1e555b51cda7d9f53a6e1 |
+| **Root State Commit**: d6a25be552ed93213df0ffc2e8c7f39f6401c04cbf22bac7a4b84d3c9493f005 |
+| **Git Commit**: 4ef68efb935c0e3393ae3966752ece5e7739bab4 |
+| **Branch/Tag**: v0.11.1 |
+| **Docker Image Tag**: v0.11.1 |
+
+---
+
+## Mainnet 1
+
+| Spork Info |
+| :------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.mainnet1.nodes.onflow.org:9000 |
+| **Date**: Oct 13, 2020 |
+| **Root Height**: 7601063 |
+| **Root Parent ID**: ab1ee18b6e1c0ee11cc021c26a17c694c627699a576e85f7013cd743bdbc7877 |
+| **Root State Commit**: 6e1adf15689eaf5ea6859bcdd0b510f5eb4c34dac878d8577b3f65bc20c3f312 |
+| **Git Commit**: 114d45436e7d9052e910c98a1e40f730e3fd12d7 |
+| **Branch/Tag**: v0.10.1 |
+| **Docker Image Tag**: v0.10.1 |
+
+---
+
+## Candidate 9
+
+| Spork Info |
+| :------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.candidate9.nodes.onflow.org:9000 |
+| **Date**: Sep 25, 2020 |
+| **Root Height**: 6483246 |
+| **Root Parent ID**: 9131733835702b0d6321088bddb4642a4964bb5c630440ccb0de47bdbc371d1a |
+| **Root State Commit**: 90c6f406f5d21880d525ad4702cb249509b85e7f745db2de67e9fe541a56da4c |
+| **Git Commit**: v0.9.3 |
+| **Branch/Tag**: v0.9.3 |
+| **Docker Image Tag**: |
+
+---
+
+## Candidate 8
+
+| Spork Info |
+| :------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.candidate8.nodes.onflow.org:9000 |
+| **Date**: Sep 9, 2020 |
+| **Root Height**: 4972987 |
+| **Root Parent ID**: 5bc2b0900a5138e39d9209a8fe32e14b3e5c884bd36d2a645620f746b7c8bd47 |
+| **Root State Commit**: 6b9161a225b087a461ec95e710fdf4e73f6d6c9401ebf066207a021dced4ce5e |
+| **Git Commit**: |
+| **Branch/Tag**: |
+| **Docker Image Tag**: |
+
+---
+
+## Candidate 7
+
+| Spork Info |
+| :------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.candidate7.nodes.onflow.org:9000 |
+| **Date**: Aug 24, 2020 |
+| **Root Height**: 4132133 |
+| **Root Parent ID**: 28f4f495aad016b519acf27fc9d9a328f6a4009807480e36e2df780eeccd99bc |
+| **Root State Commit**: 001d173bfcf9c7f71684da89bff72b3ee582b39a69c7929360230faf73735c17|
+| **Git Commit**: f811f8cd49369ae2bc559e0fbb781aff129484f5 |
+| **Branch/Tag**: candidate7 |
+| **Docker Image Tag**: v0.7.2 |
+
+---
+
+## Candidate 6
+
+| Spork Info |
+| :------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.candidate6.nodes.onflow.org:9000 |
+| **Date**: Aug 18, 2020 |
+| **Root Height**: 3187931 |
+| **Root Parent ID**: 2ff5f7424a448943a153001d2f0869d4fac330906ecb8e17b7ef7fe50e4c7b36 |
+| **Root State Commit**: bd7f16dc5ef5eced849ab5f437547c14c1907059e1ecf89a942d0521166c5cbb |
+| **Git Commit**: b30c48008c0ec1cc8ecb750aeb9ff9f3d712681d |
+| **Branch/Tag**: |
+| **Docker Image Tag**: |
+
+---
+
+## Candidate 5
+
+| Spork Info |
+| :------------------------------------------------------------------------------------- |
+| **Access Node**: access-001.candidate5.nodes.onflow.org:9000 |
+| **Date**: Jul 28, 2020 |
+| **Root Height**: 2033592 |
+| **Root Parent ID**: a0efffb2beb1500419ae4f7c6e49bfbbe3a4d1d1c201bf925ccaec467ea30e91 |
+| **Root State Commit**: 0190d417a26b9870f5bb2cf408ad31985b3aa7e57f6ababa6e543f0f90b99dcd |
+| **Git Commit**: cd876653d20b398952af4002701a0ae2800fd5f2 |
+| **Branch/Tag**: |
+| **Docker Image Tag**: |
+
+---
+
+## Candidate 4
+
+| Spork Info |
+|:----------------------------------------------------------------------------------------|
+| **Access Node**: access-001.candidate4.nodes.onflow.org:9000 |
+| **Date**: Jul 14, 2020 |
+| **Root Height**: 1065711 |
+| **Root Parent ID**: 68c2bbe68524b50f5d689bc2ac7ad2dd70e88ed7dd15ad6c3cdf6ea314cb1aa3 |
+| **Root State Commit**: c05086e4d1d428d3b9af5bd8b81d8780054f783ef4eec3ca28b491202e9ac696 |
+| **Git Commit**: b9b197280d6590576f1ef183bc3d04d41d6be587 |
+| **Branch/Tag**: |
+| **Docker Image Tag**: |
+
+---
+
+## Testnet Upgrades
+
+> Currently only includes HCUs from 2025.
+
+## Height Coordinated Upgrade 9
+
+| HCU Info |
+|:-------------------------------------------------------------------------------------|
+| **Date**: April 9, 2025 |
+| **Block Height**: 252457666 |
+| **Git Commit**: 86c40b1ff20b3b7f17c4017bde083d26303c508d |
+| **Branch/Tag**: v0.40.0 |
+| **Docker Image Tag**: v0.40.0 |
+| **Release Notes**: [v0.40.0](https://github.com/onflow/flow-go/releases/tag/v0.40.0) |
+
+## Height Coordinated Upgrade 8
+
+| HCU Info |
+|:-------------------------------------------------------------------------------------|
+| **Date**: Feb 18, 2025 |
+| **Block Height**: 243615144 |
+| **Git Commit**: 4e7e56b3a92e5772279f1304d88dd445c0ea5016 |
+| **Branch/Tag**: v0.38.3 |
+| **Docker Image Tag**: v0.38.3 |
+| **Release Notes**: [v0.38.3](https://github.com/onflow/flow-go/releases/tag/v0.38.3) |
+
+## Height Coordinated Upgrade 7
+
+| HCU Info |
+|:-------------------------------------------------------------------------------------|
+| **Date**: Feb 14, 2025 |
+| **Block Height**: 242883902 |
+| **Git Commit**: bcb8a2264fcde9dcd4c997f6b28d8184af19160b |
+| **Branch/Tag**: v0.38.2 |
+| **Docker Image Tag**: v0.38.2 |
+| **Release Notes**: [v0.38.2](https://github.com/onflow/flow-go/releases/tag/v0.38.2) |
+
+## Height Coordinated Upgrade 6
+
+| HCU Info |
+|:---------------------------------------------------------|
+| **Date**: Feb 11, 2025 |
+| **Block Height**: 242365900 |
+| **Git Commit**: bcb8a2264fcde9dcd4c997f6b28d8184af19160b |
+| **Branch/Tag**: v0.38.1 |
+| **Docker Image Tag**: v0.38.1 |
+| **Release Notes**: N/A |
+
+## Height Coordinated Upgrade 5
+
+| HCU Info |
+|:---------------------------------------------------------------------------------------|
+| **Date**: Jan 24, 2025 |
+| **Block Height**: 239255500 |
+| **Git Commit**: 5f6b25bd02257e3239341c4be0134b007f3deb49 |
+| **Branch/Tag**: v0.37.26 |
+| **Docker Image Tag**: v0.37.26 |
+| **Release Notes**: [v0.37.26](https://github.com/onflow/flow-go/releases/tag/v0.37.26) |
+
+## Devnet 52
+
+| Spork Info |
+|:----------------------------------------------------------------------------------------|
+| **Date**: Sept 24th, 2024 |
+| **Root Height**: 218215349 |
+| **Root Parent ID**: 20dd925a750399493cf7455f199c32c952e8010a6c0b4424dba00a193fa18e44 |
+| **Root State Commit**: b0498700398cdc8c0c9368cc2f82fde62e8fe4b06e9c8af6c9bb619ab499e6c3 |
+| **Git Commit**: 25d9c2a9b89bac8fa003ca67928eb79b1427ea17 |
+| **Branch/Tag**: v0.37.16-patch.1 |
+| **Docker Image Tag**: v0.37.16-patch.1 |
+
+## Devnet 51
+
+| Spork Info |
+|:----------------------------------------------------------------------------------------|
+| **Date**: Aug 14th, 2024 |
+| **Root Height**: 211176670 |
+| **Root Parent ID**: c92e07e5d4fbb3a64e0091085a190a4a1119bfc628c71efe513e373dc0482f5a |
+| **Root State Commit**: c3af77992f253f4dcfeac808912ff68e6f10923aa3fc4541a2e39eb9786c9eb3 |
+| **Git Commit**: eeac47931cd6837ec6e29c4c0480609238959ccd |
+| **Branch/Tag**: v0.37.1 |
+| **Docker Image Tag**: v0.37.1 |
+
+## Devnet 50
+
+| Spork Info |
+|:----------------------------------------------------------------------------------------------------------------------------|
+| **Date**: May 20th, 2024 |
+| **Root Height**: 185185854 |
+| **Root Parent ID**: cc4800bf44bc07864d156f829cfda2ae1964b5e103de7b9fa1bd879f9e92c10d |
+| **Root State Commit**: 6a0ae7bf43660e813ee9c2d654f00476ac1bdc357ff47ad11f0e52fc1700d62f |
+| **Git Commit**: 0585789483c4f5ea423bb11afcfe862c9a99711e |
+| **Branch/Tag**: v0.33.23-failure-mode-revert-patch |
+| **Docker Image Tag**: v0.33.23-failure-mode-revert-patch |
+
+## Devnet 49
+
+| Spork Info |
+|:----------------------------------------------------------------------------------------|
+| **Date**: Nov 2nd, 2023 |
+| **Root Height**: 129578013 |
+| **Root Parent ID**: 91b039c1a5caf25776948270a6355017b8841bfb329c87460bfc3cf5189eba6f |
+| **Root State Commit**: e10d3c53608a1f195b7969fbc06763285281f64595be491630a1e1bdfbe69161 |
+| **Git Commit**: fce4ae31c8c90c6a21de9856a319c379bb797fc5 |
+| **Branch/Tag**: v0.32.6-patch.1 |
+| **Docker Image Tag**: v0.32.6-patch.1 |
+
+## Devnet 48
+
+| Spork Info |
+|:----------------------------------------------------------------------------------------|
+| **Date**: Aug 4th, 2023 |
+| **Root Height**: 127720466 |
+| **Root Parent ID**: 2b30e75bd857f898456dcb296bea4b8bc8001cab7062eeee9e47876411b36d76 |
+| **Root State Commit**: f2e5ebfca2fd519e49f7bd85bea81e92eeaa85a705b3376d8534e9c9649da710 |
+| **Git Commit**: 692969b1718b3d21f95ee7f66e5061623d99e599 |
+| **Branch/Tag**: v0.32.3 |
+| **Docker Image Tag**: v0.32.3 |
+
+## Devnet 47
+
+| Spork Info |
+|:----------------------------------------------------------------------------------------|
+| **Date**: Aug 4th, 2023 |
+| **Root Height**: 113167876 |
+| **Root Parent ID**: dbd59a00503707c8bc3c5fb3bcc7bd243da4bf8e24c86b6a496505e275b85311 |
+| **Root State Commit**: 42006aedbfbfa9fcd949de8347b55166df77d8742bf5f273266a8dfcdf2b836b |
+| **Git Commit**: db1c2584d6d8359b7ccf733c16bd5e1b9385c9bc |
+| **Branch/Tag**: v0.31.13 |
+| **Docker Image Tag**: v0.31.13 |
+
+## Devnet 46
+
+| Spork Info |
+|:----------------------------------------------------------------------------------------|
+| **Date**: Jun 8th, 2023 |
+| **Root Height**: 105155067 |
+| **Root Parent ID**: daced0cdeed95cf143320db50ac904ed17dabe04898e988264af2a71e0d1ca48 |
+| **Root State Commit**: e8c39b7a1672cb3f5f70da6f1d71a3a0322d3d6c3d7ebf8092ae2ae40d12c30b |
+| **Git Commit**: 3d4159e93c92cc6331e69708b8c3270d40c09c5f |
+| **Branch/Tag**: v0.31.4 |
+| **Docker Image Tag**: v0.31.4 |
+
+## Devnet 45
+
+| Spork Info |
+|:----------------------------------------------------------------------------------------|
+| **Date**: Jun 7th, 2023 |
+| **Root Height**: 105032150 |
+| **Root Parent ID**: 71df56106ee1492c055a60e2d951a6a8d1b7d1483b903f10146cec912e793e82 |
+| **Root State Commit**: 0e2e053ca4436a4881f65acc031e12820b5260ef616446950650a1bc8fc9be2f |
+| **Git Commit**: 8d32e5ea087fcceb0d1aa923c56be1d5a2d6538a |
+| **Branch/Tag**: v0.31.2 |
+| **Docker Image Tag**: v0.31.2 |
+
+## Devnet 44
+
+| Spork Info |
+|:----------------------------------------------------------------------------------------|
+| **Date**: Apr 24th, 2023 |
+| **Root Height**: 100675451 |
+| **Root Parent ID**: 298854580771edc6ec2e2bbc8da3990ff7f746e2fc5cfe16e550d577bdd4bc5b |
+| **Root State Commit**: 2a062531331b8214de4e900a26ff0f76c578481b4ce22b4b5d8e55bd9535abda |
+| **Git Commit**: b5b65c9d43bf6bd12766eef06e870990c3963b7c |
+| **Branch/Tag**: v0.30.6 |
+| **Docker Image Tag**: v0.30.6 |
+
+## Devnet 43
+
+| Spork Info |
+|:----------------------------------------------------------------------------------------|
+| **Date**: Apr 12th, 2023 |
+| **Root Height**: 99452067 |
+| **Root Parent ID**: 0e6bae31b2f34ffb0d64d4e1a33c2fbcebd80c936d77d70d2f5dd9321dc92393 |
+| **Root State Commit**: 7cd69bb0a4448566dce42808efa8b1d03f322135f0bfce6f18037fca1294984c |
+| **Git Commit**: d55ca8f48167e9669bdb1dc3173253936863e31e |
+| **Branch/Tag**: v0.30.3 |
+| **Docker Image Tag**: v0.30.3 |
+
+## Devnet 42
+
+| Spork Info |
+|:----------------------------------------------------------------------------------------|
+| **Date**: Apr 12th, 2023 |
+| **Root Height**: 99444465 |
+| **Root Parent ID**: a3788d5c0ff1c45db38bca2625bf18bfc562e1bfdc9ebb7dc83ef080be31e697 |
+| **Root State Commit**: a6e5bfc16a39109ef86caad4dab77ec3752680ef3813c3449f239d84fddc5aa1 |
+| **Git Commit**: d55ca8f48167e9669bdb1dc3173253936863e31e |
+| **Branch/Tag**: v0.30.3 |
+| **Docker Image Tag**: v0.30.3 |
+
+## Devnet 41
+
+| Spork Info |
+|:----------------------------------------------------------------------------------------|
+| **Date**: Jan 30th, 2023 |
+| **Root Height**: 93156994 |
+| **Root Parent ID**: 26ff2f7f2948a05c63e723eb42946565809b47dbef87079a8f0bae0cc36a0478 |
+| **Root State Commit**: 08d712b4f7ed838d53b8699e2fd94d0ad010c4b1fa45735b6e80083ff8ef08ff |
+| **Git Commit**: a7f2cd0ddd9fc7e1e56187327a84fec9efdc3c9d |
+| **Branch/Tag**: v0.29.8 |
+| **Docker Image Tag**: v0.29.8 |
+
+## Devnet 40
+
+| Spork Info |
+|:----------------------------------------------------------------------------------------|
+| **Date**: Jan 23rd, 2023 |
+| **Root Height**: 92473965 |
+| **Root Parent ID**: 7c9812f414d9e9795c1cd7dbd27fc45baf880391452e0e948aaa80ba86dfc77d |
+| **Root State Commit**: 0068a04843d2c8e007086abaaee90c8c8cae8aa78f240048cd4d43aeb0376d0b |
+| **Git Commit**: 7f02a642bb437b45326c4ace54a7f033b32832f8 |
+| **Branch/Tag**: v0.29.6 |
+| **Docker Image Tag**: v0.29.6 |
+
+## Devnet 39
+
+| Spork Info |
+|:----------------------------------------------------------------------------------------|
+| **Date**: Jan 4th, 2023 |
+| **Root Height**: 90595736 |
+| **Root Parent ID**: 3d09b9703019b40a065787fff3dd62e28eafa5efcfb69efbc2d713d73034cf38 |
+| **Root State Commit**: afd47ff2a8e73efd51f0cbe7f572eefda25a66e77f1e6b9c4f3f4e7cdc46568f |
+| **Git Commit**: e1c172aaee7da9e33828429757b44f51e59368a2 |
+| **Branch/Tag**: v0.29.3 |
+| **Docker Image Tag**: v0.29.3 |
+
+## Devnet 38
+
+| Spork Info |
+|:----------------------------------------------------------------------------------------|
+| **Date**: Oct 19th, 2022 |
+| **Root Height**: 83007730 |
+| **Root Parent ID**: 1b914363c9a34c46b93974adeefb10c546578d7f3f4ac9291e01d746d2c84226 |
+| **Root State Commit**: 79df428bc27f22d38c233777610d93d33e180f23cfbc640a95d144a508e0f080 |
+| **Git Commit**: 3aae289f8f390f58ac481fd694254ea0e48960a8 |
+| **Branch/Tag**: v0.28.4 |
+| **Docker Image Tag**: v0.28.4 |
+
+## Devnet 37
+
+| Spork Info |
+|:----------------------------------------------------------------------------------------|
+| **Date**: Aug 10th, 2022 |
+| **Root Height**: 76159167 |
+| **Root Parent ID**: 8f379a8a86f28c7adef276890874b17786cecf5efb9e71734b0a780bd38660a0 |
+| **Root State Commit**: 7d1fe692ea2f857568dec54ddece094a68a9ba8ff8dd0de0664e6f73abb90dd8 |
+| **Git Commit**: 959911cabd50e1a11be45e89726952a90f1a9c22 |
+| **Branch/Tag**: v0.27.2 |
+| **Docker Image Tag**: v0.27.2 |
+
+## Devnet 36
+
+| Spork Info |
+|:----------------------------------------------------------------------------------------|
+| **Date**: July 27th, 2022 |
+| **Root Height**: 74786360 |
+| **Root Parent ID**: 9d9113ca8daa4f3be72e949ea9ead2d4b11db222b2ccd0dc897186ee5f8703ab |
+| **Root State Commit**: aa2e12033129f27b5320fb973cf109f562db3ad7ddaf50dbfe9d8cc195a7ac0f |
+| **Git Commit**: 13970fcae812bc04487422922f73eab39f53935c |
+| **Branch/Tag**: v0.26.17 |
+| **Docker Image Tag**: v0.26.17 |
+
+## Devnet 35
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Date**: June 9th, 2022 |
+| **Root Height**: 70072575 |
+| **Root Parent ID**: cd76fd9d5ceb1b98b5f30b0108f40836593c533ffe32eef0c6f3ed6d50bf645b |
+| **Root State Commit**: d933d73f48c9371f0a00ab7ffc1ed0daf5ba9e520d2d539e6b9494920c5ffd91 |
+| **Git Commit**: 07057c8d5fe2f09bbe5a9a3f8de6209346d910d0 |
+| **Branch/Tag**: v0.26.6 |
+| **Docker Image Tag**: v0.26.6 |
+
+## Devnet 34
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Date**: Apr 4th, 2022 |
+| **Root Height**: 64904846 |
+| **Root Parent ID**: 0cbb13d9e7ed7092b5f20d0a20a79d1cae96fd796fb2bc569b27ce49cc97d97e |
+| **Root State Commit**: f2e77e16628543e285be8bac677db06e17b37f49e53a107af1e6bf99fbc17b30 |
+| **Git Commit**: 5226c35eb14890db024b9193793b0c49d1b5ad04 |
+| **Branch/Tag**: v0.25.7 |
+| **Docker Image Tag**: v0.25.7 |
+
+## Devnet 33
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Date**: Feb 7th, 2022 |
+| **Root Height**: 59558934 |
+| **Root Parent ID**: 099fbb7b645c3441ea830746ed67059bcc1091c88ff3fd78b331137cf917d15f |
+| **Root State Commit**: 5b5578cb4ef6c34818ce2cfd9969720c7f17681f41dffa3a9e361935140d7c8e |
+| **Git Commit**: bd3dca7bf20914f5c019a325b6939bbb662aa131 |
+| **Branch/Tag**: v0.24.3 |
+| **Docker Image Tag**: v0.24.3 |
+
+## Devnet 32
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Date**: Dec 6th, 2021 |
+| **Root Height**: 53376277 |
+| **Root Parent ID**: f900db2ccff33f3bf353c8bf28ece0a9d2650f2805b23ddb7893e296774a5457 |
+| **Root State Commit**: 843ea0b5498342dcf960376585eeafee8ebe008df3b03325351408a100cb830c |
+| **Git Commit**: be20371fa8c5044a4e25e5629bbca91f1ed19731 |
+| **Branch/Tag**: v0.23.3 |
+| **Docker Image Tag**: v0.23.3 |
+
+## Devnet 31
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Date**: Nov 5th, 2021 |
+| **Root Height**: 50540412 |
+| **Root Parent ID**: cfebaa6b8c19ec48a27eaa84c3469b23255350532b5ea4c7e4c42313386c07b6 |
+| **Root State Commit**: 31a2b1eb05a6acb91560970e46b8f3f3171747245eae1ad2bf40290ce773806e |
+| **Git Commit**: 3d060b90264d59ccd38b4500ae0cd6d72036cfe4 |
+| **Branch/Tag**: v0.23-testnet |
+| **Docker Image Tag**: v0.23.1 |
+
+## Devnet 30
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Date**: Oct 6th, 2021 |
+| **Root Height**: 47330085 |
+| **Root Parent ID**: 0ec9172a21f84cbae15761ae4d59ab4a701f9d4fd15cd0632715befc8cf205cf |
+| **Root State Commit**: e280f972c72c6b379ec3d4a7173953e596704d8d72f384ef1637d2f4f01ff901 |
+| **Git Commit**: f019c1dbd778ce9f92dea61349ca36003678a9ad |
+| **Branch/Tag**: v0.22.8-patch-1-scripts-and-errors |
+| **Docker Image Tag**: v0.22.8-patch-1-scripts-and-errors |
+
+## Devnet 29
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Date**: Oct 5th, 2021 |
+| **Root Height**: 47242826 |
+| **Root Parent ID**: 00f745576222a1e7e15ee79974b4b3eaddd760fb4f56e846cfaef3cb5ea59d50 |
+| **Root State Commit**: 3c5bfb88a3fa184c9981e7677d1f2a2cd0a4eaa581bb2a7867b7b023ae015f38 |
+| **Git Commit**: e1659aebc39b4a15c68112227fc8c32788a798b6 |
+| **Branch/Tag**: v0.22.8 |
+| **Docker Image Tag**: v0.22.8 |
+
+## Devnet 28
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Date**: Sept 22, 2021 |
+| **Root Height**: 45889254 |
+| **Root Parent ID**: 1518c15f7078cb8fd4c636b9fc15ee847ac231a8631ed59a0b8c9d4a182fb5b2 |
+| **Root State Commit**: 296001ee05ce3e6c6616ad9bcdc20e6d93d02c91354e57fff6054cff44c5afa3 |
+| **Git Commit**: a979f4d25a79630581f6b350ad26730d4012cad4 |
+| **Branch/Tag**: v0.21.6 |
+| **Docker Image Tag**: v0.21.6 |
+
+## Devnet 27
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Date**: Sept 14, 2021 |
+| **Root Height**: 45051578 |
+| **Root Parent ID**: 8525ac24717b5f42e29172f881e9a7439235e4cd443a8a59494dbecf07b9376a |
+| **Root State Commit**: b3ef3b039f722130009b658e3f5faee43b3b9202fec2e976907012994a8fc9be |
+| **Git Commit**: 4f903f1d45e6f8c997a60de47de62a74ede3c2e4 |
+| **Branch/Tag**: v0.21.3 |
+| **Docker Image Tag**: v0.21.3 |
+
+## Devnet 26
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Date**: Aug 11, 2021 |
+| **Root Height**: 41567027 |
+| **Root Parent ID**: ea465f33266be26b21c82ec728c75cc0dcbb022405d83c44ed0082b0df9aa81d |
+| **Root State Commit**: 9459485a2a640b1bdc3066916a9a46dc20bf2528a03f06ddc541d34444c3264c |
+| **Git Commit**: 781ec414b892e2ccf7034aa263b5b19d97f82031 |
+| **Branch/Tag**: v0.20.4 |
+| **Docker Image Tag**: v0.20.4 |
+
+## Devnet 25
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Date**: July 20, 2021 |
+| **Root Height**: 39272449 |
+| **Root Parent ID**: 2824828e7c87e1a89bc94daca9497625f1a35c8f9fc555f52d1f8b475179e125 |
+| **Root State Commit**: bd50708e7808be0d43725a9eae6039558b32b679c5a584a2e6103bb027dad7eb |
+| **Git Commit**: 2644560c0562412a3c2209820be07f8f3f8b1846 |
+| **Branch/Tag**: v0.19.2 |
+| **Docker Image Tag**: v0.19.2 |
+
+## Devnet 24
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Date**: June 22, 2021 |
+| **Root Height**: 36290422 |
+| **Root Parent ID**: 8d6fad91536ec750d1bb44ebb59e030af2dca49d41c104e45f4f82433184e663 |
+| **Root State Commit**: fdfd7a9fff481256972095ffc2c6cba300128f41d8c6aa971985de29427eb39d |
+| **Git Commit**: 37d9ae7a309bf7d21063f57fce008d04828d4840 |
+| **Branch/Tag**: v0.18.3 |
+| **Docker Image Tag**: v0.18.3 |
+
+## Devnet 23
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Date**: May 25, 2021 |
+| **Root Height**: 33257098 |
+| **Root Parent ID**: dafa3e7a9a93de8ceb0a3acd09b2cce4ad0e5d7ea8fe4237f27c4503e5ad416c |
+| **Root State Commit**: decf340a722ba136c94ece029e9333d9fbcf216482cd1c81a274365e2abd6688 |
+| **Git Commit**: fef838147fa70c94a254183e23e7e79f0d412ef6 |
+| **Branch/Tag**: v0.17.3 |
+| **Docker Image Tag**: v0.17.3 |
+
+## Devnet 22
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Date**: Apr 27, 2021 |
+| **Root Height**: 30171528 |
+| **Root Parent ID**: 46c7c675f2ed413532009a6a6ecaa566d360a806e033693520d7add147ca89ea |
+| **Root State Commit**: d88edf1b2a07dba9ef48214dbffb743c0b2e01f7c74e3e14d828ac076d30f1a6 |
+| **Git Commit**: 8331b78d99eddea405076e3b6a7839ec5f6ea209 |
+| **Branch/Tag**: v0.16.2 |
+| **Docker Image Tag**: v0.16.2 |
+
+## Devnet 21
+
+| Spork Info |
+| :-------------------------------------------------------------------------------------- |
+| **Date**: Mar 30, 2021 |
+| **Root Height**: 26935025 |
+| **Root Parent ID**: 3f92949a68c577b6d7d17267f00fc47304d1c44052f0c9a078b63fd344f636dd |
+| **Root State Commit**: 21f48748d35178bd6ad89f6324321fa9d123ee7a07b07826acbce887260b2c70 |
+| **Git Commit**: 8331b78d99eddea405076e3b6a7839ec5f6ea209 |
+| **Branch/Tag**: v0.15.3-patch.1 |
+| **Docker Image Tag**: v0.15.3-patch.1 |
+
+## Devnet 20
+
+| Spork Info |
+| :------------------------------------------------------------------------------------- |
+| **Date**: Mar 9, 2021 |
+| **Root Height**: 25450390 |
+| **Root Parent ID**: febe212117a83f7f70ed6a5af285ff03332f81a1120ab2c306560c4cb42672f7 |
+| **Root State Commit**: 828259e9cb895f7f8a7306debbe6de524500db65cb6b80e27b2db9040513b04e |
+| **Git Commit**: b9b197280d6590576f1ef183bc3d04d41d6be587 |
+| **Branch/Tag**: v0.14.19 |
+| **Docker Image Tag**: v0.14.19 |
+
+---
+
+## Devnet 19
+
+| Spork Info |
+| :------------------------------------------------------------------------------------- |
+| **Date**: Feb 3, 2021 |
+| **Root Height**: 16483518 |
+| **Root Parent ID**: 4220911048404bd3a7733ab6219531a5945dc20020f86869bcd6422c3a6e3f76 |
+| **Root State Commit**: f6eea9b652a7df433b80d8d647ba414aabcfa03153dd1cba33048c27ce888097 |
+| **Git Commit**: eb11ae095df6db6e856b1a8e824f03ce4c713b19 |
+| **Branch/Tag**: v0.14.0 |
+| **Docker Image Tag**: v0.14.0 |
+
+---
+
+## Devnet 18
+
+| Spork Info |
+| :------------------------------------------------------------------------------------- |
+| **Date**: Dec 11, 2020 |
+| **Root Height**: 17756122 |
+| **Root Parent ID**: 52ace0d0c8d4e574213fe98e19a5043f215bee992659bd1ef35c5758acf54d1b |
+| **Root State Commit**: b1412c9d453b1c10d3ace6111e00ac804d564ba3d3295002bedb077685c7da73 |
+| **Git Commit**: 115ccee9cae920ee5bc309537cf43a9b152a1cf9 |
+| **Branch/Tag**: v0.13.0 |
+| **Docker Image Tag**: v0.13.0 |
+
+---
+
+## Devnet 17
+
+| Spork Info |
+| :------------------------------------------------------------------------------------- |
+| **Date**: Nov 27, 2020 |
+| **Root Height**: 16483518 |
+| **Root Parent ID**: 96d452f9d2a15fafab720f1809fc490b019b23e42c885590e62085e48b8c2b6b |
+| **Root State Commit**: 0b45f6055a1f09b413d098997cc0e7c9a0ef19eac8b4d294085b0e2f436c6bff |
+| **Git Commit**: ef54713595d0fe1e0bb4b14e9469c4a64dfaf6e7 |
+| **Branch/Tag**: v0.12.1 |
+| **Docker Image Tag**: v0.12.1 |
+
+
+=== networks/node-ops/node-operation/node-setup.md ===
+---
+title: Setting Up a Flow Node
+sidebar_label: Node Setup
+description: How to run a Collection, Consensus, Verification and Execution node
+sidebar_position: 12
+---
+
+This guide is for running a Collection, Consensus, Verification and Execution node.
+If you are planning to run an Access node then refer to [access node setup](../access-nodes/access-node-setup.md).
+
+First you'll need to provision a machine or virtual machine to run your node software. Please see follow the [node-provisioning](./node-provisioning.md) guide for it.
+
+## Pull the Flow Images
+
+The `flow-go` binaries are distributed as container images, and need to be pulled down to your host with your image management tool of choice.
+
+Replace `$ROLE` with the node type you are planning to run. Valid options are:
+
+- collection
+- consensus
+- execution
+- verification
+- access
+
+```shell
+ # Docker
+ docker pull gcr.io/flow-container-registry/${ROLE}:alpha-v0.0.1
+
+ # Containerd
+ ctr images pull gcr.io/flow-container-registry/${ROLE}:alpha-v0.0.1",
+```
+
+## Prepare Your Node to Start
+
+Your nodes will need to boot at startup, and restart if they crash.
+
+If you are running `systemd` you can use the service files provided by `flow-go`.
+Find them in the [Flow Go](https://github.com/onflow/flow-go/tree/master/deploy).
+
+If you are using some other system besides Systemd, you need to ensure that the Flow container is started,
+the appropriate key directories are mounted into the container, and that the container will
+automatically restart following a crash.
+
+The `systemd` files pull runtime settings from `/etc/flow/runtime-config.env` and any `.env`
+files under `/etc/flow/conf.d`. Examples of these files are also available in the github repo.
+You will need to modify the runtime config file later.
+
+### Systemd
+
+
+If you are not using Systemd, you can skip this step
+
+
+1. Ensure that you pulled the latest changes from [flow-go repository](https://github.com/onflow/flow-go) via `git`
+
+```shell
+## Clone the repo if you haven't already done so
+git clone https://github.com/onflow/flow-go
+
+## Get latest changes
+cd flow-go
+git pull origin master
+```
+
+2. Copy your respective [systemd unit file](https://github.com/onflow/flow-go/tree/master/deploy/systemd-docker) to: `/etc/systemd/system`
+3. Create directory `sudo mkdir /etc/flow`
+4. Copy the [runtime-conf.env](https://github.com/onflow/flow-go/blob/master/deploy/systemd-docker/runtime-conf.env) file to: `/etc/flow/`
+5. Enable your service `sudo systemctl enable flow-$ROLE.service` (replace `$ROLE` with your node role - eg. `collection`)
+
+### Docker Configuration
+
+If you are not using Systemd, sample commands for running each Docker container are below.
+Be sure to replace `/path/to/data` and `/path/to/bootstrap` with the appropriate paths you are using.
+
+:::warning
+
+Do not run your node using `docker run` command directly without a mechanism for the node
+to automatically restart following a crash.
+
+:::
+
+:::info
+
+The actual Docker image tag can be found [here](./past-upgrades) for appropriate spork.
+
+:::
+
+### System Configuration
+
+Flow nodes create connections to other nodes on the network, which are represented as file descriptors by the OS. Depending on the default
+limits for your machine, you may need to increase the soft limit available to the node software.
+
+Make sure the soft limit is at least `8192`.
+
+You can configure the ulimit for the node's docker container. See the [Docker documentation](https://docs.docker.com/engine/networks/commandline/run/#ulimit) for more details.
+
+### Admin Server
+
+Each node can be configured with an admin server, which allows you to control some of the node's configuration, as well as view some of its internal state. You can find
+a few of the commands in the Admin Server [README](https://github.com/onflow/flow-go/blob/master/admin/README.md). Two commands to highlight are:
+
+* `list-commands`: which returns a list of all of the available commands for your node
+* `set-log-level`: which allows you to change the log level of your node at runtime
+
+You can enable the admin server by passing the `--admin-addr` flag with an interface and port.
+
+> ⚠️ _IMPORANT: The admin server can modify your node's configuration. DO NOT allow access to untrusted clients._
+
+### Access
+
+```shell
+docker run --rm \
+ -v /path/to/bootstrap:/bootstrap:ro \
+ -v /path/to/data:/data:rw \
+ --name flow-go \
+ --network host \
+ --ulimit nofile=8192 \
+ gcr.io/flow-container-registry/access: \
+ --nodeid=${FLOW_GO_NODE_ID} \
+ --bootstrapdir=/bootstrap \
+ --datadir=/data/protocol \
+ --secretsdir=/data/secrets \
+ --execution-data-dir=/data/execution_data \
+ --rpc-addr=0.0.0.0:9000 \
+ --http-addr=0.0.0.0:8000 \
+ --admin-addr=0.0.0.0:9002 \
+ --collection-ingress-port=9000 \
+ --script-addr=${FLOW_NETWORK_EXECUTION_NODE} \
+ --bind 0.0.0.0:3569 \
+ --loglevel=error
+```
+
+### Collection
+
+```shell
+docker run --rm \
+ -v /path/to/bootstrap:/bootstrap:ro \
+ -v /path/to/data:/data:rw \
+ --name flow-go \
+ --network host \
+ --ulimit nofile=8192 \
+ gcr.io/flow-container-registry/collection: \
+ --nodeid=${FLOW_GO_NODE_ID} \
+ --bootstrapdir=/bootstrap \
+ --datadir=/data/protocol \
+ --secretsdir=/data/secrets \
+ --ingress-addr=0.0.0.0:9000 \
+ --admin-addr=0.0.0.0:9002 \
+ --bind 0.0.0.0:3569 \
+ --access-node-ids=4e17496619df8bb4dcd579c252d9fb026e54995db0dc6825bdcd27bd3288a990,7e3fe64ccc119f578a7795df8b8c512e05409bdc7de4f74259c6f48351fecb26,416c65782048656e74736368656c009530ef3ab4b8bf83b24df54fe5f81853de,416e647265772042757269616e00d219355d62b9adad8ebd3fab223a1cf84c22 \
+ --gossipsub-peer-scoring-enabled=false \
+ --gossipsub-peer-gater-enabled=true \
+ --loglevel=error
+```
+
+### Consensus
+
+```shell
+docker run --rm \
+ -v /path/to/bootstrap:/bootstrap:ro \
+ -v /path/to/data:/data:rw \
+ --name flow-go \
+ --network host \
+ --ulimit nofile=8192 \
+ gcr.io/flow-container-registry/consensus: \
+ --nodeid=${FLOW_GO_NODE_ID} \
+ --bootstrapdir=/bootstrap \
+ --datadir=/data/protocol \
+ --secretsdir=/data/secrets \
+ --admin-addr=0.0.0.0:9002 \
+ --bind 0.0.0.0:3569 \
+ --access-node-ids=4e17496619df8bb4dcd579c252d9fb026e54995db0dc6825bdcd27bd3288a990,7e3fe64ccc119f578a7795df8b8c512e05409bdc7de4f74259c6f48351fecb26,416c65782048656e74736368656c009530ef3ab4b8bf83b24df54fe5f81853de,416e647265772042757269616e00d219355d62b9adad8ebd3fab223a1cf84c22 \
+ --gossipsub-peer-scoring-enabled=false \
+ --gossipsub-peer-gater-enabled=true \
+ --loglevel=error
+```
+
+### Execution
+
+```shell
+docker run --rm \
+ -v /path/to/bootstrap:/bootstrap:ro \
+ -v /path/to/data:/data:rw \
+ --name flow-go \
+ --network host \
+ --ulimit nofile=500000 \
+ gcr.io/flow-container-registry/execution: \
+ --nodeid=${FLOW_GO_NODE_ID} \
+ --bootstrapdir=/bootstrap \
+ --datadir=/data/protocol \
+ --secretsdir=/data/secrets \
+ --triedir=/data/execution \
+ --execution-data-dir=/data/execution_data \
+ --rpc-addr=0.0.0.0:9000 \
+ --admin-addr=0.0.0.0:9002 \
+ --bind 0.0.0.0:3569 \
+ --loglevel=error
+```
+
+For execution nodes, it is recommend to increase the open files limit in your operating system. To do that, add the following to your `/etc/security/limits.conf` or the equivalent `limits.conf` for your distribution:
+
+```
+* hard nofile 500000
+* soft nofile 500000
+root hard nofile 500000
+root soft nofile 500000
+```
+
+Restart your machine to apply these changes. To verify that the new limits have been applied, run:
+
+```
+ulimit -n
+```
+
+### Verification
+
+```shell
+docker run --rm \
+ -v /path/to/bootstrap:/bootstrap:ro \
+ -v /path/to/data:/data:rw \
+ --name flow-go \
+ --network host \
+ --ulimit nofile=8192 \
+ gcr.io/flow-container-registry/verification: \
+ --nodeid=${FLOW_GO_NODE_ID} \
+ --bootstrapdir=/bootstrap \
+ --datadir=/data/protocol \
+ --secretsdir=/data/secrets \
+ --admin-addr=0.0.0.0:9002 \
+ --bind 0.0.0.0:3569 \
+ --loglevel=error
+```
+
+## Start the Node
+
+Now that your node is provisioned and configured, it can be started.
+
+
+
+Before starting your node, ensure it is [registered](./node-bootstrap.md#step-2---stake-your-node) and [authorized](./node-bootstrap.md#confirming-authorization).
+
+
+
+Ensure you start your node at the appropriate time.
+See [Spork Process](./spork.md) for when to start up a node following a spork.
+See [Node Bootstrap](./node-bootstrap.md#timing) for when to start up a newly registered node.
+
+### Systemd
+
+1. Check that your `runtime-conf.env` is at `/etc/flow/runtime-conf.env`
+2. Update your environment variables: `source /etc/flow/runtime-conf.env`
+3. Start your service: `sudo systemctl start flow`
+
+## Verify your Node is Running
+
+
+Here are a few handy commands that you can use to check if your Flow node is up and running
+
+### Systemd
+
+- To get Flow logs: `sudo journalctl -u flow-YOUR_ROLE`
+- To get the status: `sudo systemctl status flow`
+
+```shell
+● flow-verification.service - Flow Access Node running with Docker
+Loaded: loaded (/etc/systemd/system/flow-verification.service; enabled; vendor preset: enabled)
+Active: active (running) since Wed 2020-05-20 18:18:13 UTC; 1 day 6h ago
+Process: 3207 ExecStartPre=/usr/bin/docker pull gcr.io/flow-container-registry/verification:${FLOW_GO_NODE_VERSION} (code=exited, status=0/SUCCESS)
+Main PID: 3228 (docker)
+Tasks: 10 (limit: 4915)
+Memory: 33.0M
+CGroup: /system.slice/flow-verification.service
+ └─3228 /usr/bin/docker run --rm -v /var/flow/bootstrap:/bootstrap:ro -v /var/flow/data:/data:rw --rm --name flow-go --network host gcr.io/flow-container-registry/verification:candidate8 --nodeid=489f8a4513d5bd8b8b093108fec00327b683db545b37b4ea9153f61b2c0c49dc --bootstrapdir=/bootstrap --datadir=/data/protocol --alpha=1 --bind 0.0.0.0:3569 --loglevel=error
+```
+
+### Docker
+
+- To get Flow logs: `sudo docker logs flow-go`
+- To get the status: `sudo docker ps`
+
+```shell
+$ sudo docker ps
+CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
+1dc5d43385b6 gcr.io/flow-container-registry/verification:candidate8 \"/bin/app --nodeid=4…\" 30 hours ago Up 30 hours flow-go
+```
+
+## Monitoring and Metrics
+
+This is intended for operators who would like to see what their Flow nodes are currently doing. Head over to [Monitoring Node Health](./monitoring-nodes.md) to get setup.
+
+### Node Status
+
+The metrics for the node should be able to provide a good overview of the status of the node. If we want to get a quick snapshot of the status of the node, and if it's properly participating in the network, you can check the `consensus_compliance_finalized_height` or `consensus_compliance_sealed_height` metric, and ensure that it is not zero and strictly increasing.
+
+```shell
+curl localhost:8080/metrics | grep consensus_compliance_sealed_height
+
+# HELP consensus_compliance_sealed_height the last sealed height
+# TYPE consensus_compliance_sealed_height gauge
+consensus_compliance_sealed_height 1.132054e+06
+```
+
+
+=== networks/node-ops/node-operation/node-roles.md ===
+---
+title: Node Roles
+sidebar_position: 11
+---
+
+Unlike most blockchains, not all Flow nodes are equal. Flow nodes all specialize and fulfill a specific role in the operation of the network.
+Collection, consensus, execution, verification and access nodes are all staked nodes while the observer node is not staked.
+
+## Collection
+
+Collection nodes are bandwidth-optimized nodes divided by the protocol into several cooperating Clusters. Their first task is managing the transaction pool and collecting well-formed transactions to propose to Consensus nodes. Transactions are assigned to a cluster pseudorandomly by transaction hash. A well-formed transaction must include credentials from the guarantor of the transaction. When a Collection Node sees a well-formed transaction, it hashes the text of that transaction and signs the transaction to indicate two things: first, that it is well-formed; and second, that it will commit to storing the transaction text until the Execution nodes have finished processing it. Each cluster collects transactions, assembles them into Collections and submits a Collection Guarantee signed by a super-majority of the cluster to the Consensus nodes.
+
+Collection nodes are required to stake a minimum of 250,000 FLOW to be a confirmed node operator.
+
+## Consensus
+
+Consensus nodes form and propose blocks in a manner similar to traditionally-structured proof-of-stake blockchains, using the HotStuff consensus algorithm to create a globally consistent chain of blocks. Consensus nodes validate that the signed collection hashes submitted to them by Collection nodes were, in fact, signed by the required majority of Collection nodes. Thereafter, the Consensus nodes assemble the transactions into blocks and finalize them through voting.
+The more participants there are in this process, the more decentralized the network. However, consensus algorithms typically bottleneck the limit to the number of participants. The Flow protocol chose the HotStuff algorithm because it is flexible enough to add participants and currently supports about 100 operators. Adding more than 100 participants to the protocol by adapting HotStuff will continue to be an area of active development.
+
+Consensus nodes act as checkpoints against other Collection nodes. They are responsible for checking that a critical number of Collection nodes reviewed and signed for the transaction. Collection nodes are held accountable by Consensus nodes. A common concern with proof-of-work- and proof-of-stake based systems is that a small subset of the population of nodes can control important resources such as the mining or stake needed to produce and vote on blocks, which is a degradation of the security of the system. By lowering the requirements to participate, Flow makes it extremely difficult and expensive to coordinate a Byzantine majority of Consensus nodes.
+
+Consensus nodes have minimal bandwidth and computation requirements, allowing even a modest computing device (any consumer-grade hardware) to participate in the voting process and ensure the safety of the network. Many networks claim open participation, yet substantial resources — stake, computation, or otherwise — are needed to partake. Maintaining such barriers to entry undermines the security of the network. Lowering the participation requirements preserves the security of the network by providing a high degree of byzantine fault tolerance since it becomes exceedingly difficult for a subset of bad actors to subvert the network.
+
+Consensus nodes are required to stake a minimum of 500,000 FLOW to be a confirmed node operator.
+
+## Execution
+
+Execution nodes are the most resource-intensive nodes on the Flow network, responsible for executing transactions and maintaining the Execution State — a cryptographically-verifiable data store for all user accounts and smart contract states — as well as responding to queries related to it. Execution nodes compute the outputs of the blocks they are provided. They then ask the Collection nodes for the collections which contain transactions waiting to be executed. With this data they are able to compute the output, which is later verified by Verification nodes to ensure honesty (allocation of Verification nodes is via a sortition algorithm). The Execution nodes are primarily responsible for Flow's improvements in scale and efficiency because only a very small number of these powerful compute resources are required to compute and store the historical state.
+
+Execution nodes give the Flow network its performance characteristics: highly scalable within a single shared state environment (i.e., no sharding). However, the significant hardware requirements make them the least accessible option for participation as a Validator. Because the revenue pool splits between relatively few nodes, the revenue per-node should more than compensate for the high capital costs of operating this node.
+
+An Execution Node presents a hashed commitment once it has computed the output. The output is only revealed once its co-executors have also submitted their outputs. This is important to ensure nodes aren't spoofing each other's work. Once they've all submitted their answers, the output is revealed and subjected to random queries and checks run by Verification nodes. The Execution nodes have relatively low byzantine fault tolerance. However, this does not compromise the overall security of the system because the process they perform is deterministic -- any bad actor will easily be detected and punished by Verification nodes.
+
+This relatively small group of nodes has the most substantial technical requirements for processor speed and bandwidth because they are tasked with all the computations necessary to determine the output of the network. Allowing for this degree of specialization can reduce computation costs by at least one thousand times, and possibly much more, when compared to Ethereum.
+
+Execution nodes are required to stake a minimum of 1,250,000 FLOW to be a confirmed node operator.
+
+## Verification
+
+Verification nodes are responsible for confirming the correctness of the work done by Execution nodes. Individual Verification nodes only check a small amount of the total computation, but collectively they check every computation many times in parallel. Verification nodes verify Execution Receipts provided by Execution nodes and issue Result Approvals. A sortition algorithm determines which chunks of the Execution Receipt from the Execution nodes the Verification Node must query to check they were computed correctly. Ultimately, these nodes keep the Execution nodes honest; this balance of power maintains the access, security, and verifiability criteria of decentralization. It is highly byzantine fault tolerant because even if there is a substantial number of byzantine errors in the Verification Node
+pool, the Consensus nodes are still required to approve that transactions they signed were reviewed by a critical amount of the network.
+
+Verification nodes are required to stake a minimum of 135,000 FLOW to be a confirmed node operator.
+
+## Access
+
+Access nodes act as a proxy to the Flow network. The Access node routes transactions to the correct collection node and routes state queries to execution nodes (while likely caching state to answer queries in a timely manner in the future). Clients submit their transactions to any Access node or run their own if they can't find a service provider they're happy with.
+
+Access nodes are required to stake 100 FLOW to be a confirmed node operator. However, since an access node does not participate in block production, it does not receive any staking rewards.
+
+## Observer
+
+An observer node provides locally accessible, continuously updated, verified copy of the block data. It serves the Access API but unlike an access node, an observer node does not need to be staked, and **anyone** can run it without being added to the approved list of nodes.
+
+[Get started running an observer node](../light-nodes/observer-node.md)
+
+##
+
+Here is a comparison of the different node roles,
+
+| Role | Staked | Recives Rewards | Permissioned |
+| :---------------|:---------------:| :---------------:|:---------------:|
+| Collection | Yes | Yes | Yes |
+| Consensus | Yes | Yes | Yes |
+| Execution | Yes | Yes | Yes |
+| Verification | Yes | Yes | Yes |
+| Access | Yes | No | No 🆕 |
+| Observer | No | No | No |
+
+
+=== networks/node-ops/node-operation/node-provisioning.md ===
+---
+title: Provisioning a Flow node
+sidebar_label: Node Provisioning
+description: Hardware, networking and Operating system setup for a Flow node
+sidebar_position: 10
+---
+
+## Hardware Requirements
+
+The hardware your Node will need varies depending on the role your Node will play in the Flow network. For an overview of the differences see the [Node Roles Overview](./node-roles.md).
+
+| Node Type | CPU | Memory | Disk | Example GCP Instance | Example AWS Instance |
+|:----------------:| ---------:| ------:| ------:|:--------------:|:--------------:|
+| **Collection** | 4 cores | 32 GB | 200 GB | n2-highmem-4 | r6i.xlarge |
+| **Consensus** | 2 cores | 16 GB | 200 GB | n2-standard-4 | m6a.xlarge |
+| **Execution** | 128 cores | 864 GB | 9 TB (with maintenance see: [pruning chunk data pack](https://forum.flow.com/t/execution-node-upgrade-to-v0-31-15-and-managing-disk-space-usage/5167) or 30 TB without maintenance) | n2-highmem-128 | |
+| **Verification** | 2 cores | 16 GB | 200 GB | n2-highmem-2 | r6a.large |
+| **Access** | 16 cores | 64 GB | 750 GB | n2-standard-16 | m6i.4xlarge |
+| **Observer** | 2 cores | 4 GB | 300 GB | n2-standard-4 | m6i.xlarge |
+| **EVM Gateway** | 2 cores | 32 GB | 30 GB | n2-highmem-4 | r6i.xlarge |
+
+_Note: The above numbers represent our current best estimate for the state of the network. These will be actively updated as we continue benchmarking the network's performance._
+
+## Networking Requirements
+
+Most of the load on your nodes will be messages sent back and forth between other nodes on the network. Make sure you have a sufficiently fast connection; we recommend at _least_ 1Gbps, and 5Gbps is better.
+
+Each node will require a fixed DNS name and we will refer to this more generally as your 'Node Address' from here on out.
+
+
+ Your Node Address must be a publicly routable valid DNS name
+ that points to your node. This is how other nodes in the network will
+ communicate with you.
+
+
+Your firewalls must expose **TCP/3569** for both, ingress and egress.
+
+If you are running an Access Node, you must also expose the GRPC port **9000** to your internal network traffic. Port 9000 is not required for external ingress/egress.
+
+
+
+## Operating System Requirements
+
+The Flow node code is distributed as a Linux container image, so your node must be running an OS with a container runtime like [docker](https://docker.com) or [containerd](https://containerd.io).
+
+The bootstrapping scripts we'll use later are compiled binaries targeting an `amd64` architecture, so your system must be 64-bit. Some of these scripts are bash based hence a shell interpreter that is bash compatible will also be needed.
+
+Flow also provides `systemd` service and unit files as a template for installation, though `systemd` is not required to run Flow.
+
+
+ Flow is distributed in such a way that makes it very system agnostic. You are
+ free to build your own orchestration around how you run your nodes and manage
+ your keys.
+
+ For the remainder of this guide, we cover the most simple case, a single node being
+ hand deployed. This should give you a good sense of what's needed, and you can
+ modify to suit your needs from there.
+
+ The Flow team has tested running nodes on Ubuntu 18.04 and GCP's Container
+ Optimized OS, which is based on Chromium OS. If you are unsure where to start,
+ those are good choices.
+
+
+## Time synchronization
+
+You should also ensure you run **time synchronization** on the machine hosting the container, to avoid clock drift. In practice, this means configuring a client for the NTP protocol, and making sure it runs as a daemon. `ntpd` is one recommended example. To configure it, you just have to point it to an NTP server to query periodically. A default from your Linux distribution or cloud operator may already be set, and in the interest of decentralization, our recommendation would be to use it unless you have a specific reason to do otherwise.
+
+
+
+ - **Leap-smearing**: Leap-smearing time servers and non-leap-smearing time servers are both acceptable for the magnitude of our time precision requirements - though considering very few providers offer leap smearing time servers, a "regular" time server helps ensure our pool of time providers is more diverse.
+
+ - **Why not do it in the container itself? Why do we need to do this?**: Without special privileges and in all major container runtimes, a container will not run with the `CAP_SYS_TIME` capability. For Flow, this means that the node software itself cannot change the time of the host machine, making the in-container use of standard time synchronization protocols ineffective.
+
+ - **Why does time matter in Flow?**: Time information comes up in consensus and in smart contracts. The consensus algorithm of Flow allows nodes to exit the influence of a corrupt or ineffective "leader" node by collectively deciding to switch to the next "phase" of the protocol at the right time. The smart contract language also allows developer access to block time stamps, which provide an approximation of time. To resist manipulation in each case, honest nodes must compute timing values from an aggregate of the information provided by all nodes. That approach, though resilient, is still sensitive to inaccurate time information. In other words, a node subject to clock drift but otherwise honest will not stop the consensus, but might make it slower.
+
+
+
+## Setup Data Directories & Disks
+
+Flow stores protocol state on disk, as well as execution state in the case of execution nodes.
+
+Where the data is stored is up to you. By default, the `systemd` files that ship with Flow use `/var/flow/data`.
+This is where the vast majority of Flow's disk usage comes from, so you may wish to mount this directory on a separate disk from the OS.
+The performance of this disk IO is also a major bottleneck for certain node types.
+While all nodes need to make use of this disk, if you are running an execution node, you should make sure this is a high performing SSD.
+
+As a rough benchmark for planning storage capacity, each Flow block will grow the data directory by 3-5KiB.
+
+### Confidential Data & Files
+
+Flow stores dynamically generated confidential data in a separate database. We strongly recommend enabling encryption
+for this database - see [this guide](./db-encryption-existing-operator.md) for instructions.
+
+Confidential information used by Flow is stored in the `private-root-information` subtree of the `bootstrap` folder.
+In particular:
+* the staking private key (`node-info.priv.json`)
+* the networking private key (`node-info.priv.json`)
+* the encryption key for the secrets database (`secretsdb-key`)
+* (if applicable) the initial random beacon private key (`random-beacon.priv.json`)
+
+These files contain confidential data, and must be stored and accessed securely.
+
+
+
+=== networks/node-ops/node-operation/node-providers.md ===
+---
+sidebar_position: 18
+description: |
+ Easy access to Flow's blockchain. Providers handle the technical work, letting you use Flow's features without managing nodes yourself.
+sidebar_custom_props:
+ icon: 📚
+---
+
+# Node Providers
+
+## Quick Node
+
+[QuickNode](https://www.quicknode.com/chains/flow) offers convenient access to Flow's blockchain infrastructure, allowing developers and businesses to utilize Flow's capabilities without the complexities of managing nodes themselves. It offers reliable and fast connectivity to blockchain networks, sparing users from the resource-intensive task of running their own full nodes.
+
+### Supported Networks
+
+- Testnet
+- Mainnet
+
+## Tatum
+
+[Tatum](https://tatum.io/) provides a comprehensive platform that simplifies the process of building, testing, and deploying blockchain applications. With Tatum, users can access infrastructure, an SDK, and a unified API to develop blockchain apps without the need to handle individual blockchain node configuration or maintenance.
+
+### Supported Networks
+
+- Testnet
+- Mainnet
+
+=== networks/node-ops/node-operation/node-migration.md ===
+---
+title: Node Migration
+description: How to migrate a Flow node from one machine to another
+sidebar_position: 9
+---
+
+There are a few different methods to migrate a running Flow node from one machine to the other.
+
+Choose the method depending upon what part of the staking data of the node is changing.
+
+### Method 1 - No change to the node staking data
+
+If there is no change to the network address or the staking and networking keys and only the hardware the node is running needs to be changed then do the following:
+1. Stop the Flow node.
+2. Copy over the bootstrap data (typically under `/var/flow/bootstrap`) which contains the node private key to the new machine.
+3. Copy over the data folder (typically under `/var/flow/data`) which contains the state data.
+4. Start the new node on the same network address as the old one.
+
+:::warning
+
+Please ensure that there is minimal downtime during this migration.
+
+:::
+
+:::warning
+
+The network address is currently part of the staking data that was submitted for the node. It is how other nodes in the network discover this node.
+Hence, the network address of the node must stay the same between epochs otherwise the node will become unreachable for the other nodes and stop functioning.
+
+:::
+
+### Method 2 - Network address change
+
+A change to the node network address (IP or a hostname) can only be done during the spork process.
+
+To change the networking address:
+1. A day before the [upcoming mainnet spork](./upcoming-sporks.md), change the network address for the nodes in Flow Port (using the update network address feature).
+The change will not take effect till an epoch transition happens.
+2. Change the addresses in the `/var/flow/bootstrap/private-root-information/private-node-info_/node-info.priv.json` json file on the node.
+3. A spork also causes an epoch transition, and the new addresses will take effect after the spork immediately.
+
+### Method 3 - Staking or networking key change
+
+If the node after migration will be using new staking or networking keys then it needs to be unstaked and then re-staked with the new keys.
+
+1. Unstake the node via Flow Port.
+2. Register the new node via Flow Port with the new staking information.
+3. Run the new node with the new keys and network address. It should be able to join the network at the next epoch (see [timing](./node-bootstrap.md#timing))
+
+:::warning
+
+Unstaking a node will result in the node [not earning rewards](../../staking/06-technical-overview.md#staking-operations-available-to-all-stakers) for the next epoch.
+Delegators to the old node will have their tokens unstaked automatically. They will also stop earning rewards unless they withdraw their unstaked tokens and delegate them to a different node.
+
+:::
+
+
+=== networks/node-ops/node-operation/node-economics.md ===
+---
+title: Node Economics
+sidebar_label: Node Economics
+description: Node Operator Economics - An illustration
+sidebar_position: 8
+---
+
+Node operators play a crucial role in securing the Flow network. Here’s a simple example to illustrate what node operators can expect in terms of node economics.
+
+## Node Operator Economics: An illustration
+
+
+:::warning
+
+This illustration is strictly to serve as an example. Actual numbers will vary based on several factors.
+
+For real-time numbers, please refer to the [block explorer](https://www.flowscan.io/tokenomics).
+
+:::
+
+
+| # | Parameter | Value | Explanation |
+| -------- | ------------- | ------------- | ------------- |
+| A| Node Operator’s Stake | 500,000 FLOW | Assuming minimum staking requirements for a consensus node. Remember there’s no upper cap on how much FLOW can be staked to a Flow node. |
+| B| Delegation to node | 1,000,000 FLOW | Funds that individual/ institutional delegators delegate to your node. Assuming 1M FLOW for this example. |
+| C | APY | 10% | Subject to change based on total ecosystem stake in each epoch. Remember APY = R / S, where S = Total FLOW Staked / Total FLOW Supply and R = 5% (”reward rate”) |
+| D | Delegation Rate | 8% | Fee taken by the node operator from delegator rewards to cover their operating expenses, currently set at 8% of the rewards received by delegators. Note that the 8% fee is only applied to the staking reward, not to the tokens delegated. |
+| E | Annual Staking Rewards | 50,000 FLOW | Product of A x C; the number shown is annualized but is paid each epoch (week). |
+| F | Annual Delegator Fee | 8,000 FLOW | Product of B x C x D; ; the number shown is annualized but is paid each epoch (week). |
+| G | Annual (Gross) Rewards | 58,000 FLOW | Sum of E and F |
+| H | COGS | 4,190 FLOW | Assumed costs of running a consensus node in FLOW assuming 1US$/FLOW. The actual cost will vary depending on several factors such as self-hosted vs cloud, bare metal vs VM, the type of node, the FLOW exchange rate. |
+| J | Net Annual Rewards | 53,810 FLOW | G less H |
+
+## Note
+
+1. Each year, 5% of the total Flow supply is distributed as rewards to incentivize validators and delegators. While the total rewards for each epoch are fixed, the rewards for individual stakers vary depending on the amount they stake and the total funds delegated to their node.
+2. All Flow node types follow the same economic principles, with the only difference being their minimum staking requirements. For details on the minimum stakes needed for each node type, see [here](https://flow.com/flow-tokenomics/technical-overview).
+
+
+
+=== networks/node-ops/node-operation/node-bootstrap.md ===
+---
+title: Node Bootstrap
+sidebar_label: Node Bootstrapping
+description: How to get started running a node on Flow
+sidebar_position: 8
+---
+
+This guide is for getting a new node staked and running on Flow other than a permissionless Access node. For running a permissionless Access node see [Access node setup](../access-nodes/access-node-setup.md). For sporking documentation for existing node operators, see [Spork Process](./spork.md).
+
+## Timing
+
+New nodes are able to join the network each time a new epoch begins.
+In order to join the network at epoch N+1, the node must be registered with sufficient stake and
+authorized by the service account prior to the end of epoch N's Staking Auction Phase.
+Confirmation of a new node's inclusion in epoch N+1 is included in the [`EpochSetup` event](../../staking/05-epoch-scripts-events.md#flowepochepochsetup).
+
+Nodes registered for epoch N+1 are able to participate in network communication on a limited basis starting in the `Epoch Setup Phase` of epoch N.
+
+
+
+Once registered and confirmed to join the network at epoch N+1, the node must start up **before** epoch N+1 begins.
+* Verification & Access nodes may start up any time during the `Epoch Setup Phase`.
+* Consensus & Collection nodes must start up within the first **1000 views (~30mins)**
+of the `Epoch Setup Phase` to participate in the [Epoch Preparation Protocol](../../staking/04-epoch-preparation.md#phase-1-epoch-setup).
+
+## Step 1 - Run Genesis Bootstrap
+
+:::info
+
+ You will need to run this process for each node that you are operating
+
+:::
+
+### Download the Bootstrapping Kit
+
+:::warning
+
+If you have downloaded the bootstrapping kit previously, ensure you check the hash below still matches. If not, re-download to ensure you are using the most up-to-date version.
+
+:::
+
+```shell
+curl -sL -O storage.googleapis.com/flow-genesis-bootstrap/boot-tools.tar
+tar -xvf boot-tools.tar
+chmod +x ./boot-tools/bootstrap
+chmod +x ./boot-tools/transit
+```
+
+```shell CheckSHA256
+sha256sum ./boot-tools/bootstrapcmd
+460cfcfeb52b40d8b8b0c4641bc4e423bcc90f82068e95f4267803ed32c26d60 ./boot-tools/bootstrap
+
+sha256sum ./boot-tools/transit
+f146bdc82ce0cce73c0fb9de284b2e2639e851120f8b89a1dd9368e8442123b4 ./boot-tools/transit
+```
+
+### Generate Your Node Keys
+
+#### Network Address
+
+:::info
+
+Use a fully qualified domain name for the network address. Please also include the port number in the network address e.g. `example.com:3569`
+
+:::
+
+:::warning
+
+Do not include in `http://` format.
+
+:::
+
+:::info
+
+If you are running multiple nodes, please
+ensure you have different addresses for each node.
+
+:::
+
+:::warning
+
+All your current keys and Flow genesis files should be in the `bootstrap`
+folder created earlier. Please take a back up of the entire folder.
+
+:::
+
+
+```shell
+## Skip this section if this is your first time ##
+# If you joined our network previously, make sure to take a backup of your previously generated keys!
+cp -r /path/to/bootstrap /path/to/bootstrap.bak
+#########################################################
+# Generate Keys
+$ mkdir ./bootstrap
+# YOUR_NODE_ADDRESS: FQDN associated to your instance (do NOT use an IP address, use a hostname)
+# YOUR_NODE_ROLE: The Flow nodes that you wish to run, it should be ONE of the following - [ access, collection, consensus, execution, verification ]
+$ ./boot-tools/bootstrap key --address \"YOUR_NODE_ADDRESS_GOES_HERE:3569\" --role YOUR_NODE_ROLE_GOES_HERE -o ./bootstrap
+
+```
+
+```shell Example
+$./boot-tools/bootstrap key --address "consensus-001.nodes.flow.com:3569" --role consensus -o ./bootstrap
+ DBG will generate networking key
+ INF generated networking key
+ DBG will generate staking key
+ INF generated staking key
+ DBG will generate db encryption key
+ INF generated db encryption key
+ DBG assembling node information address=consensus-001.nodes.flow.com:3569
+ DBG encoded public staking and network keys networkPubKey=7f31ae79017a2a58a5e59af9184f440d08885a16614b2c4e361019fa72a9a1a42bf85b4e3f9674782f12ca06afd9782e9ccf19496baed069139385b82f8f40f6 stakingPubKey=829d086b292d84de8e7938fd2fafa8f51a6e025f429291835c20e59d9e25665febf24fa59de12a4df08be7e82c5413180cc7b1c73e01f26e05344506aaca4fa9cc009dc1c33f8ba3d7c7509e86d3d3e7341b43b9bf80bb9fba56ae0b3135dd72
+ INF wrote file bootstrap/public-root-information/node-id
+ INF wrote file bootstrap/private-root-information/private-node-info_ab6e0b15837de7e5261777cb65665b318cf3f94492dde27c1ea13830e989bbf9/node-info.priv.json
+ INF wrote file bootstrap/private-root-information/private-node-info_5e44ad5598bb0acb44784f629e84000ffea34d5552427247d9008ccf147fb87f/secretsdb-key
+ INF wrote file bootstrap/public-root-information/node-info.pub.ab6e0b15837de7e5261777cb65665b318cf3f94492dde27c1ea13830e989bbf9.json
+ DBG will generate machine account key
+ INF generated machine account key
+ DBG assembling machine account information address=consensus-001.nodes.flow.com:3569
+ INF encoded machine account public key for entry to Flow Port machineAccountPubKey=f847b8406e8969b869014cd1684770a8db02d01621dd1846cdf42fc2bca3444d2d55fe7abf740c548639cc8451bcae0cd6a489e6ff59bb6b38c2cfb83e095e81035e507b02038203e8
+ INF wrote file bootstrap/private-root-information/private-node-info_ab6e0b15837de7e5261777cb65665b318cf3f94492dde27c1ea13830e989bbf9/node-machine-account-key.priv.json
+
+$tree ./bootstrap/
+./bootstrap
+├── private-root-information
+│ └── private-node-info_ab6e0b15837de7e5261777cb65665b318cf3f94492dde27c1ea13830e989bbf9
+│ ├── node-info.priv.json
+│ ├── node-machine-account-key.priv.json
+│ └── secretsdb-key
+└── public-root-information
+ ├── node-id
+ └── node-info.pub.ab6e0b15837de7e5261777cb65665b318cf3f94492dde27c1ea13830e989bbf9.json
+
+3 directories, 4 files
+```
+
+:::info
+
+For `consensus` and `collection` node types an additional key will be created for the Machine Account.
+For all other node types this will not be needed.
+
+:::
+
+#### Machine Account Creation
+
+If you are running a collection and consensus node, you will have an additional private key file (`node-machine-account-key.priv.json`)
+which contains the private key for your node's machine account. You can learn more about machine
+accounts [here](../../staking/11-machine-account.md).
+
+In Step 2 of this guide, when you submit a transaction to stake your node, you will need to provide the
+machine account public key, which can be found in the output of the previous `bootstrap key` command.
+
+```shell MachineAccountPublicKey
+$./boot-tools/bootstrap key --address YOUR_NODE_ADDRESS_GOES_HERE --role YOUR_NODE_ROLE_GOES_HERE -o ./bootstrap
+...
+ DBG encoded public machine account key machineAccountPubKey=1b9c00e6f0930792c5738d3397169f8a592416f334cf11e84e6327b98691f2b72158b40886a4c3663696f96cd15bfb5a08730e529f62a00c78e2405013a6016d
+ INF wrote file bootstrap/private-root-information/private-node-info_ab6e0b15837de7e5261777cb65665b318cf3f94492dde27c1ea13830e989bbf9/node-machine-account-key.priv.json
+```
+
+:::warning
+
+Copy the machine account public key somewhere safe. You will need it in a later step.
+
+:::
+
+## Step 2 - Stake Your Node
+
+Stake your node via [Flow Port](https://port.onflow.org/)
+
+The `node details` (`Node ID`, `Network Address`, `Networking Key` and `Staking Key`) that need to be submitted when staking the node on Flow Port, can be found in the file: `./bootstrap/public-root-information/node-info.pub..json`.
+
+```shell Example
+$cat ./bootstrap/public-root-information/node-info.pub.39fa54984b8eaa463e129919464f61c8cec3a4389478df79c44eb9bfbf30799a.json
+{
+ "Role": "consensus",
+ "Address": "consensus-001.nodes.flow.com:3569",
+ "NodeID": "39fa54984b8eaa463e129919464f61c8cec3a4389478df79c44eb9bfbf30799a",
+ "Weight": 0,
+ "NetworkPubKey": "d92e3d5880abe233cf9fe9104db34bbb31251468a541454722b3870c04156a1b0504aef443bcaad124b997384b8fe7052847ce1e6189af1392d865e6be69835b",
+ "StakingPubKey": "917826e018f056a00b778a58ae83054906957ffd4b6f1b7da083551f7a9f35e02b76ace50424ed7d2c9fc69207a59f0f08a031048f5641db94e77d0648b24d150dedd54bab7cd44b4aa60cfd54be418647b0b3965f8ae54c0bcb48ae9d705162"
+}
+```
+
+If you are running a collection or consensus node, you will need to provide an additional field `Machine Account Public Key`.
+This value is found in the output of the `bootstrap key` command from Step 1.
+
+Staking a collection or consensus node will also create a machine account for the node. The machine account will be mentioned in the output of the staking transaction displayed by Flow Port. Please save the machine account for the next step.
+
+:::info
+
+Please let us know your node id via discord or email.
+
+:::
+
+### Finalize Machine Account Setup
+
+:::warning
+
+If you are not running a collection or consensus node, you can skip this step.
+
+:::
+
+You will now need to use the `bootstrap` utility to run `machine-account` with the created address to finalize the set up of your Machine account.
+
+```shell
+$ ./boot-tools/bootstrap machine-account --address YOUR_MACHINE_ACCOUNT_ADDRESS_GOES_HERE -o ./bootstrap
+```
+
+```shell Example
+$ ./boot-tools/bootstrap machine-account --address 0x1de23de44985c7e7 -o ./bootstrap
+ INF read machine account private key json
+ DBG encoded public machine account key machineAccountPubKey=2743786d1ff1bf7d7026d693a774210eaa54728343859baab62e2df7f71a370651f4c7fd239d07af170e484eedd4f3c2df47103f6c39baf2eb2a50f67bbcba6a
+ INF wrote file bootstrap/private-root-information/private-node-info_6f6e98c983dbd9aa69320452949b81abeab2ac591a247f55f19f4dbf0b477d26/node-machine-account-info.priv.json
+
+$tree ./bootstrap/
+./bootstrap
+├── private-root-information
+│ └── private-node-info_d60bd55ee616c5c297cae1d5cfb7f65e7e04014d9c4abe595af2fd83f3cfe160
+│ ├── node-info.priv.json
+│ ├── node-machine-account-info.priv.json
+│ ├── node-machine-account-key.priv.json
+│ └── secretsdb-key
+└── public-root-information
+ ├── node-id
+ └── node-info.pub.d60bd55ee616c5c297cae1d5cfb7f65e7e04014d9c4abe595af2fd83f3cfe160.json
+
+3 directories, 5 files
+```
+
+After running this step, you should see the `node-machine-account-info.priv.json` file in your `bootstrap` directory as shown above.
+
+### Verify Machine Account Setup
+
+After finalizing your machine account setup, you should verify its correctness with the `check-machine-account` command:
+
+```shell CheckMachineAccount
+$ ./boot-tools/bootstrap check-machine-account --access-address access.mainnet.nodes.onflow.org:9000 -o ./bootstrap
+ DBG read machine account info from disk hash_algo=SHA3_256 key_index=0 machine_account_address=0x284463aa6e25877c machine_account_pub_key=f847b84051bad4512101640772bf5e05e8a49868d92eaf9ebed41030881d95485769afd28653c5c53216cdcda4554384bb3ff6396a2ac04842422d55f0562496ad8d952802038203e8 signing_algo=ECDSA_P256
+ DBG checking machine account configuration... machine_account_address=0x284463aa6e25877c role=consensus
+ DBG machine account balance: 0.10000000
+ INF 🤖 machine account is configured correctly
+```
+
+This command will detect and provide information about common misconfigurations, or confirm that the machine account is configured correctly.
+
+### Push transit keys (consensus node only)
+
+If you are running a consensus node, run the following command to generate the transit keys.
+
+```shell transit
+$ ./boot-tools/transit prepare -b ./bootstrap -r consensus
+ INF running prepare
+ INF generating key pair
+ INF completed preparation role=consensus
+```
+
+This will generate the public and private transit keys under the bootstrap folder.
+The transit keys are used to transfer the DKG keys after a network upgrade.
+
+Please share the **public** transit key with the Flow Foundation via [discord](https://discord.gg/flow) or [email](mailto::governance@flow.com).
+
+## Step 3 - Start Your Flow Node
+
+Ensure you have configured your node using the [Node Setup guide](./node-setup.md).
+
+### Confirming authorization
+
+You can confirm your node's successful registration and authorization by executing a Cadence script to query the [Staking Contract](../../../build/core-contracts/06-staking-contract-reference.md#contract).
+At the end of the `Staking Auction Phase`, the members of the Proposed Identity Table are confirmed as authorized participants in the next epoch.
+Therefore, if your node ID appears in the Proposed Identity Table during the `Staking Auction Phase`, your node will be a participant in the next epoch.
+
+You can read the current Proposed Identity Table using the [getProposedTable script](https://github.com/onflow/flow-core-contracts/blob/master/transactions/idTableStaking/scripts/get_proposed_table.cdc).
+
+You can read the current epoch phase using the [getEpochPhase script](https://github.com/onflow/flow-core-contracts/blob/master/transactions/epoch/scripts/get_epoch_phase.cdc). (A return value of `0` indicates the `Staking Auction Phase`.)
+
+### Trusted Root Snapshot
+
+Once your node has been registered and authorized by the service account, it will be able to participate in the next epoch.
+
+
+
+A new node must bootstrap with a trusted root snapshot of the protocol state, where the node is a confirmed participant.
+Since new nodes are confirmed at the end of the `Staking Auction Phase`, this means that, if the node is registered to join at epoch `N+1`, it must use a root snapshot from within the `Epoch Setup Phase` of epoch `N`.
+
+### Dynamic Startup
+
+Flow provides a mechanism called Dynamic Startup to simplify the process of obtaining the root snapshot.
+When using Dynamic Startup, the node can be started **at any time during the `Staking Auction Phase`**.
+The node will wait for the `Epoch Setup Phase` to begin, retrieve a valid root snapshot from a trusted Access Node, then bootstrap its state and join the network.
+This is the recommended way to start your node for the first time.
+
+1. Remove any `root-protocol-state-snapshot.json` file from your `bootstrap` folder. (If this file is present the node will attempt to bootstrap with it rather than Dynamic Startup.)
+2. Select a trusted Access Node to provide the root snapshot. You will need this node's **secure GRPC server address** and **Networking Public Key**.
+3. Configure Dynamic Startup by adding flags:
+```shell ExampleDynamicStartupFlags
+ ... \
+ --dynamic-startup-access-address=secure.mainnet.nodes.onflow.org:9001 \
+ --dynamic-startup-access-publickey=28a0d9edd0de3f15866dfe4aea1560c4504fe313fc6ca3f63a63e4f98d0e295144692a58ebe7f7894349198613f65b2d960abf99ec2625e247b1c78ba5bf2eae
+```
+4. Start your node (see [guide](./node-setup#start-the-node))
+
+:::info
+
+Once the node has bootstrapped, these flags will be ignored and may be removed.
+
+:::
+
+### Manually Provisioned Root Snapshot
+
+You can also provision the root snapshot file manually, then start the node without configuring Dynamic Startup.
+See [here](./protocol-state-bootstrap.md) for the available options to provision a Root Snapshot.
+
+:::warning
+
+The snapshot must be within the `Epoch Setup Phase`.
+
+:::
+
+:::warning
+
+Since Collection and Consensus Nodes must start up in the first ~30mins of the `Epoch Setup Phase` (see [Timing](./node-bootstrap.md#timing)),
+the snapshot must be provisioned within this time window.
+
+:::
+
+Once a valid root snapshot file is downloaded to the node's bootstrap folder, it can be started (see [guide](./node-setup.md#start-the-node))
+
+
+=== networks/node-ops/node-operation/monitoring-nodes.md ===
+---
+title: Monitoring Node Health
+sidebar_label: Node Monitoring
+sidebar_position: 7
+---
+
+A Flow node generates logs and publishes metrics as it runs. These logs and metrics can be used to gain insights into the health of the node.
+
+## Logs
+
+Logs are emitted to `stdout` as JSON formed strings. Where these logs are available on your system depends on how you launch your containers. On `systemd` systems for example, the logs will be sent to the system journal daemon `journald`. Other systems may log to `/var/log`.
+
+## Metrics
+
+Flow nodes produce health metrics in the form of [Prometheus](https://prometheus.io) metrics, exposed from the node software on `/metrics`.
+
+If you wish to make use of these metrics, you'll need to set up a Prometheus server to scrape your Nodes. Alternatively, you can deploy the Prometheus Server on top of your current Flow node to see the metrics without creating an additional server.
+
+> The flow-go application doesn't expose any metrics from the underlying host such as CPU, network, or disk usages. It is recommended you collect these metrics in addition to the ones provided by flow using a tool like node exporter (https://github.com/prometheus/node_exporter)
+
+1. Copy the following Prometheus configuration into your current flow node
+
+ ```yaml
+ global:
+ scrape_interval: 15s # By default, scrape targets every 15 seconds.
+
+ scrape_configs:
+ # The job name is added as a label `job=` to any timeseries scraped from this config.
+ - job_name: 'prometheus'
+
+ # Override the global default and scrape targets from this job every 5 seconds.
+ scrape_interval: 5s
+
+ static_configs:
+ - targets: ['localhost:8080']
+ ```
+
+2. Start Prometheus server
+ ```shell
+ docker run \
+ --network=host \
+ -p 9090:9090 \
+ -v /path/to/prometheus.yml:/etc/prometheus/prometheus.yml \
+ prom/prometheus"
+ ```
+3. (optional) Port forward to the node if you are not able to access port 9090 directly via the browser
+ `ssh -L 9090:127.0.0.1:9090 YOUR_NODE`
+
+4. Open your browser and go to the URL `http://localhost:9090/graph` to load the Prometheus Dashboard
+
+### Key Metric Overview
+
+The following are some important metrics produced by the node.
+
+| Metric Name | Description |
+| ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
+| go\_\* | Go runtime metrics |
+| consensus_compliance_finalized_height | Latest height finalized by this node; should increase at a constant rate. |
+| consensus_compliance_sealed_height | Latest height sealed by this node; should increase at a constant rate. |
+| consensus_hotstuff_cur_view | Current view of the HotStuff consensus algorith; Consensus/Collection only; should increase at a constant rate. |
+| consensus_hotstuff_timeout_seconds | How long it takes to timeout failed rounds; Consensus/Collection only; values consistently larger than 5s are abnormal. |
+
+### Machine Account
+
+Collection and consensus nodes use a machine account that must be kept funded. See [here](../../staking/11-machine-account.md) for details.
+
+Nodes check their machine account's configuration and funding and produce metrics.
+
+| Metric Name | Description |
+| ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
+| machine_account_balance | The current balance (FLOW) |
+| machine_account_recommended_min_balance | The recommended minimum balance (FLOW) |
+| machine_account_is_misconfigured | 0 if the node is configured correctly; 1 if the node is misconfigured |
+
+To be notified when your node's machine account needs to be refilled or has a configuration error, you can set up alerts.
+
+When the machine account balance needs to be refilled:
+```
+machine_account_balance < machine_account_recommended_min_balance
+```
+
+When the machine account has a configuration error:
+```
+machine_account_is_misconfigured > 0
+```
+
+The metrics include the account address of the machine account (`acct_address` label) for convenience:
+```
+# HELP machine_account_balance the last observed balance of this node's machine account, in units of FLOW
+# TYPE machine_account_balance gauge
+machine_account_balance{acct_address="7b16b57ae0a3c6aa"} 9.99464935
+```
+
+
+
+=== networks/node-ops/node-operation/machine-existing-operator.md ===
+---
+title: Machine Accounts for Existing Node Operators
+sidebar_label: Machine Accounts for Existing Node Operators
+description: Instructions for existing Node Operators to follow to create a machine account for their collection or consensus nodes.
+sidebar_position: 6
+---
+
+The [Flow Epoch Preparation Protocol](../../staking/04-epoch-preparation.md) requires that
+`collection` and `consensus` nodes use an automated [machine account](../../staking/09-qc-dkg.md#machine-accounts)
+to participate in important processes required to start the next epoch. (QC and DKG, respectively)
+
+Starting on Thursday, August 26th 2021, all collector and consensus nodes who register with Flow Port will
+automatically create and initialize this machine account as part of their node registration.
+
+If you have an existing `consensus` or `collection` node that you registered with Flow Port before Thursday August 26th,
+you will need to create this Machine Account manually in order to participate in epochs.
+You will need to create one Machine Account for each `consensus` or `collection` node that you operate.
+
+This guide will walk you through creating a Machine Account and getting it set up.
+
+
+ During this process you will generate a new private key which will have sole control over your machine account.
+ This private key will be stored on the machine you use to run your node, alongside your staking and networking keys.
+ Loss of any of these keys (staking, networking, or machine account) will require you to un-stake your tokens, start a completely new node, and register the new node to continue participating in the Flow network, which takes multiple weeks.
+
+
+## Downloading Bootstrap Utility
+
+
+ If you have downloaded the bootstrapping kit previously, ensure that you do
+ this step again to get the latest copy of the bootstrapping kit since there
+ have been significant changes to it.
+
+
+Follow the instructions [here](./node-bootstrap.md#download-the-bootstrapping-kit)
+to download the latest version of the bootstrapping kit, then return to this page.
+
+## Generate Machine Account key
+
+You will need to generate a Machine account private key using the `bootstrap` utility.
+
+
+
+ Ensure you run the following commands on the machine you use to run your node software.
+ The bootstrap directory passed to the `-o` flag must be the same bootstrap directory used by your node.
+ The default location is `/var/flow/bootstrap`, but double-check your setup before continuing.
+
+
+
+```shell GenerateMachineAccountKey
+$./boot-tools/bootstrap machine-account-key -o ./bootstrap
+ INF generated machine account private key
+ INF encoded machine account public key for entry to Flow Port machineAccountPubKey=f847b84031d9f47b88435e4ea828310529d2c60e806395da50d3dd0dd2f32e2de336fb44eb06488645673850897d7cc017701d7e6272a1ab7f2f125aede46363e973444a02038203e8
+ INF wrote file bootstrap/private-root-information/private-node-info_6f6e98c983dbd9aa69320452949b81abeab2ac591a247f55f19f4dbf0b477d26/node-machine-account-key.priv.json
+
+$tree ./bootstrap/
+./bootstrap
+├── private-root-information
+│ └── private-node-info_ab6e0b15837de7e5261777cb65665b318cf3f94492dde27c1ea13830e989bbf9
+│ ├── node-info.priv.json
+│ └── node-machine-account-key.priv.json
+│ └── secretsdb-key
+└── public-root-information
+ ├── node-id
+ └── node-info.pub.ab6e0b15837de7e5261777cb65665b318cf3f94492dde27c1ea13830e989bbf9.json
+
+3 directories, 4 files
+```
+
+## Create Machine Account
+
+You will now need to copy the Machine account public key displayed in the terminal output and
+head over to [Flow Port](../../../networks/flow-port/staking-guide.md#stake-a-node) to submit a transaction to create a Machine Account.
+For example, from the example above, we would copy `f847...` from this line:
+
+```shell Example
+ INF encoded machine account public key for entry to Flow Port machineAccountPubKey=f847b84031d9f47b88435e4ea828310529d2c60e806395da50d3dd0dd2f32e2de336fb44eb06488645673850897d7cc017701d7e6272a1ab7f2f125aede46363e973444a02038203e8
+```
+
+This process will create your machine account for you and show you your machine account's address, which you will need to save for the next step.
+
+## Finalize Machine Account setup
+
+You will now need to use the `bootstrap` utility to run `machine-account` with the created address to finalize the set up of your Machine account.
+
+```shell
+$ ./boot-tools/bootstrap machine-account --address ${YOUR_MACHINE_ACCOUNT_ADDRESS} -o ./bootstrap
+```
+
+```shell Example
+$./boot-tools/bootstrap machine-account --address 0x1de23de44985c7e7 -o ./bootstrap
+ INF read machine account private key json
+ DBG encoded public machine account key machineAccountPubKey=2743786d1ff1bf7d7026d693a774210eaa54728343859baab62e2df7f71a370651f4c7fd239d07af170e484eedd4f3c2df47103f6c39baf2eb2a50f67bbcba6a
+ INF wrote file bootstrap/private-root-information/private-node-info_6f6e98c983dbd9aa69320452949b81abeab2ac591a247f55f19f4dbf0b477d26/node-machine-account-info.priv.json
+
+$tree ./bootstrap/
+./bootstrap
+├── private-root-information
+│ └── private-node-info_d60bd55ee616c5c297cae1d5cfb7f65e7e04014d9c4abe595af2fd83f3cfe160
+│ ├── node-info.priv.json
+│ ├── node-machine-account-info.priv.json
+│ └── node-machine-account-key.priv.json
+│ └── secretsdb-key
+└── public-root-information
+ ├── node-id
+ └── node-info.pub.d60bd55ee616c5c297cae1d5cfb7f65e7e04014d9c4abe595af2fd83f3cfe160.json
+
+3 directories, 5 files
+```
+
+After running this step, you should see the `node-machine-account-info.priv.json` file in your `bootstrap` directory as shown above.
+
+### Verify Machine Account Setup
+
+After finalizing your machine account setup, you should verify its correctness with the `check-machine-account` command:
+
+```shell CheckMachineAccount
+$ ./boot-tools/bootstrap check-machine-account --access-address access.mainnet.nodes.onflow.org:9000 -o ./bootstrap
+ DBG read machine account info from disk hash_algo=SHA3_256 key_index=0 machine_account_address=0x284463aa6e25877c machine_account_pub_key=f847b84051bad4512101640772bf5e05e8a49868d92eaf9ebed41030881d95485769afd28653c5c53216cdcda4554384bb3ff6396a2ac04842422d55f0562496ad8d952802038203e8 signing_algo=ECDSA_P256
+ DBG checking machine account configuration... machine_account_address=0x284463aa6e25877c role=consensus
+ DBG machine account balance: 0.10000000
+ INF 🤖 machine account is configured correctly
+```
+
+This command will detect and provide information about common misconfigurations, or confirm that the machine account is configured correctly.
+
+
+=== networks/node-ops/node-operation/hcu.md ===
+---
+title: Height coordinated upgrade (HCU)
+sidebar_label: Height coordinated upgrade
+---
+
+## Overview
+
+To enables rapid development of the Flow Protocol, the height coordinated upgrade method is used to roll out non-breaking changes such as bug fixes,
+feature implementations and security fixes.
+
+## HCU versus Spork
+
+A [spork](./spork.md) requires a coordinated network upgrade process where node operators upgrade their node software and
+re-initialize with a consolidated representation of the previous spork's state.
+It is used to roll out changes which may be non-backward compatible with respect to the protocol and the execution state.
+Spork entails a network downtime as all nodes in the system are upgraded and brought back online.
+Sporks are only executed once every quarter.
+
+A height coordinated upgrade (HCU) on the other hand allows the execution and the verification nodes to be upgraded without stopping the network.
+There is no network downtime during an HCU but the transaction execution will stop for few minutes while the execution nodes restart.
+Currently, an HCU is only used to update the execution and the verification nodes.
+For other node types, a simple rolling upgrade is used where operators are asked to upgrade their nodes async.
+
+## HCU process
+
+The HCU is executed in two parts.
+
+The first part is executed by the service committee. In this, the version boundary at which the execution nodes and verification nodes should stop is set on chain by submitting the [set_version_boundary](https://github.com/onflow/flow-core-contracts/blob/master/transactions/nodeVersionBeacon/admin/set_version_boundary.cdc) transaction.
+The version boundary includes the block height at which the two node types should stop and the new node software version that the nodes should compare after a restart.
+
+
+The second part is executed by the node operator. In this the node operator, monitors the execution and verification node that they are running. When the nodes reach the height set on chain, they stop if their version is lower then the version specified in the version boundary.
+At this point, the operator should update the node version to the new node software version and start the node again. The node will continue from where it left off.
+
+The block height and the node version will be announced by the Flow team on Discord as well as the [forum page](https://forum.onflow.org/c/mainnet-sporks/36).
+It can also be directly queried from the chain using the following script.
+
+```
+TODO: insert flow cli command here to query the block version details.
+```
+
+
+=== networks/node-ops/node-operation/faq.md ===
+---
+title: Operator FAQ
+sidebar_position: 1
+---
+
+# Operator FAQ
+
+### Can anybody run a node? What is the approval process?
+
+Anyone can run an [observer node](../light-nodes/observer-node.md).
+
+Anyone can run an Access Node after registering and staking. See [Access Node Setup](../access-nodes/access-node-setup.md) for detailed instructions.
+
+For the other node roles, individuals can go through an application process that involves asking about their background and experience contributing to decentralized projects. To pursue an application, please visit [the Flow website here to apply](https://www.onflow.org/node-validators).
+
+Pending approval, new node operators will be onboarded and invited to join a webinar to meet the team and share more about how they’ll grow the community. Node Operators are invited to join and participate in Flow's Node Validator Discord channel for setup questions and network announcements.
+
+In the long-term, anyone can run a node validator on Flow.
+
+### How do I generate keys?
+
+Please follow the instructions provided here: [Generate Your Node Keys](./node-bootstrap.md#generate-your-node-keys)
+
+### How do I check on the status of my node?
+
+Please follow the instructions provided here: [Monitoring nodes](./monitoring-nodes.md)
+
+### Can I bootstrap and run a node at any time?
+
+Flow allows nodes to join/leave the network each time a new epoch begins (roughly once per week).
+See [Staking & Epochs](../../staking/index.md#epochs) for general information and [Node Setup](./node-bootstrap.md#timing) for a guide to running a new node.
+
+### Would it hurt the network to have a node that constantly spins up and down?
+
+All staked nodes except access nodes, have to be online at all time. A staked node, other than an access node, which is not online can cause severe degradation of network performance and will be subjected to slashing of rewards.
+A way to prevent this is to check your equipment meets Flow's [recommended requirements](./node-provisioning.md#hardware-requirements), periodically checking for updates and announcements in Discord but also using a node monitoring system for when your node does go offline.
+
+### Does Flow has a regular schedule for Sporks?
+
+Yes, see [Upcoming Sporks](./upcoming-sporks.md) for the latest schedule. Currently, Flow has a Mainnet Spork and a Testnet Spork roughly every two months.
+
+### How do I update the Node Software?
+
+One of the reasons for a [spork](./spork.md) is to make sure all nodes update to the latest software version. Hence, you should have the latest software update as long as you are participating in each spork.
+However, if we do release any software update in between a Spork (e.g. an emergency patch) we will announce it on Discord.
+
+### Is there any way to know if a node is currently online?
+
+To verify if a node is online, please [setup metrics](./faq.md#how-do-i-check-on-the-status-of-my-node) for the node.
+
+### Can I migrate a node to a new machine?
+
+Yes, as long as you retain the `boostrap` information which includes the node staking key, networking key, IP address and port from the old node to the new.
+More on this [here](./node-migration.md)
+
+### Where can I find how many nodes are currently running Flow?
+
+If you are running a node, then you most definitely have this information on your node in the file `/public-root-information/node-infos.pub.json`. If you are not running a node, you can find this information by using a Cadence script to query the [Staking Smart Contract](../../../build/core-contracts/06-staking-contract-reference.md) (or check [Flowdiver](https://flowdiver.io/staking/overview))
+
+### Why do I need to update my node's ulimit?
+
+Flow nodes create network connections to other nodes on the network to participate in the protocol. The node's operating system represents
+these connections as file descriptors, and uses soft and hard limits to control the number of open files. The node software uses these limits
+to manage how many connections it will open and accept from other nodes. If the limit is too low, the node will not be able to communicate
+with its peers, preventing it from functioning properly.
+
+
+=== networks/node-ops/node-operation/db-encryption-existing-operator.md ===
+---
+title: Database Encryption for Existing Node Operators
+sidebar_label: Database Encryption for Existing Node Operators
+description: Instructions for existing Node Operators to follow to create a machine account for their collection or consensus nodes.
+sidebar_position: 4
+---
+
+In Mainnet14, the DKG (distributed key generation) is turned on, requiring storage of
+dynamically generated confidential data (random beacon keys). These are stored in a
+separate database which is new with the Mainnet14 release.
+
+All node operators joining after Mainnet14 will generate encryption keys for this database
+through the node bootstrapping and staking process. We strongly recommend all node operators
+(especially consensus node operators) generate an encryption key for this database. This
+guide demonstrates how to enable encryption for this database for existing operators.
+
+## Downloading Bootstrap Utility
+
+
+ If you have downloaded the bootstrapping kit previously, ensure that you do
+ this step again to get the latest copy of the bootstrapping kit since there
+ have been significant changes to it.
+
+
+Follow the instructions [here](./node-bootstrap.md#download-the-bootstrapping-kit)
+to download the latest version of the bootstrapping kit, then return to this page.
+
+## Generate Database Encryption Key
+
+You will need to generate an encryption key for the database using the `bootstrap` utility.
+
+
+
+ Ensure you run the following commands on the machine you use to run your node software.
+ The bootstrap directory passed to the `-o` flag must be the same bootstrap directory used by your node.
+ The default location is `/var/flow/bootstrap`, but double-check your setup before continuing.
+
+
+
+```shell GenerateEncryptionKey
+$./boot-tools/bootstrap db-encryption-key -o ./bootstrap
+ INF generated db encryption key
+ INF wrote file bootstrap/private-root-information/private-node-info_ab6e0b15837de7e5261777cb65665b318cf3f94492dde27c1ea13830e989bbf9secretsdb-key
+
+$tree ./bootstrap/
+./bootstrap
+├── private-root-information
+│ └── private-node-info_ab6e0b15837de7e5261777cb65665b318cf3f94492dde27c1ea13830e989bbf9
+│ ├── node-info.priv.json
+│ └── secretsdb-key
+└── public-root-information
+ ├── node-id
+ └── node-info.pub.ab6e0b15837de7e5261777cb65665b318cf3f94492dde27c1ea13830e989bbf9.json
+
+3 directories, 4 files
+```
+
+
+=== networks/node-ops/node-operation/byzantine-node-attack-response.md ===
+---
+title: Byzantine Node Attack Response
+sidebar_label: Byzantine Attack Response
+description: How to respond to a byzantine node attack on the network
+sidebar_position: 3
+---
+
+Flow, like most blockchains, forms an open decentralized peer-to-peer network between all of the nodes
+on the network. Due to its decentralized nature, there is a potential for nodes to behave maliciously
+(byzantine) and intentionally try to harm the network. There are a variety of protections within the
+node software to deal with invalid messages - message signatures, sender authorization, payload
+validation, etc. These protections guard the network against many types of attacks. However, there
+could still be a byzantine node that spams other nodes in the network with invalid messages at volumes
+that are intended to impact node performance. While this will not compromise the security of the
+network it could impact network liveness.
+
+This guide explains how to detect such a node and what actions you should take as a node operator
+to deal with such byzantine nodes.
+
+Responding to an attack from a byzantine node requires the following:
+
+1. Immediate action to block network traffic originating from the byzantine node to your node.
+2. Raising a governance FLIP to remove the node from the network as described in this [FLIP](https://github.com/onflow/flips/blob/main/governance/20230105-identify-errant-node.md).
+3. A service account transaction to set the node weight to 0.
+
+This guide focuses on the first action.
+
+## Admin Server
+
+Flow nodes have an admin server which exposes a simple REST API for interacting with the node.
+See the [README](https://github.com/onflow/flow-go/blob/master/admin/README.md) for some useful examples.
+It is disabled by default.
+
+### Enable the Admin Server
+
+To enable to admin server,
+
+1. Add the following option to the node's CLI flags.
+```
+--admin-addr=localhost:9002
+```
+
+> Note: The port does not have to be 9002. You can choose any free port.
+
+> ⚠️ Do NOT expose the port outside the machine and always use localhost :port
+
+2. Reboot the node to apply the new setting. You can then verify it’s working by logging into
+the machine via ssh and running,
+
+```
+curl localhost:9002
+```
+
+This should return a json response message as below.
+```
+{"code":5,"message":"Not Found","details":[]}
+```
+
+If you instead get a connection rejected message then it’s not configured correctly.
+
+## Detecting a Byzantine Node
+
+There are 2 general categories of byzantine attacks:
+1. Safety attacks - are attacks where a node attempts to corrupt or modify the state of the
+blockchain outside of normal protocol rules.
+2. Liveness attacks - sometimes called spamming attacks, are when a node attempts to disrupt the
+network by abusing their access to waste network and node resources. This generally results in
+degraded performance.
+
+Flow nodes are protected against safety attacks, but liveness attacks are extremely difficult to
+completely prevent. To close the gap, we rely on coordination between node operators to detect
+and block abusive nodes.
+
+### Metrics
+
+Flow nodes generate a variety of metrics that can be used to measure the node's performance and
+identify abnormal behavior. Most metrics are only useful in the context of "normal" operation,
+so it is a good idea to regularly review them to build an understanding of what is "normal".
+
+Metrics to watch:
+* CPU, memory, network connections, network I/O, file descriptors
+* `network_authorization_*` - counts the number of unauthorized/invalid messages received
+* `network_queue_message_queue_size` - measures the number of incoming messages waiting to be processed
+* `network_engine_messages_received_total` - measures the number of messages received from the network
+
+There are many other metrics, but these are a good starting point. If you notice any anomalous trends,
+review the logs for additional context.
+
+### Logs
+
+Log events related to suspicious activity are logged with the label `"suspicious":true`. This is
+helpful to identify the most relevant logs, but there are legitimate cases when these logs are
+emitted, so they cannot be used as a definitive indicator of malicious activity. Two examples of
+expected log messages are:
+* `rejected inbound connection` - You may see this error if an operator unstaked their node between
+sporks, but never shut it down. The node will continue to operate as usual, but peers will not have
+it in their identity table and will (correctly) reject incoming connections.
+* `middleware does not have subscription for the channel ID indicated in the unicast message received` -
+This is commonly logged during node startup when receiving messages before all of the components
+have finished registering their channels with the network layer. It is NOT expected after startup.
+
+The following is an example of a log message indicating an Access node attempted to send a message it
+is not authorized to send:
+```
+{
+ "level": "error",
+ "node_role": "collection",
+ "node_id": "4a6f7264616e20536368616c6d00a875801849f2b5bea9e9d2c9603f00e5d533",
+ "module": "network_slashing_consumer",
+ "peer_id": "QmY2kby3xt3ugu2QqJP5w24rP4HSakYgDFpAJy1ifSRkF7",
+ "networking_offense": "unauthorized_sender",
+ "message_type": "messages.BlockProposal",
+ "channel": "sync-committee",
+ "protocol": "publish",
+ "suspicious": true,
+ "role": "access",
+ "sender_id": "f9237c896507b8d654165c36b61c9a3080e6dd042dea562a4a494fbd73133634",
+ "time": "2023-01-24T21:10:32.74684667Z",
+ "message": "potential slashable offense: sender role not authorized to send message on channel"
+}
+```
+
+### Identifying the Source of Malicious Traffic
+
+Most log messages include either the node ID or peer ID. Peer ID is the ID used to identify nodes on
+by the libp2p library. Peer IDs are derived from the node's networking public key, so there is a 1:1
+mapping between node ID and peer ID.
+
+The two simplest ways to match a node ID to a peer ID:
+1. `inbound connection established` and `outbound connection established` log messages contain both
+the node and peer IDs
+2. The following admin command will return the node info for a given peer ID:
+```
+curl localhost:9002/admin/run_command \
+ -H 'Content-Type: application/json' \
+ -d '{"commandName": "get-latest-identity", "data": { "peer_id": "QmY2kby3xt3ugu2QqJP5w24rP4HSakYgDFpAJy1ifSRkF7" }}'
+```
+
+If you cannot find any log messages at the current log level, you may need to enable debug logging.
+See the admin server's [README](https://github.com/onflow/flow-go/blob/master/admin/README.md) for
+an example.
+
+## Reporting the Byzantine Node
+
+Report the suspicious node on Discord in the `#flow-validators-alerts` channel along with all the
+evidence you have collected (log messages, other networking related metrics, etc).
+This will alert other node operators who can review their nodes to corroborate the report. Using
+evidence from multiple operators, a consensus can be reached about the suspicious node, and
+appropriate action can be taken.
+
+## Blocking a Byzantine Node
+
+Once a consensus is reached about the suspicious node on Discord among the node operators, the
+suspicious node can be blocked using the admin command.
+
+```
+curl localhost: 9002/admin/run_command \
+ -H 'Content-Type: application/json' \
+ -d '{"commandName": "set-config","data": {"network-id-provider-blocklist": [""]}}
+```
+
+After blocking the node, all traffic coming from the node will be rejected and you should only see
+logs about reject messages and connections for that node ID.
+
+## Unblocking a Node
+
+If you need to unblock a node, you can use the same command to remove the node ID from the blocklist.
+Simply run it again with an empty list to remove all blocked nodes, or an existing list with the
+specific node ID you want to unblock removed.
+
+The following command returns a list of the currently blocked nodes.
+```
+curl localhost: 9002/admin/run_command \
+ -H 'Content-Type: application/json' \
+ -d '{"commandName": "get-config", "data": "network-id-provider-blocklist"}
+```
+
+After unblocking the node, connections and traffic coming from the node should resume.
+
+
+=== networks/node-ops/node-operation/guides/starting-nodes.md ===
+---
+title: Starting Your Nodes
+---
+
+Prior to starting up your nodes make sure you have the following items completed:
+
+1. Bootstrap process completed with the bootstrap directory handy (default: `/var/flow/bootstrap`)
+2. Flow `data` directory created (default: `/var/flow/data`)
+3. [node config](../node-bootstrap.md) ready
+4. Firewall exposes TCP/3569, and if you are running `access` node also the GRPC port (default: TCP/9000)
+
+For more details head back to [Setting up your node](../node-setup.md#prepare-your-node-to-start)
+
+When you have all the above completed, you can start your Flow node via `systemd` or `docker`.
+
+## systemd
+
+Ensure that you downloaded the systemd unit file. If you haven't, follow the [Set your node to start](../node-setup.md#prepare-your-node-to-start) guide to get your unit file and enabled.
+
+Once you have your Flow service enabled you can now start your service: `systemctl start flow`
+
+## Docker
+
+If you don't have have systemd on your system, or prefer not to use systemd, you can run the following `docker` commands for your respective Flow role to start your node!
+
+### Access
+
+```
+docker run --rm \
+ -v /path/to/bootstrap:/bootstrap:ro \
+ -v /path/to/data:/data:rw \
+ --name flow-go \
+ --network host \
+ gcr.io/flow-container-registry/access:v0.0.6-alpha \
+ --nodeid=${FLOW_GO_NODE_ID} \
+ --bootstrapdir=/bootstrap \
+ --datadir=/data/protocol \
+ --rpc-addr=0.0.0.0:9000 \
+ --ingress-addr=${FLOW_NETWORK_COLLECTION_NODE} \
+ --script-addr=${FLOW_NETWORK_EXECUTION_NODE} \
+ --bind 0.0.0.0:3569 \
+ --loglevel=error
+```
+
+### Collection
+
+```
+docker run --rm \
+ -v /path/to/bootstrap:/bootstrap:ro \
+ -v /path/to/data:/data:rw \
+ --name flow-go \
+ --network host \
+ gcr.io/flow-container-registry/collection:v0.0.6-alpha \
+ --nodeid=${FLOW_GO_NODE_ID} \
+ --bootstrapdir=/bootstrap \
+ --datadir=/data/protocol \
+ --rpc-addr=0.0.0.0:9000 \
+ --nclusters=${FLOW_NETWORK_COLLECTION_CLUSTER_COUNT} \
+ --bind 0.0.0.0:3569 \
+ --loglevel=error
+```
+
+### Consensus
+
+```
+docker run --rm \
+ -v /path/to/bootstrap:/bootstrap:ro \
+ -v /path/to/data:/data:rw \
+ --name flow-go \
+ --network host \
+ gcr.io/flow-container-registry/consensus:v0.0.6-alpha \
+ --nodeid=${FLOW_GO_NODE_ID} \
+ --bootstrapdir=/bootstrap \
+ --datadir=/data/protocol \
+ --nclusters=${FLOW_NETWORK_COLLECTION_CLUSTER_COUNT} \
+ --bind 0.0.0.0:3569 \
+ --loglevel=error
+```
+
+### Execution
+
+```
+docker run --rm \
+ -v /path/to/bootstrap:/bootstrap:ro \
+ -v /path/to/data:/data:rw \
+ --name flow-go \
+ --network host \
+ gcr.io/flow-container-registry/execution:v0.0.6-alpha \
+ --nodeid=${FLOW_GO_NODE_ID} \
+ --bootstrapdir=/bootstrap \
+ --datadir=/data/protocol \
+ --ingress-addr=0.0.0.0:9000 \
+ --nclusters=${FLOW_NETWORK_COLLECTION_CLUSTER_COUNT} \
+ --bind 0.0.0.0:3569 \
+ --loglevel=error
+```
+
+### Verification
+
+```
+docker run --rm \
+ -v /path/to/bootstrap:/bootstrap:ro \
+ -v /path/to/data:/data:rw \
+ --name flow-go \
+ --network host \
+ gcr.io/flow-container-registry/verification:v0.0.6-alpha \
+ --nodeid=${FLOW_GO_NODE_ID} \
+ --bootstrapdir=/bootstrap \
+ --datadir=/data/protocol \
+ --nclusters=${FLOW_NETWORK_COLLECTION_CLUSTER_COUNT} \
+ --bind 0.0.0.0:3569 \
+ --loglevel=error
+```
+
+### Additional Flags
+#### Networking Layer
+All networking layer settings are initialized to default values from the [config/default-config.yml](https://github.com/onflow/flow-go/blob/master/config/default-config.yml) file when the Flow node starts up. Each attribute in this YAML file matches a flag name, allowing you to override the default setting by specifying the corresponding flag in the `docker run` command. For instance, to change the `networking-connection-pruning` setting, use its matching flag name (`networking-connection-pruning`) and desired value in the `docker run` command.
+
+
+=== networks/node-ops/node-operation/guides/spork-practice.md ===
+---
+title: Spork Practice
+---
+
+## Sporking
+
+The actual process of Sporking will mostly be covered by the Node Operators Quick Guide, and will not be covered here.
+
+[Spork](../spork.md)
+
+Instead, we'll aim to give some instructions for those that want to Practice the process themselves, before joining the Mainnet Spork.
+
+This guide assumes you have access to the Flow-Go repo, which you'll need to build up-to-date containers and run code snippets.
+
+[](https://github.com/onflow/flow-go)
+
+## Local Testnet
+
+One way to get a good feel of the network without too much interaction with infrastructure is to play with the local testnet, which we've named the Flow Local Instrumented Test Environment (FLITE).
+
+[https://github.com/onflow/flow-go/blob/master/integration/localnet/README.md](https://github.com/onflow/flow-go/blob/master/integration/localnet/README.md)
+
+FLITE will allow you to start a full flow network locally, which means starting all 5 roles required for a functioning network. Instructions for initializing and starting the local network are provided in the README above.
+
+When Starting FLITE, it will build all the docker images required for the network. This can also be done manually ahead of time, using `make docker-build-flow` from the root directory of `flow-go`
+
+## Remote Testnet
+
+If you would like more control over the nodes, beyond what docker compose can provide, or you wish to deploy the docker images to separate VMs, to more closely imitate Mainnet, you will have to manually run bootstrapping for a specific configuration of nodes that you would like to test.
+
+[](https://github.com/onflow/flow-go/blob/master/cmd/bootstrap/README.md)
+
+Example files are available in the `cmd/bootstrap/example_files` folder.
+
+Where the `node-config.json` will usually store all flow's nodes, whereas partner node info usually goes into a separate folder. The last file, which will need to be manually populated, is the partner stakes file, which takes the IDs of all the partner nodes and associates a stake. For now, this can be arbitrary.
+
+Once you have all the information, you can make use of the `finalize` command:
+
+[](https://github.com/onflow/flow-go/tree/master/cmd/bootstrap#example-1)
+
+And generate the bootstrapping folder required to start up your nodes.
+
+Once you have the bootstrapping folder, you'll be able to start up all the nodes that were included in the bootstrapping process.
+
+[Node Setup Docker](../node-setup.md#docker)
+
+The startup command will look very similar to what is provided in the quick guide. One such example, assuming we named our bootstrap folder `bootstrap`:
+
+```shell
+docker run --rm \
+ -v /path/to/bootstrap:/bootstrap:ro \
+ -v /path/to/data:/data:rw \
+ --name flow-go \
+ --network host \
+ gcr.io/flow-container-registry/execution:latest \
+ --nodeid=${FLOW_GO_NODE_ID} \
+ --bootstrapdir=/bootstrap \
+ --datadir=/data/protocol \
+ --rpc-addr=0.0.0.0:9000 \
+ --nclusters=${FLOW_NETWORK_COLLECTION_CLUSTER_COUNT} \
+ --bind 0.0.0.0:3569 \
+ --loglevel=error
+```
+
+The two missing pieces of info here are `FLOW_GO_NODE_ID` which will have been generated from the bootstrap process, and will depend on which node you're trying to run, and `FLOW_NETWORK_COLLECTION_CLUSTER_COUNT` which we've been defaulting to `2`
+
+## Practice Testnet
+
+Lastly, if the goal is to practice the entire Sporking procedure, including `transit` of staking and networking keys, and joining a network, we can help spin up a Testnet temporarily for this purpose. This will require quite a bit of coordination, and will basically be the same steps as the Mainnet spork, so please let us know if this is something you'd like to do and we’ll connect to plan accordingly.
+
+
+=== networks/node-ops/node-operation/guides/genesis-bootstrap.md ===
+---
+title: Genesis Bootstrapping
+---
+
+
+
+ All nodes joining the network in May are required to go through this process as part of the Genesis Bootstrapping.
+
+
+## Overview
+
+To kickstart the Flow network and build the first block, all the nodes that will participate in the first round of consensus need to be known and have exchanged some metadata in advance.
+
+This guide will take you through setting up your nodes, running the initial metadata and key generation, exchanging data back and forth with the Flow team, and then finally starting your nodes to join the network.
+
+## Before You Begin
+
+The Flow consensus algorithm depends on there always being a previous block, which means your nodes cannot start until _after_ the Genesis block has been signed. The process of signing that block will be done by the Flow team, and can only be done after every node has completed the first half of the bootstrapping process, which assures that all the identities are included. Since the Flow team needs to wait for metadata from all participants, it will take hours to even days until the Flow network can start.
+
+The bootstrapping process will be in 2 phases, with the Flow team signing the Genesis block between the two.
+
+
+ The bootstrapping process deals with a number of different keys. Make sure you understand their usage and terminology by reviewing the [Node Keys Guide](../node-bootstrap.md#generate-your-node-keys).
+
+
+## Download the Bootstrapping Toolkit
+
+Both phases of the bootstrapping are automated with scripts. Pull a copy onto each of your nodes and extract it.
+
+```shell Pull-boot-tools
+~ $ curl -sL -O storage.googleapis.com/flow-genesis-bootstrap/boot-tools.tar
+~ $ tar -xvf boot-tools.tar
+```
+
+## Generate Your Node Keys
+
+Start the bootstrapping process by generating your Staking Key and Networking Key. Use your Node Address that you generated in [Setting Up a Node](../node-setup.md) in the `--address` flag, and the node role.
+
+Your Node Address must be a publicly routable IPv4 address or valid DNS name that points to your node. This is how other nodes in the network will communicate with you.
+
+```shell Generate-bootstrap-keys"
+~ $ mkdir ./bootstrap
+~ $ ./boot-tools/bootstrap key --address \"${YOUR_NODE_ADDRESS}:3569\" --role ${YOUR_NODE_ROLE} -o ./bootstrap
+```
+
+
+ By default, the bootstrap script uses the kernel entropy source, either via a `getrandom` syscall or `/dev/urandom`. If you have a more secure source of entropy, like a hardware device, you can specify `--staking-seed` and `--networking-seed`, to provide your own seeds.
+
+ Run the `bootstrap` command with no flags to print usage information."
+
+
+
+ The key pairs generated in the bootstrapping process are extremely sensitive and must be managed securely. This guide does not deal with storing the keys in a secure backup or controlling access, as the right approach to this will vary from user to user, but it is something you must consider.
+
+ Private keys are suffixed with `.priv.json`, their public counterparts are not sensitive and can be shared freely.
+
+
+This command generates two keys, a Staking Key and a Network Key, and stores them both in a `.node-info` file. Both these keys are needed during runtime and must be present as a file to start your flow node.
+
+For more details around all the keys that are needed to run nodes and their usage, see the [Node Keys](../node-bootstrap.md#generate-your-node-keys) overview.
+
+The bootstrapping process will create a file structure similar to the following
+
+```text bootstrap-directory
+~
+└──bootstrap
+ ├──{id}.node-info.priv.json
+ └──{id}.node-info.pub.json",
+```
+
+## Upload Public Keys
+
+To mint the Genesis Block, the Flow team will need the public Staking and Network keys from all your nodes.
+
+**If you have previously joined our networks, and you are generating your keys again. Ensure that you take a backup of your keys before generating it again**
+
+To facilitate this, the boot-tools directory comes with a script `push-keys` that will bundle your `*.pub.json` files and send it to the flow team. You can inspect this script to make sure no private key material is being bundled or uploaded. The data not encrypted before being sent as the public keys involved are not sensitive.
+
+In phase 2 of the bootstrapping process, the Flow team will need to securely issue each node a Random Beacon key. This key is again sensitive and unique to your node. To enable this, the `push-keys` script also generates another key pair called the Transit Key. The public key of this pair will be uploaded along with the Staking and Network keys, and your Random Beacon key will be encrypted with it before being sent to you. You must keep your Transit Key until you have received and decrypted your Random Beacon key from the Flow team.
+
+
+ The transit script here need a `-t` token parameter flag. This token will have been provided to you by the Flow team out of band. Reach out to your contact if you don't have your token.
+
+
+```shell Upload-public-keys
+# If you joined our network previously, make sure to take a backup!
+cp /path/to/bootstrap /path/to/bootstrap.bak
+$ ./boot-tools/transit push -d ./bootstrap -t ${TOKEN} -role ${YOUR_NODE_ROLE}
+Running push
+Generating keypair
+Uploading ...
+Uploaded 400 bytes
+
+```
+
+
+ Once you've run the bootstrap and are confident in your setup, run the transit push command only once. If you bootstrap again and transit push again with a new node ID, it will count against your quota of Nodes. Exceeding your quota will result in a long back and forth with the Flow team to see which node is the extra one.
+
+
+## Update Node Config
+
+As flow node requires a `--nodeid` flag to start. You will need to pass in the contents of the `node-id` into either your container, `runtime-config.env` file, or hard coded into the `systemd` unit file which the flow team provides.
+
+You can get the `node-id` from the metadata that you pulled. It will be at: `/path/to/bootstrap/public-genesis-information/node-id`
+
+### Wait
+
+Now the ball is in the Flow team's court. As soon as all nodes have completed the above steps, the Genesis block will be created and distributed to you.
+
+Join the [Flow discord server](https://chat.onflow.org) if you haven't already and stay tuned for updates. Your nodes need not be online during this waiting period if you want to suspend them to reduce cost, but you must not lose your key material.
+
+
+ For the Genesis Block, your nodes will start pre-staked, which means no action on your part is needed to get your nodes staked.
+
+ For more details on staking check the guide on [Staking and Rewards](../../../staking/08-staking-rewards.md).
+
+
+## Receive Your Random Beacon Keys
+
+When the Flow team gives the go-ahead, your Random Beacon keys will be available for retrieval. Each Node will need to pull their own keys down individually.
+
+```shell Pull-beacon-keys
+~ $ ./boot-tools/transit pull -d ./bootstrap -t ${TOKEN} -role ${YOUR_NODE_ROLE}
+Fetching keys for node ID FEF5CCFD-DC66-4EF6-8ADB-C93D9B6AE5A4
+Decrypting Keys
+Keys available
+```
+
+Pulling your keys will also pull a bunch of additional metadata needed for the bootstrapping process.
+In the end, your bootstrap directory should look like this:
+
+```text bootstrap-directory
+~
+bootstrap/
+├── private-genesis-information
+│ └── private-node-info_{node id}
+│ ├── node-info.priv.json
+│ └── random-beacon.priv.json
+├── public-genesis-information
+│ ├── dkg-data.pub.json
+│ ├── genesis-block.json
+│ ├── genesis-cluster-block.{cid}.json
+│ ├── genesis-cluster-block.{cid}.json
+│ ├── genesis-cluster-qc.{cid}.json
+│ ├── genesis-cluster-qc.{cid}.json
+│ ├── genesis-commit.json
+│ ├── genesis-qc.json
+│ ├── node-id
+│ ├── node-info.pub.{node id}.json
+│ └── node-infos.pub.json
+├──
+```
+
+
+
+ Unlike staking and account keys, the beacon keys are not randomly generated, and depend on inputs from all consensus nodes on the network. In typical Flow network operation, these keys will be dynamically generated on demand by the consensus nodes communicating. However for genesis, as the consensus nodes aren't communicating yet, the Flow team will generate and distribute them to kickstart the process.
+
+
+## Move Genesis Data
+
+This bootstrapping data is needed by your node at each startup, so it must be present on disk.
+
+Where in the filesystem you store this data is up to you, but you may not change the folder structure generated by the bootstrapping process. By default, flow stores this data under `/var/flow/bootstrap`.
+
+## New Images
+
+Once the Genesis block has been minted, it will be included into the official container images so that it's available to all nodes. Pull the new images, which should now be version `v1.0.0`.
+
+## Start Your Nodes
+
+Once every node has puled its keys and fetched the new images, the network is ready to start.
+
+Make sure you're part of the [Discord Chat](https://chat.onflow.org). Once all nodes are ready, updates will be provided to everyone.
+
+Start your systems, let's make some blocks!
+
+
+=== networks/node-ops/light-nodes/observer-node.md ===
+---
+title: Light Node a.k.a Observer Node
+sidebar_label: Light Node Setup
+sidebar_position: 1
+---
+
+A light node also known as the observer node is similar to an access node and provides a locally accessible, continuously updated, verified copy of the block data. It serves the [gRPC Access API](../../access-onchain-data/index.md) but unlike an access node, an light node does not need to be staked, and **anyone** can run it without being added to the approved list of nodes.
+
+The light node bootstraps by connecting to an access node and becoming part of the public network comprised of access nodes and other light nodes. It then continuously receives blocks, which the consensus nodes are adding to the chain, either directly from access nodes or from other light nodes that are part of the public network. However, it makes no trust assumption of the upstream access node or the light node which is providing the block and locally verifies that the blocks that are received are the correct extension of the chain e.g. after receiving valid blocks A, B and C when it receives block D, it verifies that block D is indeed signed by the consensus nodes and is a valid next block. The received block data is indexed and made available via the Access API. For Collection, Transactions and Account queries, it delegates those requests to the upstream access node. Similarly, transactions and scripts sent to a light node are also forwarded to the upstream access node. Future versions of the light node will be able to serve this data locally as well.
+
+Since the light node is not staked, it does not produce or execute blocks but instead serves as an _unstaked access node_ that can be easily run on any consumer-grade computer which has enough disk space.
+
+
+
+## Who should run a light node?
+
+The light node provides an alternative to running an access node. Hence, it is ideal for Dapps that need access to the latest block data locally on a machine they control. Examples include a wallet application that needs to track the latest block ID and height. Alternatively, access node operators that want to scale their access node endpoints geographically can spin up light nodes in different regions, which can talk to their staked access node and to each other.
+
+## Running an light node
+
+### Hardware
+
+In general, any consumer-grade computer with a decent network connection and sufficient disk space should be able to run a light node.
+
+Minimum requirements
+
+- CPU with 2+ cores
+- 4 GB RAM minimum
+- 300 GB SSD disk
+- 10Mbps network connection
+
+### Steps to run a light node
+
+> [Here](https://www.loom.com/share/990a725531754106b91d8ccec6244219) is video walk-though of these 👇 steps.
+
+#### Step 1 - Generate the node directory structure
+The light node requires the following directory structure,
+```shell
+$ tree flow_observer
+flow_observer/
+├── bootstrap
+│ ├── network.key (file containing the node private network key)
+│ └── public-root-information
+│ └── root-protocol-state-snapshot.json (the genesis data of the current spork)
+└── data (directory used by the light node to store block data)
+```
+
+Create the parent and the sub-directories
+e.g.
+```shell
+mkdir -p flow_observer/bootstrap/public-root-information
+mkdir flow_observer/data
+```
+
+#### Step 2 - Generate the network key
+
+Like any other Flow node, the light node also needs a networking [ECDSA key](https://github.com/onflow/flow-go/blob/master/cmd/bootstrap/utils/key_generation.go#L52-L54) to talk to the network.
+Download the Bootstrapping kit, and generate the networking key.
+
+```shell
+curl -sL -O storage.googleapis.com/flow-genesis-bootstrap/boot-tools.tar
+tar -xvf boot-tools.tar
+./boot-tools/bootstrap observer-network-key --output-file ./flow_observer/bootstrap/network.key
+```
+
+_If you are running on a mac, download the boot-tools for mac to generate the key_
+```shell
+# For M1
+curl -sL -O storage.googleapis.com/flow-genesis-bootstrap/boot-tools-m1.tar
+# For Intel Mac
+curl -sL -O storage.googleapis.com/flow-genesis-bootstrap/boot-tools-intel-mac.tar
+```
+
+#### Step 3 - Download the root-protocol-state-snapshot.json file for the current spork
+
+The `root-protocol-state-snapshot.json` is generated for each [spork](../node-operation/spork.md) and contains the genesis data for that spork.
+It is published and made available after each spork. The download location is specified [here](https://github.com/onflow/flow/blob/master/sporks.json) under [rootProtocolStateSnapshot](https://github.com/onflow/flow/blob/master/sporks.json#L16) and can be downloaded as follows,
+
+For mainnet find the latest spork version from [sporks.json](https://github.com/onflow/flow/blob/master/sporks.json) and then download the `root-protocol-state-snapshot.json` and the signature file for it.
+
+```shell
+wget -P ./flow_observer/bootstrap/public-root-information https://storage.googleapis.com/flow-genesis-bootstrap/mainnet--execution/public-root-information/root-protocol-state-snapshot.json
+wget -P ./flow_observer/bootstrap/public-root-information https://storage.googleapis.com/flow-genesis-bootstrap/mainnet--execution/public-root-information/root-protocol-state-snapshot.json.asc
+```
+
+Similarly, for testnet find the latest spork version from [sporks.json](https://github.com/onflow/flow/blob/master/sporks.json) and then download the `root-protocol-state-snapshot.json` and the signature file for it.
+```shell
+wget -P ./flow_observer/bootstrap/public-root-information https://storage.googleapis.com/flow-genesis-bootstrap/testnet-/public-root-information/root-protocol-state-snapshot.json
+wget -P ./flow_observer/bootstrap/public-root-information https://storage.googleapis.com/flow-genesis-bootstrap/testnet-/public-root-information/root-protocol-state-snapshot.json.asc
+```
+
+##### Verify the PGP signature
+
+Add the `flow-signer@onflow.org` public key
+```shell
+gpg --keyserver keys.openpgp.org --search-keys flow-signer@onflow.org
+
+gpg: data source: http://keys.openpgp.org:11371
+(1) Flow Team (Flow Full Observer node snapshot verification master key) <
+ 256 bit ECDSA key CB5264F7FD4CDD27, created: 2021-09-15
+Keys 1-1 of 1 for "flow-signer@onflow.org". Enter number(s), N)ext, or Q)uit > 1
+```
+
+Verify the root-snapshot file
+```shell
+gpg --verify ./flow_observer/bootstrap/public-root-information/root-protocol-state-snapshot.json.asc
+
+gpg: assuming signed data in 'bootstrap/public-root-information/root-protocol-state-snapshot.json'
+gpg: Signature made Wed Sep 15 11:34:33 2021 PDT
+gpg: using ECDSA key 40CD95717AC463E61EE3B285B718CA310EDB542F
+gpg: Good signature from "Flow Team (Flow Full Observer node snapshot verification master key) " [unknown]
+gpg: WARNING: This key is not certified with a trusted signature!
+gpg: There is no indication that the signature belongs to the owner.
+Primary key fingerprint: 7D23 8D1A E6D3 2A71 8ECD 8611 CB52 64F7 FD4C DD27
+ Subkey fingerprint: 40CD 9571 7AC4 63E6 1EE3 B285 B718 CA31 0EDB 542F
+```
+
+Alternately, if you don't care about the blocks before the current block, you can request the current root-snapshot file via the [Flow CLI](../../../tools/flow-cli/index.md).
+
+For mainnet
+```shell
+ flow snapshot save ./flow_observer/bootstrap/public-root-information/root-protocol-state-snapshot.json --host secure.mainnet.nodes.onflow.org:9001 --network-key 28a0d9edd0de3f15866dfe4aea1560c4504fe313fc6ca3f63a63e4f98d0e295144692a58ebe7f7894349198613f65b2d960abf99ec2625e247b1c78ba5bf2eae
+```
+
+For testnet
+```shell
+flow snapshot save ./flow_observer/bootstrap/public-root-information/root-protocol-state-snapshot.json --host secure.testnet.nodes.onflow.org:9001 --network-key ba69f7d2e82b9edf25b103c195cd371cf0cc047ef8884a9bbe331e62982d46daeebf836f7445a2ac16741013b192959d8ad26998aff12f2adc67a99e1eb2988d
+```
+
+#### Step 4 - Start the node
+
+The light node can be run as a docker container
+
+##### Observer for Flow Mainnet
+
+```shell
+docker run --rm \
+ -v $PWD/flow_observer/bootstrap:/bootstrap:ro \
+ -v $PWD/flow_observer/data:/data:rw \
+ --name flow_observer \
+ -p 80:80 \
+ -p 3569:3569 \
+ -p 9000:9000 \
+ -p 9001:9001 \
+ gcr.io/flow-container-registry/observer:v0.27.2 \
+ --bootstrapdir=/bootstrap \
+ --datadir=/data/protocol \
+ --bind 0.0.0.0:3569 \
+ --rest-addr=:80 \
+ --loglevel=error \
+ --secretsdir=/data/secrets \
+ --upstream-node-addresses=secure.mainnet.nodes.onflow.org:9001 \
+ --upstream-node-public-keys=28a0d9edd0de3f15866dfe4aea1560c4504fe313fc6ca3f63a63e4f98d0e295144692a58ebe7f7894349198613f65b2d960abf99ec2625e247b1c78ba5bf2eae \
+ --bootstrap-node-addresses=secure.mainnet.nodes.onflow.org:3570 \
+ --bootstrap-node-public-keys=28a0d9edd0de3f15866dfe4aea1560c4504fe313fc6ca3f63a63e4f98d0e295144692a58ebe7f7894349198613f65b2d960abf99ec2625e247b1c78ba5bf2eae \
+ --observer-networking-key-path=/bootstrap/network.key
+```
+
+##### Observer for Flow Testnet
+
+```shell
+docker run --rm \
+ -v $PWD/flow_observer/bootstrap:/bootstrap:ro \
+ -v $PWD/flow_observer/data:/data:rw \
+ --name flow_observer \
+ -p 80:80 \
+ -p 3569:3569 \
+ -p 9000:9000 \
+ -p 9001:9001 \
+ gcr.io/flow-container-registry/observer:v0.27.2 \
+ --bootstrapdir=/bootstrap \
+ --datadir=/data/protocol \
+ --bind 0.0.0.0:3569 \
+ --rest-addr=:80 \
+ --loglevel=error \
+ --secretsdir=/data/secrets \
+ --upstream-node-addresses=secure.devnet.nodes.onflow.org:9001 \
+ --upstream-node-public-keys=ba69f7d2e82b9edf25b103c195cd371cf0cc047ef8884a9bbe331e62982d46daeebf836f7445a2ac16741013b192959d8ad26998aff12f2adc67a99e1eb2988d \
+ --bootstrap-node-addresses=secure.devnet.nodes.onflow.org:3570 \
+ --bootstrap-node-public-keys=ba69f7d2e82b9edf25b103c195cd371cf0cc047ef8884a9bbe331e62982d46daeebf836f7445a2ac16741013b192959d8ad26998aff12f2adc67a99e1eb2988d \
+ --observer-networking-key-path=/bootstrap/network.key
+```
+
+The light node acts as a DHT client and bootstraps from upstream access nodes which run the DHT server.
+The upstream bootstrap server is specified using the `bootstrap-node-addresses` which is the comma-separated list of hostnames of the access nodes.
+The `bootstrap-node-public-keys` is the list of the corresponding networking public key of those nodes.
+
+The light node delegates many of the API calls to the upstream access nodes.
+The `upstream-node-addresses` is the list of access node hostnames to which this light node can delegate to. The list can be different from the bootstrap node list.
+The `bootstrap-node-public-key` is the list of the corresponding networking public key of those nodes.
+
+> In the above docker commands, the Flow community access nodes are being used as the upstream access nodes. However, any other Flow access node that supports a light node can be used
+
+_All parameters and their explanation can be found [here](https://github.com/onflow/flow-go/blob/82da35141ff095fbf75ce2c950efec240ad38565/cmd/access/node_builder/access_node_builder.go#L523-L558)_
+
+🚀 **The node should now be up and running**
+
+You can now query the node for blocks, transaction etc. similar to how you would query an access node.
+
+e.g. querying the gRPC API endpoint using Flow CLI
+```shell
+flow blocks get latest --host localhost:9000
+```
+
+e.g. querying the REST API endpoint using curl
+```shell
+curl "http://localhost/v1/blocks?height=sealed"
+```
+
+The light node, like the other type of Flow nodes, also produces Prometheus metrics that can be used to monitor node health. More on that [here](../node-operation/node-setup.md#monitoring-and-metrics)
+
+
+## FAQs
+
+### Does the light node need to be staked?
+
+No, the light node is not a staked node.
+
+### Can any access node be used to bootstrap a light node?
+
+No, only Access nodes which have explicitly turned ON support for light nodes can be used to bootstrap a light node.
+
+The public access nodes that support light nodes are listed below. Apart from these, other public access nodes run by node operators other than the Flow foundation team may choose to support light nodes.
+
+### How can an access node turn ON support for light node?
+
+An access node can support a light node by passing in the following two parameters when starting the access node
+```shell
+ --supports-observer=true --public-network-address=0.0.0.0:3570
+```
+`public-network-address` is the address the light nodes will connect to.
+
+### Are light nodes subject to rate limits?
+
+The light node serves all the [Block related queries](https://github.com/onflow/flow/blob/master/protobuf/flow/access/access.proto#L24-L42) from is local database. These are not subjected to any rate limits.
+
+However, it proxies all the other requests to the access node and those will be rate limited as per the rate limits defined on that access node.
+
+
+### Flow community access nodes that support connections from light nodes
+
+#### For mainnet
+
+Access-007:
+* Host: `access-007.[current mainnet spork].nodes.onflow.org`
+* Public Key: `28a0d9edd0de3f15866dfe4aea1560c4504fe313fc6ca3f63a63e4f98d0e295144692a58ebe7f7894349198613f65b2d960abf99ec2625e247b1c78ba5bf2eae`
+
+Access-008:
+* Host: `access-008.[current mainnet spork].nodes.onflow.org`
+* Public Key: `11742552d21ac93da37ccda09661792977e2ca548a3b26d05f22a51ae1d99b9b75c8a9b3b40b38206b38951e98e4d145f0010f8942fd82ddf0fb1d670202264a`
+
+#### For testnet
+
+Access-001:
+* Host: `access-001.[current devnet spork].nodes.onflow.org`
+* Public Key: `ba69f7d2e82b9edf25b103c195cd371cf0cc047ef8884a9bbe331e62982d46daeebf836f7445a2ac16741013b192959d8ad26998aff12f2adc67a99e1eb2988d`
+
+Access-003:
+* Host: `access-003.[current devnet spork].nodes.onflow.org`
+* Public Key: `b662102f4184fc1caeb2933cf87bba75cdd37758926584c0ce8a90549bb12ee0f9115111bbbb6acc2b889461208533369a91e8321eaf6bcb871a788ddd6bfbf7`
+
+
+While the public keys remain the same, the hostnames change each spork to include the spork name. Substitute `[current mainnet spork]` and `[current devnet spork]` with the appropriate spork name (e.g. `mainnet20`).
+See [Past Sporks](../node-operation/past-upgrades) for the current spork for each network.
+
+
+=== networks/node-ops/evm-gateway/evm-gateway-setup.md ===
+---
+title: Setting up an EVM Gateway node
+sidebar_label: EVM Gateway Setup
+sidebar_position: 2
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+This guide is for running the [EVM Gateway](https://github.com/onflow/flow-evm-gateway) node on Flow. The EVM Gateway implements the
+[Ethereum JSON-RPC specification](https://ethereum.org/en/developers/docs/apis/json-rpc/) and is the only node type which accepts EVM
+client connections.
+
+The EVM Gateway consumes Flow protocol state from the configured Flow Access Node and persists the indexed EVM state locally to
+service EVM client requests. It submits EVM transactions it receives into the Flow network, wrapped in a Cadence transaction, and
+mutating EVM state when executed. Non-mutating RPC methods only query the local state index of the gateway and are never forwarded
+to Access Nodes. It does not participate in the block production process and requires no stake.
+
+## Anyone can run EVM Gateway
+
+The EVM Gateway can serve as a dedicated private RPC, a performance scaling solution, and a free gas provider offering similar capabilities
+to centralized middleware providers like Infura, Alchemy, etc. at a fraction of the cost. EVM Gateway nodes connect directly to the Flow network
+with no middleware, giving you full control.
+
+If you are just getting started building your application, you can use the [public EVM Gateway](https://developers.flow.com/evm/networks).
+Applications generating high call volumes to the JSON-RPC may have hit rate limits on Flow public EVM Gateway and may benefit from running their
+own gateway to remove rate limits. Self-hosted gateways connect directly to public Flow Access Nodes, which may also optionally be [run](../access-nodes/access-node-setup.md).
+
+:::info
+
+Apps can use EVM gateway to subsidize user transaction fees for smoother onboarding
+
+:::
+
+Alternatively, you can also choose from any of the following providers who provide the EVM Gateway as a managed service along with other value added services on top.
+
+1. [Alchemy](https://www.alchemy.com/flow)
+2. [ThirdWeb](https://thirdweb.com/flow)
+3. [Moralis](https://docs.moralis.com/web3-data-api/evm/chains/flow)
+4. [QuickNode](https://www.quicknode.com/chains/flow)
+
+## Hardware specifications
+
+The EVM Gateway is a lightweight node which runs on commodity hardware and cloud VMs. It can be run on GCP **standard** and AWS **large**
+VM types for low to moderate volume app co-location use-cases. However, higher volume use cases may require larger instance types and more
+testing. An inactive node requires less than 200MB memory when run in Docker and data storage growth corresponds with Flow EVM transaction
+growth. Listed below are theoretical RPS maximums based on Flow mainnet CPU and memory resource utilization metrics and linear scaling assumptions.
+
+### Google Cloud Platform (GCP) VM Types
+
+| VM Type | vCPUs | Memory (GB) | Estimated Max Requests/s |
+| --------- |-------|-------------|--------------------------|
+| n2-standard-2 | 2 | 8 | ~2,950 |
+| c4a-standard-1 | 1 | 4 | ~1,475 |
+| c4a-standard-2 | 2 | 8 | ~2,950 |
+| n2-highmem-4 | 4 | 32 | ~11,800 |
+| c3-standard-8 | 8 | 32 | ~29,500 |
+
+### Amazon Web Services (AWS) EC2 Instance Types
+| Instance Type | vCPUs | Memory (GB) | Estimated Max Requests/s |
+| --------- |--------|-------------|--------------------------|
+| m6i.large | 2 | 8 | ~2,950 |
+| c6i.large | 2 | 4 | ~3,687 |
+| m6i.xlarge | 4 | 16 | ~11,800 |
+| c6i.2xlarge | 8 | 16| ~29,500 |
+| t3.2xlarge | 8 | 32 | ~17,700 |
+
+# How To Run EVM Gateway
+
+## Step 1 - Account Creation
+
+The EVM Gateway's role in mediating EVM transactions over to Cadence is how it accrues fees from handling client transactions. Since
+the gateway submits Cadence transactions wrapping EVM transaction payloads to the Flow Access Node the transaction fee for that must
+be paid by the EVM Gateway.
+
+The account used for funding gateway Cadence transactions must be a COA, not an EOA. `--coa-address` is configured with the Cadence address
+of the COA account and the `--coa-key` must belong to the same account. The `--coinbase` account accrues EVM Gateway fees from EVM client
+transactions and can be either an EVM EOA or COA address.
+
+It is acceptable to create a single Cadence account for the COA and use the EVM address associated with that for the COINBASE address.
+
+### Create Flow account to use for COA
+
+If you don't already have a Flow account you will need to create one.
+
+
+
+
+ 1. Install [Flow Wallet](https://wallet.flow.com/)
+ 2. Once installed you will be able to copy the wallet address, similar to _0x1844efeb3fef2242_
+ 3. Obtain account private key from
+ Settings -> Account List -> Choose Main account -> Private Key -> [Password prompt]
+ 4. Ensure the wallet is funded from a CEX or other wallet
+
+
+
+
+Install [Flow CLI](https://developers.flow.com/tools/flow-cli/install) if not already installed.
+
+```bash
+flow keys generate
+```
+This will output something similar to:
+`
+```bash
+🔴️ Store private key safely and don't share with anyone!
+Private Key 3cf8334d.....95c3c54a28e4ad1
+Public Key 33a13ade6....85f1b49a197747
+Mnemonic often scare peanut ... boil corn change
+Derivation Path m/44'/539'/0'/0/0
+Signature Algorithm ECDSA_P256
+```
+
+Visit https://faucet.flow.com/, and use the generated `Public Key`, to create and fund your Flow testnet account.
+
+
+
+
+## Step 2 - Build the gateway
+
+To run EVM Gateway on bare metal or in a VM without the use of docker, select the '_Build from source_' tab otherwise refer to the
+'_Build using Docker_' tab.
+
+
+
+
+This will build the EVM gateway binary from source.
+
+```bash
+git clone https://github.com/onflow/flow-evm-gateway.git
+
+cd flow-evm-gateway
+git checkout $(curl -s https://api.github.com/repos/onflow/flow-evm-gateway/releases/latest | jq -r .tag_name)
+CGO_ENABLED=1 go build -o evm-gateway cmd/main/main.go
+chmod a+x evm-gateway
+mv evm-gateway /usr/bin
+```
+
+
+
+
+```bash
+git clone https://github.com/onflow/flow-evm-gateway.git
+
+cd flow-evm-gateway
+git checkout $(curl -s https://api.github.com/repos/onflow/flow-evm-gateway/releases/latest | jq -r .tag_name)
+make docker-build
+```
+
+
+
+
+Registry versions available for download can be found [here](https://console.cloud.google.com/artifacts/docker/dl-flow-devex-production/us-west1/development/flow-evm-gateway).
+```bash
+docker pull us-west1-docker.pkg.dev/dl-flow-devex-production/development/flow-evm-gateway:${VERSION}
+```
+
+
+
+
+## Step 3 - Start Your Node
+
+Operators will need to refer to the gateway [configuration flags](https://github.com/onflow/flow-evm-gateway?tab=readme-ov-file#configuration-flags) and make adjustments that align with the desired
+deployment topology.
+
+### EVM Coinbase address
+
+If this is your first time setting up the gateway we need to ensure that an EVM COA or EOA address is available to configure the `COINBASE`. This account
+can be an account created using Metamask or other web3.js wallet, or otherwise can be the EVM address corresponding to the Flow Wallet COA account created above.
+
+If you haven't already got an EVM address and you have the COA account created by Flow Wallet above then follow the steps below:
+
+* Click top left burger icon to show current profile
+* Click 'Enable the path to Flow EVM' button
+* Your EVM account will now be available to use in the left nav account view
+* When you switch to that account you can obtain its EVM address
+
+### COA Address and Key
+
+COA address and private key is configured for `--coa-address` & `--coa-key` configuration flags. If running multiple EVM Gateway hosts it is standard to
+share the same COA address and key across _n_ hosts.
+
+### Run the gateway
+
+Ensure that the following ENV variables have been set. Add/update as required if your configuration differs from those listed.
+
+```bash
+# Set required environment variables
+export ACCESS_NODE_GRPC_HOST="access.mainnet.nodes.onflow.org:9000" # or access.devnet.nodes.onflow.org:9000 for testnet
+export FLOW_NETWORK_ID="flow-mainnet" # or flow-testnet
+export INIT_CADENCE_HEIGHT="85981135" # 211176670 for testnet
+export COINBASE="${EVM_ADDRESS_WITHOUT_0x}"
+export COA_ADDRESS="${CADENCE_ACCOUNT_ADDRESS_WITHOUT_0x}"
+export COA_KEY="${CADENCE_ACCOUNT_PRIVATE_KEY_WITHOUT_0x}"
+export GAS_PRICE="100" # operators can set this to 0 for zero cost transactions. The linked COA account will pay for transactions on users behalf
+
+# $\{ACCESS_NODE_SPORK_HOSTS\} are comma separated
+# testnet: access-001.devnet51.nodes.onflow.org:9000
+# mainnet: access-001.mainnet25.nodes.onflow.org:9000
+```
+ACCESS_NODE_SPORK_HOSTS is used by the gateway to track state across Flow sporks. These are generally infrequent with only one planned
+spork per year. A canonical list of required hosts can be found in the EVM Gateway [Makefile](https://github.com/onflow/flow-evm-gateway/blob/main/Makefile#L9).
+
+
+
+
+**Create EVM Gateway service**
+
+```bash
+sudo tee </dev/null /etc/systemd/system/gateway.service
+[Unit]
+Description=Gateway daemon
+After=network-online.target
+
+[Service]
+User=$USER
+ExecStart=/usr/bin/evm-gateway \
+--access-node-grpc-host=$ACCESS_NODE_GRPC_HOST \
+--access-node-spork-hosts=$ACCESS_NODE_SPORK_HOSTS \
+--flow-network-id=$FLOW_NETWORK_ID \
+--init-cadence-height=$INIT_CADENCE_HEIGHT \
+--ws-enabled=true \
+--coinbase=$COINBASE \
+--coa-address=$COA_ADDRESS \
+--coa-key=$COA_KEY \
+--rate-limit=9999999 \
+--rpc-host=0.0.0.0 \
+--gas-price=$GAS_PRICE \
+--tx-state-validation=local-index
+Restart=always
+RestartSec=3
+LimitNOFILE=4096
+
+[Install]
+WantedBy=multi-user.target
+EOF
+
+cat /etc/systemd/system/gateway.service
+sudo systemctl enable gateway
+```
+
+**Start all services**
+
+```bash
+sudo systemctl daemon-reload
+sudo systemctl restart access-node
+sudo systemctl restart gateway
+```
+
+**Check logs**
+
+```bash
+# change log settings to persistent if not already
+sed -i 's/#Storage=auto/Storage=persistent/g' /etc/systemd/journald.conf
+sudo systemctl restart systemd-journald
+
+journalctl -u gateway.service -f -n 100
+```
+
+
+
+
+It may be necessary to make local changes to the `docker-run` target to add params which are needed for your requirements. If you pulled a
+specific image from the gateway container registry ensure that the `$VERSION` environment variable is set to the same as the image version
+you pulled.
+
+```bash
+cd flow-evm-gateway
+make docker-run
+```
+Additional options are available as follows
+
+```bash
+DOCKER_RUN_DETACHED=true
+DOCKER_HOST_MOUNT=[host mount directory]
+DOCKER_HOST_PORT=[desired port to expose on host]
+DOCKER_HOST_METRICS_PORT=[desired port to expose on host for metrics]
+
+# Example usage
+
+make DOCKER_RUN_DETACHED=true DOCKER_HOST_PORT=1234 DOCKER_HOST_MOUNT=/my/host/dir docker-run
+```
+
+
+
+
+### Startup bootstrap indexing
+
+Once your EVM Gateway is up and running you will see it indexing the Flow network which was configured. At the present time this
+is a lengthy process (possibly 1-3 days, depending on CPU core count) during which time the gateway will not respond to queries.
+Once the data is fully indexed the gateway can serve requests to clients.
+
+To speed up gateway setup we recommend backing up the `/${GATEWAY_HOME_DIR}/data` directory to use when creating additional nodes
+using the same release version. We are currently working on an export/import feature that will enable gateway operators to
+store state snapshots to bootstrap newly created nodes without the delay.
+
+:::note
+
+If you are upgrading the gateway from pre-v1.0.0 release versions the indexed data directory will need to be reindexed from genesis.
+You will not be able to re-use the DB data dir from the previous versions.
+
+:::
+
+### Account and Key Management
+
+When operating an EVM Gateway it is important to understand how keys are configured and used. Each gateway instance
+must be configured with a Flow account address, which is sufficiently funded and which it uses to pay to wrap EVM transactions into a
+Cadence transaction when submitting to the Flow Access Node. This can be configured with a standalone private key file for
+the `--coa-key` config flag. Alternatively, you may also use cloud KMS providers per the guidance below.
+
+#### COA Account signing key rotation
+
+The gateway implements a signing key rotation scheme to scale the use of the `COA_KEY` and enable it to be used across many
+EVM client transactions. This is configured by reusing the COA public key to create new on-chain signing keys. Although it may seem
+counter-intuitive to use the same COA public key when creating new signing keys, the newly added keys all occupy different
+key slots on the account which enables the gateway to support concurrent transaction signing without causing [nonce collisions](https://developers.flow.com/build/advanced-concepts/scaling#problem)
+for EVM clients.
+
+Assuming there is already one key on the account, the following example transaction adds 100 copies of that key:
+```swift
+transaction {
+ prepare(signer: auth(AddKey) &Account) {
+ let firstKey = signer.keys.get(keyIndex: 0)!
+ let range: InclusiveRange = InclusiveRange(1, 100, step: 1)
+ for element in range {
+ signer.keys.add(
+ publicKey: firstKey.publicKey,
+ hashAlgorithm: HashAlgorithm.SHA2_256,
+ weight: 1000.0
+ )
+ }
+ }
+}
+```
+Signing keys which are added to the COA account are required to use the same hashing algorithm as the key being copied.
+
+If keys are added while the gateway is running it will need to be restarted to make use of the new keys.
+
+:::note
+
+If you are operating your EVM Gateway(s) to relay traffic for Flow EVM, or if you otherwise anticipate high volumes of
+transactions we recommend configuring 2000 signing keys or more. Signing key utilization increases proportionately
+with transaction throughput growth.
+
+A large number of keys are recommended for live networks because keys have a lengthy cool down period of 600 blocks (approx 10 minutes)
+before they are re-used. This is to avoid nonce collisions from re-using the key too soon.
+
+:::
+
+You can track signing key utilization as a metric, see `evm_gateway_available_signing_keys` below.
+
+
+#### KMS Configuration
+
+EVM Gateway allows for Google and AWS Key Management Service (KMS) integration, which is the recommended way of setting up the gateway
+for live networks. It is only required to configure a single KMS key for the Flow account configured as the gateway `COA_ACCOUNT`.
+
+```
+--coa-cloud-kms-project-id=your-project-kms-id \
+--coa-cloud-kms-location-id=global \
+--coa-cloud-kms-key-ring-id=your-project-kms-key-ring-id \
+--coa-cloud-kms-key=example-gcp-kms@1 \
+```
+
+### Monitoring and Metrics
+
+The EVM Gateway reports Prometheus metrics which are a way to monitor the gateway's availability and progress. The database folder
+size may also need to be monitored to prevent disk full issues.
+
+**Metric labels**
+```bash
+evm_gateway_api_errors_total # Total count of API errors for period
+evm_gateway_api_request_duration_seconds_bucket # Histogram metric buckets for API request durations
+evm_gateway_api_request_duration_seconds_count # Histogram metric API request count for period
+evm_gateway_api_request_duration_seconds_sum # Histogram metric API request sum of values for period
+evm_gateway_api_server_panics_total # Total count of server panics for period
+evm_gateway_blocks_indexed_total # Total count of EVM blocks indexed
+evm_gateway_cadence_block_height # Cadence block height
+evm_gateway_evm_account_interactions_total # Count of unique accounts observed for period
+evm_gateway_evm_block_height # EVM block height
+evm_gateway_operator_balance # Gateway node COA operator account balance
+evm_gateway_trace_download_errors_total # Total count of trace download errors
+evm_gateway_txs_indexed_total # Total count of indexed transactions
+evm_gateway_available_signing_keys # Total count of available COA signing keys
+```
+
+Alerts are recommended to be configured on server panics, low operator balance, available signing keys and disk usage metrics.
+
+**Metrics port**
+
+```
+--metrics-port 8080 \
+```
+### Node Status
+
+For basic node status or keepalive monitoring we recommend automated checks on the following monotonically increasing counter:
+```
+curl -s -XPOST 'your-evm-gw-host:8545' --header 'Content-Type: application/json' --data-raw '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' | jq -r '.result' | xargs printf "%d\n"
+10020239
+```
+
+## Troubleshooting
+
+Join our [Discord](https://discord.com/invite/J6fFnh2xx6) and use the `#flow-evm` channel to ask any questions you may have about
+EVM Gateway.
+
+### No signing keys available
+
+```bash
+Failed to send transaction: no signing keys available
+```
+This message indicates that the GW has used all its available signing keys. Please refer to the [Account and Key Management](./evm-gateway-setup#account-and-key-management) documentation to add more signing keys to your COA.
+
+### Database version inconsistency/corruption
+
+If you see a similar message to this from an aborted startup the gateway database directory is not compatible with the schema versions of the runtime, or there may be corruption. In this instance we recommend that you delete the contents of the EVM GW data directory.
+
+```bash
+Jan 16 17:00:57 nodename docker[6552]: {"level":"error","error":"failed to open db for dir: /flow-evm-gateway/db, with: pebble: manifest file \"MANIFEST-018340\" for DB \"/flow-evm-gateway/db\": comparer name from file \"leveldb.BytewiseComparator\" != comparer name from Options \"flow.MVCCComparer\"","time":"2025-01-16T17:00:57Z","message":"Gateway runtime error"}
+```
+
+### State stream configuration
+
+If you are running an Access Node on the same logical host as the EVM Gateway you may see the following log entries.
+
+```bash
+failure in event subscription at height ${INIT-CADENCE-HEIGHT}, with: recoverable: disconnected: error receiving event: rpc error: code = Unimplemented desc = unknown service flow.executiondata.ExecutionDataAPI”
+```
+```bash
+component execution data indexer initialization failed: could not verify checkpoint file: could not find expected root hash e6d4f4c755666c21d7456441b4d33d3521e5e030b3eae391295577e9130fd715 in checkpoint file which contains: [e10d3c53608a1f195b7969fbc06763285281f64595be491630a1e1bdfbe69161]
+```
+
+To resolve this configure `--state-stream-addr` to use the same address/port combination which is set for Access Node `--rpc-addr`.
+This is required by the gateway to allow both the streaming and non-streaming APIs to query using the same connection.
+
+### Access Node not fully synced
+
+The following log entry will occur when the EVM Gateway attempts to sync with the Access Node but it has not yet synced up to latest block
+```bash
+failure in event subscription at height ${INIT-CADENCE-HEIGHT}, with: recoverable: disconnected: error receiving event: rpc error: code = FailedPrecondition desc = could not get start height: failed to get lowest indexed height: index not initialized
+```
+
+
+=== networks/node-ops/access-nodes/access-node-setup.md ===
+---
+title: Setting Up a Flow Access Node
+sidebar_label: Access Node Setup
+sidebar_position: 1
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+This guide is for running a permissonless Access node on Flow. If you are planning to run a different type of staked node then see [node bootstrap](../node-operation/node-bootstrap.md).
+
+Permissionless Access nodes allow any operator to run a Flow Access node.
+Unlike the other staked nodes, a permissionless access node does not have to be approved by the service account before it can join the network, hence the term "permissionless". The goal is to make all node types permissionless and this is the first step towards achieving that goal.
+
+## Who Should Run a Permissionless Access Node?
+dApp developers can choose to run their own private permissionless access node and move away from using the community access nodes. This will also allow them to not be subjected to the API rate limits of the public access nodes.
+
+Node operators can also run their own permissionless access node and provide access to that node as a service.
+
+Chain analytics, audit and exploration applications can run such an access node and do not have to rely on third parties for the state of the network.
+
+## Timing
+
+New nodes are able to join the network each time a new epoch begins.
+An epoch is a period of time (approximately one week) when the node operators in the network are constant.
+At epoch boundaries, newly staked node operators are able to join the network and existing node operators which have unstaked may exit the network.
+You can read more about epochs [here](../../staking/03-schedule.md).
+
+
+In order to join the network at epoch N+1, the access node **must** be registered with at least 100 FLOW staked prior to the end of epoch N's Staking Auction Phase.
+
+Currently on mainnet, the staking auction starts every Wednesday at around 20:00 UTC and ends on the next Wednesday at around 12:00 UTC.
+Since this deadline may shift slightly from epoch to epoch, we recommend the node be staked by _Wednesday, 8:00 UTC_ to be able to join the network in the next epoch.
+
+Confirmation of a new node's inclusion in epoch N+1 is included in the [`EpochSetup` event](../../staking/05-epoch-scripts-events.md#flowepochepochsetup).
+
+
+
+## Limitations
+
+There are five open slots for access nodes every epoch.
+You can view the exact epoch phase transition time [here](https://dashboard.flow.com/) under `Epoch Phase`.
+
+To summarize,
+
+| **Epoch** | **Epoch Phase** | |
+|:----------:|:----------------------:|:---------------------------------------------------:|
+| N | Staking auction starts | Three new access node slots are opened. Anyone can register their access nodes |
+| N | Staking auction ends | Three of the nodes registered during this epoch are randomly selected to be a part of the network in the next epoch. No more nodes can register until the next epoch starts. |
+| N+1 | Epoch N+1 starts | The newly selected nodes can now participate in the network. Three new slots are opened. |
+
+## How To Run a Permissionless Access Node?
+
+:::note
+
+To run an access node you will need to provision a machine or virtual machine to run your node software. Please follow the [node-provisioning](../node-operation/node-provisioning.md) guide for it.
+You can provision the machine before or after your node has been chosen.
+
+:::
+
+At a high level, to run a permissionless Access node, you will have to do the following steps:
+1. Generate the node identity (private and public keys, node ID etc.).
+2. Stake the node with 100 FLOW by the end of the staking phase of the current epoch (see [timing](#timing)) by providing the node information generated in step 1.
+3. You can verify if your node ID was selected by the on-chain random selection process on Wednesday at around 20:00 UTC when the next epoch starts.
+4. If your node ID was selected, you can provision and start running the node. If your node wasn't selected, your tokens will have been refunded to your unstaked bucket in the staking smart contract. When the next epoch begins, you can try committing tokens again in a future epoch to get a new spot.
+
+Following is a detail explanation of these four steps.
+If you want to run multiple access nodes, you will have to run through these steps for each node.
+
+## Step 1 - Generate Node Information
+
+### Download the Bootstrapping Kit
+
+```shell
+curl -sL -O storage.googleapis.com/flow-genesis-bootstrap/boot-tools.tar
+tar -xvf boot-tools.tar
+```
+
+```shell CheckSHA256
+sha256sum ./boot-tools/bootstrap
+460cfcfeb52b40d8b8b0c4641bc4e423bcc90f82068e95f4267803ed32c26d60 ./boot-tools/bootstrap
+```
+
+> If you have downloaded the bootstrapping kit previously, ensure the SHA256 hash for it still matches. If not, re-download to ensure you are using the most up-to-date version.
+
+### Generate Your Node Identity
+
+```shell
+#########################################################
+# Generate Keys
+$ mkdir ./bootstrap
+# YOUR_NODE_ADDRESS: FQDN associated to your instance
+$ ./boot-tools/bootstrap key --address ":3569" --role access -o ./bootstrap
+```
+
+```shell Example
+$./boot-tools/bootstrap key --address "flowaccess.mycompany.com:3569" --role access -o ./bootstrap
+ DBG will generate networking key
+ INF generated networking key
+ DBG will generate staking key
+ INF generated staking key
+ DBG will generate db encryption key
+ INF generated db encryption key
+ DBG assembling node information address=flowaccess.mycompany.com:3569
+ DBG encoded public staking and network keys networkPubKey=f493a74704f6961ae7903e062ecd58d990672858eff99aece7bfbccf3aa02de8f1a624ecbf21a01e8b2f4a5854c231fbe218edd7762a34fea881f3958a215305 stakingPubKey=ae8dcf81f3a70d72036b7ba2c586ed37ed0eb82b9c0a4aab998a8420f98894f94c14f84fa716e93654d3940fc0c8ff4d19b504c90a5b4918b28f421e9d3659dc2b7e246025ebeffea0d83cceefe315d7ed346dbe412fdac51b64997d97d29f7e
+ INF wrote file bootstrap/public-root-information/node-id
+ INF wrote file bootstrap/private-root-information/private-node-info_e737ec6efbd26ef43bf676911cdc5a11ba15fc6562d05413e6589fccdd6c06d5/node-info.priv.json
+ INF wrote file bootstrap/private-root-information/private-node-info_e737ec6efbd26ef43bf676911cdc5a11ba15fc6562d05413e6589fccdd6c06d5/secretsdb-key
+ INF wrote file bootstrap/public-root-information/node-info.pub.e737ec6efbd26ef43bf676911cdc5a11ba15fc6562d05413e6589fccdd6c06d5.json
+
+$tree ./bootstrap/
+./bootstrap/
+├── private-root-information
+│ └── private-node-info_e737ec6efbd26ef43bf676911cdc5a11ba15fc6562d05413e6589fccdd6c06d5
+│ ├── node-info.priv.json
+│ └── secretsdb-key
+└── public-root-information
+ ├── node-id
+ └── node-info.pub.e737ec6efbd26ef43bf676911cdc5a11ba15fc6562d05413e6589fccdd6c06d5.json
+
+3 directories, 4 files
+```
+
+:::warning
+
+_Use a fully qualified domain name for the network address. Please also include the port number in the network address e.g. `flowaccess.mycompany.com:3569`_
+
+:::
+
+:::warning
+
+_Do not include the prefix `http://` in the network address._
+
+:::
+
+:::tip
+
+If you would like to stake multiple access nodes, please ensure you generate a unique identity for each node.
+
+:::
+
+Your node identity has now been generated. Your node ID can be found in the file `./bootstrap/public-root-information/node-id`.
+
+```shell Example
+$cat ./bootstrap/public-root-information/node-id
+e737ec6efbd26ef43bf676911cdc5a11ba15fc6562d05413e6589fccdd6c06d5
+```
+
+:::info
+
+All your private keys should be in the `bootstrap` folder created earlier. Please take a back up of the entire folder.
+
+:::
+
+## Step 2 - Stake the Node
+
+You need to now register the node on chain by staking the node via [Flow Port](https://port.onflow.org/).
+
+[Here](../../flow-port/staking-guide.md) is a guide on how to use Flow port if you are not familiar with it.
+If you are staking via a custody provider or would like to directly submit a staking transaction instead follow this [guide](../../staking/index.md#how-do-i-stake).
+
+Fund you Flow account with at least 100.01 FLOW tokens, which covers the required stake plus the storage deposit.
+
+On Flow port, choose `Stake and Delegate` -> `Start Staking` or `Stake Again` and then choose Access node as the option.
+
+
+
+On the next screen, provide the node details of you node.
+
+Those node details (`Node ID`, `Network Address`, `Networking Key` and `Staking Key`) can be found in the file: `./bootstrap/public-root-information/node-info.pub..json`.
+
+```shell Example
+$cat ./bootstrap/public-root-information/node-info.pub. e737ec6efbd26ef43bf676911cdc5a11ba15fc6562d05413e6589fccdd6c06d5.json
+{
+ "Role": "access",
+ "Address": "flowaccess.mycompany.com:3569",
+ "NodeID": "e737ec6efbd26ef43bf676911cdc5a11ba15fc6562d05413e6589fccdd6c06d5",
+ "Weight": 0,
+ "NetworkPubKey": "f493a74704f6961ae7903e062ecd58d990672858eff99aece7bfbccf3aa02de8f1a624ecbf21a01e8b2f4a5854c231fbe218edd7762a34fea881f3958a215305",
+ "StakingPubKey": "ae8dcf81f3a70d72036b7ba2c586ed37ed0eb82b9c0a4aab998a8420f98894f94c14f84fa716e93654d3940fc0c8ff4d19b504c90a5b4918b28f421e9d3659dc2b7e246025ebeffea0d83cceefe315d7ed346dbe412fdac51b64997d97d29f7e"
+}
+```
+
+#### Example
+
+
+
+On the next screen, ensure that you stake 100 FLOW token.
+
+#### Example
+
+
+
+Submit the Transaction.
+
+## Step 3 - Verify That Your Node ID Was Selected
+
+On Wednesday at around 12:00 UTC, the staking auction for the current epoch will end and five nodes from candidate list of nodes will be chosen at random by the staking contract to be part of the next epoch.
+
+:::note
+
+If all 5 slots have been taken from the previous epoch, then no new access nodes will be chosen (see #limitations)
+
+:::
+
+There are several ways to verify whether your node was chosen as explained below.
+
+When you stake the node, the tokens will show up under the `tokensCommitted` bucket. After the staking auction ends, if the node is selected, the tokens remain in the `tokensCommitted` bucket and are moved to the `tokensStaked` bucket at the end of the epoch.
+If the node is not selected, the tokens are moved to the `tokensUnstaked` bucket.
+
+### Check Using Flow Port
+You can check these balances on Flow Port before and after the epoch transition that will occur on Wednesday (see [timing](#timing)).
+
+When you stake the node, you should see the following on Flow Port under `Stake & Delegate`
+
+
+
+After the epoch transition, if you see you token balance under the Staked Amount then your node got chosen.
+
+
+
+Instead, if you see that your token balance is under the Unstaked Amount, then your node did not get chosen.
+
+
+
+### Check Using Flow CLI
+
+You can also check these balance using [Flow Cli](https://github.com/onflow/flow-cli). Once you have downloaded and installed Flow Cli, you can query the account balance using the command,
+```shell
+flow accounts staking-info -n mainnet
+```
+
+For Example, the following node was chosen as Tokens staked is 100.
+
+```shell Example
+$ flow accounts staking-info 0xefdfb20806315bfa -n testnet
+
+Account staking info:
+ ID: "e737ec6efbd26ef43bf676911cdc5a11ba15fc6562d05413e6589fccdd6c06d5"
+ Initial Weight: 100
+ Networking Address: "flowaccess.mycompany.com:3569"
+ Networking Key: "f493a74704f6961ae7903e062ecd58d990672858eff99aece7bfbccf3aa02de8f1a624ecbf21a01e8b2f4a5854c231fbe218edd7762a34fea881f3958a215305"
+ Role: 5
+ Staking Key: "ae8dcf81f3a70d72036b7ba2c586ed37ed0eb82b9c0a4aab998a8420f98894f94c14f84fa716e93654d3940fc0c8ff4d19b504c90a5b4918b28f421e9d3659dc2b7e246025ebeffea0d83cceefe315d7ed346dbe412fdac51b64997d97d29f7e"
+ Tokens Committed: 0.00000000
+ Tokens To Unstake: 100.00000000
+ Tokens Rewarded: 0.00000000
+ Tokens Staked: 100.00000000
+ Tokens Unstaked: 0.00000000
+ Tokens Unstaking: 0.00000000
+ Node Total Stake (including delegators): 0.00000000
+```
+
+### Epoch Setup Event
+
+Alternatively, if you can monitor events, look for [the epoch setup event](../../staking/05-epoch-scripts-events.md#flowepochepochsetup) that gets emitted by the epoch contract. That event is emitted at the end of epoch N's staking auction and contains a list of node IDs that are confirmed for the next epoch.
+
+## Step 4 - Start Your Node
+
+If your node was selected as part of Step 3, you can now start your node.
+
+First you'll need to provision a machine or virtual machine to run your node software. Please see follow the [node-provisioning](../node-operation/node-provisioning.md) guide for it.
+
+The access node can be run as a Docker container with the following command.
+
+Be sure to set `$VERSION` below to the version tag (e.g. `v1.2.3`) corresponding to the latest **released** version [here](https://github.com/onflow/flow-go/releases) for version releases). Set `$NODEID` to your node's ID (see [Generate Your Node Identity](#generate-your-node-identity) section above).
+
+
+
+
+```shell
+docker run --rm \
+-v $PWD/bootstrap:/bootstrap:ro \
+-v $PWD/data:/data:rw \
+--name flow-go \
+--network host \
+gcr.io/flow-container-registry/access:$VERSION \
+--nodeid=$NODEID \
+--bootstrapdir=/bootstrap \
+--datadir=/data/protocol \
+--secretsdir=/data/secrets \
+--rpc-addr=0.0.0.0:9000 \
+--http-addr=0.0.0.0:8000 \
+--rest-addr=0.0.0.0:80 \
+--rpc-metrics-enabled=true \
+--bind 0.0.0.0:3569 \
+--dynamic-startup-access-address=secure.mainnet.nodes.onflow.org:9001 \
+--dynamic-startup-access-publickey=28a0d9edd0de3f15866dfe4aea1560c4504fe313fc6ca3f63a63e4f98d0e295144692a58ebe7f7894349198613f65b2d960abf99ec2625e247b1c78ba5bf2eae \
+--dynamic-startup-epoch-phase=EpochPhaseStaking \
+--loglevel=error
+```
+
+
+
+
+```shell
+docker run --rm \
+-v $PWD/bootstrap:/bootstrap:ro \
+-v $PWD/data:/data:rw \
+--name flow-go \
+--network host \
+gcr.io/flow-container-registry/access:$VERSION \
+--nodeid=$NODEID \
+--bootstrapdir=/bootstrap \
+--datadir=/data/protocol \
+--secretsdir=/data/secrets \
+--rpc-addr=0.0.0.0:9000 \
+--http-addr=0.0.0.0:8000 \
+--rest-addr=0.0.0.0:80 \
+--rpc-metrics-enabled=true \
+--bind 0.0.0.0:3569 \
+--dynamic-startup-access-address=secure.testnet.nodes.onflow.org:9001 \
+--dynamic-startup-access-publickey=ba69f7d2e82b9edf25b103c195cd371cf0cc047ef8884a9bbe331e62982d46daeebf836f7445a2ac16741013b192959d8ad26998aff12f2adc67a99e1eb2988d \
+--dynamic-startup-epoch-phase=EpochPhaseStaking \
+--loglevel=error
+```
+
+
+
+
+For example, if your Node ID is `e737ec6efbd26ef43bf676911cdc5a11ba15fc6562d05413e6589fccdd6c06d5` and the software version is `v1.2.3`, the Docker command would be the following:
+```shell Example
+docker run --rm \
+ -v $PWD/bootstrap:/bootstrap:ro \
+ -v $PWD/data:/data:rw \
+ --name flow-go \
+ --network host \
+ gcr.io/flow-container-registry/access:v1.2.3 \
+ --nodeid=e737ec6efbd26ef43bf676911cdc5a11ba15fc6562d05413e6589fccdd6c06d5 \
+ --bootstrapdir=/bootstrap \
+ --datadir=/data/protocol \
+ --secretsdir=/data/secrets \
+ --rpc-addr=0.0.0.0:9000 \
+ --http-addr=0.0.0.0:8000 \
+ --rest-addr=0.0.0.0:80 \
+ --rpc-metrics-enabled=true \
+ --bind 0.0.0.0:3569 \
+ --dynamic-startup-access-address=secure.mainnet.nodes.onflow.org:9001 \
+ --dynamic-startup-access-publickey=28a0d9edd0de3f15866dfe4aea1560c4504fe313fc6ca3f63a63e4f98d0e295144692a58ebe7f7894349198613f65b2d960abf99ec2625e247b1c78ba5bf2eae \
+ --dynamic-startup-epoch-phase=EpochPhaseStaking \
+ --loglevel=error
+```
+
+> If you would like your node to sync from the start of the last network upgrade, then please see the instructions [here](https://developers.flow.com/networks/node-ops/node-operation/spork)
+
+Alternatively, you can build a binary for the access node to run it without using Docker.
+To build the access node binary, see the instructions [here](https://github.com/onflow/flow-go?tab=readme-ov-file#building-a-binary-for-the-access-node).
+Please make sure to git checkout the latest release tag before building the binary.
+
+
+
+
+```shell
+$PWD/flow-go/flow_access_node \
+--nodeid=e1a8b231156ab6f2a5c6f862c933baf5e5c2e7cf019b509c7c91f4ddb0a13398 \
+--bootstrapdir=$PWD/bootstrap \
+--datadir=$PWD/data/protocol \
+--secretsdir=$PWD/data/secrets \
+--execution-data-dir=$PWD/data/execution_data \
+--rpc-addr=0.0.0.0:9000 \
+--secure-rpc-addr=0.0.0.0:9001 \
+--http-addr=0.0.0.0:8000 \
+--rest-addr=0.0.0.0:8070 \
+--admin-addr=localhost:9002 \
+--bind=0.0.0.0:3569 \
+--dht-enabled=false \
+--grpc-compressor=gzip \
+--profiler-dir=$PWD/data/profiler \
+--dynamic-startup-access-address=secure.mainnet.nodes.onflow.org:9001 \
+--dynamic-startup-access-publickey=28a0d9edd0de3f15866dfe4aea1560c4504fe313fc6ca3f63a63e4f98d0e295144692a58ebe7f7894349198613f65b2d960abf99ec2625e247b1c78ba5bf2eae \
+--dynamic-startup-epoch-phase=EpochPhaseStaking
+```
+
+
+
+
+```shell
+$PWD/flow-go/flow_access_node \
+--nodeid=e1a8b231156ab6f2a5c6f862c933baf5e5c2e7cf019b509c7c91f4ddb0a13398 \
+--bootstrapdir=$PWD/bootstrap \
+--datadir=$PWD/data/protocol \
+--secretsdir=$PWD/data/secrets \
+--execution-data-dir=$PWD/data/execution_data \
+--rpc-addr=0.0.0.0:9000 \
+--secure-rpc-addr=0.0.0.0:9001 \
+--http-addr=0.0.0.0:8000 \
+--rest-addr=0.0.0.0:8070 \
+--admin-addr=localhost:9002 \
+--bind=0.0.0.0:3569 \
+--dht-enabled=false \
+--grpc-compressor=gzip \
+--profiler-dir=$PWD/data/profiler \
+--dynamic-startup-access-address=secure.testnet.nodes.onflow.org:9001 \
+--dynamic-startup-access-publickey=ba69f7d2e82b9edf25b103c195cd371cf0cc047ef8884a9bbe331e62982d46daeebf836f7445a2ac16741013b192959d8ad26998aff12f2adc67a99e1eb2988d \
+--dynamic-startup-epoch-phase=EpochPhaseStaking
+```
+
+
+
+
+For a more mature setup, it is recommended that you run the container using systemd as described [here](../node-operation/node-setup.md#systemd)
+
+> 🚀 The access node should now be up and running, and you should be able to query the node using Flow CLI or curl,
+
+```shell Example
+flow blocks get latest --host localhost:9000
+```
+
+```shell Example
+curl http://localhost/v1/blocks?height=sealed
+```
+
+## Monitoring and Metrics
+
+The node publishes several Prometheus metrics. See [Monitoring Node Health](../node-operation/monitoring-nodes.md) to setup node monitoring.
+
+### Node Status
+
+The metrics for the node should be able to provide a good overview of the status of the node. If we want to get a quick snapshot of the status of the node, and if it's properly participating in the network, you can check the `consensus_compliance_finalized_height` or `consensus_compliance_sealed_height` metric, and ensure that it is not zero and strictly increasing.
+
+```shell
+curl localhost:8080/metrics | grep consensus_compliance_sealed_height
+
+# HELP consensus_compliance_sealed_height the last sealed height
+# TYPE consensus_compliance_sealed_height gauge
+consensus_compliance_sealed_height 1.132054e+06
+```
+
+## FAQs
+
+### Will the access node receive rewards?
+
+No, the access nodes do not receive any rewards.
+
+### Why is there a 100 FLOW token minimum?
+
+As mentioned in the [FLIP](https://github.com/onflow/flips/blob/main/protocol/20220719-automated-slot-assignment.md), the minimum is required to prevent certain vulnerabilities
+in the smart contract that are a result of having a zero minimum stake requirement.
+
+### Can the Access node be unstaked?
+
+Yes, like any other staked node, the Access node can be unstaked. The staked tokens will be moved to the unstaked bucket in the subsequent epoch.
+
+### How to see all the access nodes that have staked?
+
+When the nodes are initially staked, they are all added to the candidate list of nodes before the end of the epoch staking phase.
+The list can be retrieved from the chain by executing the [get_candidate_nodes](https://github.com/onflow/flow-core-contracts/blob/48ba17d3386023d70817197a20effbc5d16339b3/transactions/idTableStaking/scripts/get_candidate_nodes.cdc) script which returns the candidate list for the current epoch.
+
+```shell
+$ flow scripts execute ./transactions/idTableStaking/scripts/get_candidate_nodes.cdc -n mainnet
+```
+
+### How to check the availability of open access nodes slots for the next epoch?
+
+The limits for the open slots are defined in the staking contract and can be queried from the chain by executing the [get_slot_limits](https://github.com/onflow/flow-core-contracts/blob/master/transactions/idTableStaking/scripts/get_slot_limits.cdc) script.
+
+Node types are defined [here](https://github.com/onflow/flow-core-contracts/blob/5696ec5e3e6aa5fc10762cbfeb42b9c5c0b8ddbe/contracts/FlowIDTableStaking.cdc#L114-L119)
+
+```shell
+
+$ flow scripts execute ./transactions/idTableStaking/scripts/get_slot_limits.cdc --args-json '[{ "type":"UInt8", "value":"5"}]' -n mainnet
+Result: 118
+```
+
+Example: there are 115 access nodes already part of the network. Hence, the total number of new nodes that can join are 118 - 115 = 3.
+
+
+=== networks/node-ops/access-nodes/access-node-configuration-options.md ===
+---
+title: Serving execution data
+sidebar_label: Execution Data
+sidebar_position: 2
+---
+
+Flow chain data comprises of two parts,
+1. Protocol state data - This refers to the blocks, collection, transaction that are being continuously added to the chain.
+2. Execution state data - This refers to what makes up the execution state and includes transaction events and account balances.
+
+The access node by default syncs the protocol state data and has been now updated to also sync the execution state data.
+This guide provides an overview of how to use the execution data sync feature of the Access node.
+
+
+
+⚠️ Nodes MUST be running `v0.32.10+` or newer to enable execution data indexing.
+
+
+
+## Setup node’s directory
+
+The access node typically has the following directory structure:
+
+```bash
+$ tree flow_access
+ flow_access/
+ ├── bootstrap
+ │ ├── private-root-information (with corresponding AN data)
+ │ └── execution-state
+ │ └── public-root-information
+ │ ├── node-id
+ │ └── node-info.pub.NODE_ID.json
+ │ └── root-protocol-state-snapshot.json (the genesis data)
+ └── data (directory used by the node to store block data)
+ │ └── execution-data
+ │ └── execution-state
+
+```
+
+## Setup execution data indexing
+
+First, your node needs to download and index the execution data. There are 3 steps:
+
+1. Enable Execution Data Sync
+2. Download the root checkpoint file
+3. Configure the node to run the indexer
+4. Use the indexed data in the Access API.
+
+As of **`mainnet24`** / **`devnet49`**, Access nodes can be configured to index execution data to support local script execution, and serving all of the Access API endpoints using local data. There are different setup procedures depending on if you are enabling indexing immediately after a network upgrade, or at some point between upgrades.
+
+# Enable Execution Data Sync
+
+This is enabled by default, so as long as you didn’t explicitly disable it, the data should already be available.
+
+1. Make sure that either `--execution-data-sync-enabled` is not set, or is set to `true`
+2. Make sure that you have a path configured for `--execution-data-dir`, otherwise the data will be written to the running user’s home directory, which is most likely inside the container’s volume. For example, you can create a folder within the node’s data directory `/data/execution-data/`.
+
+There are some additional flags available, but you most likely do not need to change them.
+
+## **Option 1: Enabling Indexing at the Beginning of a Spork**
+
+### Download the root protocol state snapshot
+
+The `root-protocol-state-snapshot.json` is generated for each [spork](https://developers.flow.com/networks/node-ops/node-operation/spork) and contains the genesis data for that spork. It is published and made available after each spork. The download location is specified [here](https://github.com/onflow/flow/blob/master/sporks.json) under [rootProtocolStateSnapshot](https://github.com/onflow/flow/blob/master/sporks.json#L16).
+
+Store the **`root-protocol-state-snapshot.json`** into the **`/bootstrap/public-root-information/`** folder.
+
+### Download the root checkpoint
+
+The root checkpoint for the network is used by Execution nodes and Access nodes to bootstrap their local execution state database with a known trusted snapshot. The checkpoint contains 18 files that make up the merkle trie used to store the blockchain’s state.
+
+The root checkpoint for each spork is hosted in GCP. You can find the link for the specific network in the [`sporks.json`](https://github.com/onflow/flow/blob/master/sporks.json) file. Here’s the URL for `mainnet24`:
+
+[https://github.com/onflow/flow/blob/52ee94b830c2d413f0e86c1e346154f84c2643a4/sporks.json#L15](https://github.com/onflow/flow/blob/52ee94b830c2d413f0e86c1e346154f84c2643a4/sporks.json#L15)
+
+The URL in that file will point to a file named `root.checkpoint`. This is the base file and is fairly small. There are 17 additional files that make up the actual data, named `root.checkpoint.000`, `root.checkpoint.001`, …, `root.checkpoint.016`. If you have `gsutil` installed, you can download them all easily with the following command.
+
+```bash
+gsutil -m cp "gs://flow-genesis-bootstrap/[network]-execution/public-root-information/root.checkpoint*" .
+```
+
+Where `[network]` is the network you are downloading for. For example, `mainnet-24` or `testnet-49`.
+
+Once the files are downloaded, you can either move them to `/bootstrap/execution-state/` within the node’s bootstrap directory or put them in any mounted directory and reference the location with this cli flag: `--execution-state-checkpoint=/path/to/root.checkpoint`. The naming of files should be `root.checkpoint.*`.
+
+## **Option 2: Enabling Indexing Mid-Spork**
+
+### Identify the root checkpoint
+
+The root checkpoint for the network is used by Execution and Access nodes to bootstrap their local execution state database with a known trusted snapshot. The checkpoint contains 18 files that make up the merkle trie used to store the blockchain’s state.
+
+Root checkpoints are periodically generated on Flow Foundation execution nodes and uploaded to a GCP bucket. You can see
+a list of available checkpoints [here](https://console.cloud.google.com/storage/browser/flow-genesis-bootstrap/checkpoints),
+or list them using the [gsutil](https://cloud.google.com/storage/docs/gsutil) command
+
+```bash
+gsutil ls "gs://flow-genesis-bootstrap/checkpoints/"
+```
+
+The checkpoint paths are in the format `flow-genesis-bootstrap/checkpoints/[network]/[epoch number]-[block height]/`.
+Where
+* `[network]` is the network the checkpoint is from. For example, `mainnet` or `testnet`.
+* `[epoch number]` is the epoch number when the checkpoint was taken. You can find the current epoch number on the [flowscan.io](https://flowscan.io/) home page.
+* `[block height]` is the block height at which the checkpoint was taken.
+Make sure that the checkpoint you select is from an epoch when your node was part of the network.
+
+### Download the root checkpoint
+
+Once you have selected the checkpoint to download, you can download the files. If you have `gsutil` installed, you can download them all easily with the following command.
+
+```bash
+gsutil -m cp "gs://flow-genesis-bootstrap/checkpoints/[network]/[epoch number]-[block height]/root.checkpoint*" .
+```
+
+Once the files are downloaded, you can either move them to `/bootstrap/execution-state/` within the node’s bootstrap directory or put them in any mounted directory and reference the location with this cli flag: `--execution-state-checkpoint=/path/to/root.checkpoint`. The naming of files should be `root.checkpoint*`.
+
+### Download the root protocol state snapshot
+
+Access nodes require that the data in the root checkpoint corresponds to the root block in the `root-protocol-state-snapshot.json` file.
+It's important to download the snapshot for the correct height, otherwise bootstrapping will fail with an error described in the Troubleshooting section.
+
+You can download the `root-protocol-state-snapshot.json` file generated by the Execution from the same GCP bucket.
+
+```bash
+gsutil cp "gs://flow-genesis-bootstrap/checkpoints/[network]/[epoch number]-[block height]/root-protocol-state-snapshot.json" .
+```
+
+Alternatively, you can download it directly from a trusted Access node using the `GetProtocolStateSnapshotByHeight` gRPC endpoint
+with the corresponding height. You will get a `base64` encoded snapshot which decodes into a json object. At this time, this endpoint is only support using the grpc API.
+
+Store the **`root-protocol-state-snapshot.json`** into the **`/bootstrap/public-root-information/`** folder.
+
+
+# Configure the node to run the indexer
+
+Now you have the execution sync setup and the root checkpoint in place, it’s time to configure the node to index all of the data so it can be used for script execution.
+
+There are 2 cli flags that you will need to add:
+
+- `--execution-data-indexing-enabled=true` This will enable the indexer.
+- `--execution-state-dir` This defines the path where the registers db will be stored. A good default is on the same drive as the protocol db. e.g. `/data/execution-state`
+
+
+# Start your node
+
+Now that all of the settings to enable indexing are in place, you can start your node.
+
+At a minimum, you will need the following flags:
+
+```
+--execution-data-indexing-enabled=true
+--execution-state-dir=/data/execution-state
+--execution-data-sync-enabled=true
+--execution-data-dir=/data/execution-data
+```
+
+For better visibility of the process, you can also add
+
+`-p 8080:8080` - export port 8080 from your docker container, so you could inspect the metrics
+
+`--loglevel=info` - for checking logs.
+
+Notes on what to expect:
+
+- On startup, the node will load the checkpoint into the `execution-state` db. For `devnet48`, this takes 20-30 min depending on the node’s specs. For `mainnet24`, it takes >45 min. The loading time will increase over time. You can follow along with the process by grepping your logs for `register_bootstrap`.
+- After the checkpoint is loaded, the indexer will begin ingesting the downloaded execution data. This will take several hours to days depending on if the data was already downloaded and the hardware specs of the node.
+- If your node already had all the data, it will index all of it as quickly as possible. This will likely cause the node to run with a high CPU.
+
+When you restart the node for the first time with syncing enabled, it will sync execution data for all blocks from the network.
+
+# Use the indexed data in the Access API
+
+### Setup Local Script Execution
+
+Local execution is controlled with the `--script-execution-mode` flag, which can have one of the following values:
+
+- `execution-nodes-only` (default): Requests are executed using an upstream execution node.
+- `failover` (recommended): Requests are executed locally first. If the execution fails for any reason besides a script error, it is retried on an upstream execution node. If data for the block is not available yet locally, the script is also retried on the EN.
+- `compare`: Requests are executed both locally and on an execution node, and a comparison of the results and errors are logged.
+- `local-only`: Requests are executed locally and the result is returned directly.
+
+There are a few other flags available to configure some limits used while executing scripts:
+
+- `--script-execution-computation-limit`: Controls the maximum computation that can be used by a script. The default is `100,000` which is the same as used on ENs.
+- `--script-execution-timeout`: Controls the maximum runtime for a script before it times out. Default is `10s`.
+- `--script-execution-max-error-length`: Controls the maximum number of characters to include in script error messages. Default is `1000`.
+- `--script-execution-log-time-threshold`: Controls the run time after which a log message is emitted about the script. Default is `1s`.
+- `--script-execution-min-height`: Controls the lowest block height to allow for script execution. Default: `no limit`.
+- `--script-execution-max-height`: Controls the highest block height to allow for script execution. Default: `no limit`.
+- `--register-cache-size`: Controls the number of registers to cache for script execution. Default: `0 (no cache)`.
+
+### Setup Using Local Data with Transaction Results and Events
+
+Local data usage for transaction results and events are controlled with the `--tx-result-query-mode` and `--event-query-mode` corresponding flags, which can have one of the following values:
+
+- `execution-nodes-only` (default): Requests are forwarded to an upstream execution node.
+- `failover` (recommended): - `failover` (recommended): Requests are handled locally first. If the processing fails for any reason, it is retried on an upstream execution node. If data for the block is not available yet locally, the script is also retried on the EN.
+- `local-only`: Requests are handled locally and the result is returned directly.
+
+# Troubleshooting
+
+- If the root checkpoint file is missing or invalid, the node will crash. It must be taken from the same block as the `root-protocol-state-snapshot.json` used to start your node.
+- If you don’t set one the `--execution-data-dir` and `--execution-state-dir` flags, the data will be written to the home directory inside the container (likely `/root`). This may cause your container to run out of disk space and crash, or lose all data each time the container is restarted.
+- If your node crashes or restarts before the checkpoint finishes loading, you will need to stop the node, delete the `execution-state` directory, and start it again. Resuming is currently not supported.
+- If you see the following message then your `checkpoint` and `root-protocol-state-snapshot` are not for the same height.
+
+```json
+{
+ "level":"error",
+ ...
+ "module":"execution_indexer",
+ "sub_module":"job_queue",
+ "error":"could not query processable jobs: could not read job at index 75792641, failed to get execution data for height 75792641: blob QmSZRu2SHN32d9SCkz9KXEtX3M3PozhzksMuYgNdMgmBwH not found",
+ "message":"failed to check processables"
+}
+```
+
+- You can check if the execution sync and index heights are increasing by querying the metrics endpoint:
+ ```
+ curl localhost:8080/metrics | grep highest_download_height
+ curl -s localhost:8080/metrics | grep highest_indexed_height
+ ```
+
+# Execution Data Sync
+
+The Execution Sync protocol is enabled by default on Access nodes, and uses the bitswap protocol developed by Protocol Labs to share data trustlessly over a peer-to-peer network. When enabled, nodes will download execution data for each block as it is sealed, and contribute to sharing the data with its peers. The data is also made available to systems within the node, such as the `ExecutionDataAPI`.
+
+Below is a list of the available CLI flags to control the behavior of Execution Sync requester engine.
+
+| Flag | Type | Description |
+| --- | --- | --- |
+| execution-data-sync-enabled | bool | Whether to enable the execution data sync protocol. Default is true |
+| execution-data-dir | string | Directory to use for Execution Data database. Default is in the user’s home directory. |
+| execution-data-start-height | uint64 | Height of first block to sync execution data from when starting with an empty Execution Data database. Default is the node’s root block. |
+| execution-data-max-search-ahead | uint64 | Max number of heights to search ahead of the lowest outstanding execution data height. This limits the number non-consecutive objects that will be downloaded if an earlier block is unavailable. Default is 5000. |
+| execution-data-fetch-timeout | duration | Initial timeout to use when fetching execution data from the network. timeout increases using an incremental backoff until execution-data-max-fetch-timeout. Default is 10m. |
+| execution-data-max-fetch-timeout | duration | Maximum timeout to use when fetching execution data from the network. Default is 10s |
+| execution-data-retry-delay | duration | Initial delay for exponential backoff when fetching execution data fails. Default is 1s |
+| execution-data-max-retry-delay | duration | Maximum delay for exponential backoff when fetching execution data fails. Default is 5m |
+
+
+ℹ️ Note: By default, execution data is written to the home directory of the application user. If your node is running in docker, this is most likely in the container’s volume. Depending on how you configure your node, this may cause the node’s boot disk to fill up.
+
+As a best practice, specify a path with `--execution-data-dir`. A sensible default is to put it within the same directory as `--datadir`. e.g. `--execution-data-dir=/data/execution_data`.
+
+
+
+# Execution Data Indexer
+
+Below is a list of the available CLI flags to control the behavior of Execution Data Indexer.
+
+| Flag | Type | Description |
+| --- | --- | --- |
+| execution-data-indexing-enabled | bool | Whether to enable the execution data indexing. Default is false |
+| execution-state-dir | string | Directory to use for execution-state database. Default is in the user’s home directory. |
+| execution-state-checkpoint | string | Location of execution-state checkpoint (root.checkpoint.*) files. |
+| event-query-mode | string | Mode to use when querying events. one of [local-only, execution-nodes-only(default), failover] |
+| tx-result-query-mode | string | Mode to use when querying transaction results. one of [local-only, execution-nodes-only(default), failover] |
+
+Below is a list of the available CLI flags to control the behavior of Script Execution.
+
+| Flag | Type | Description |
+| --- | --- | --- |
+| script-execution-mode | string | Mode to use when executing scripts. one of [local-only, execution-nodes-only, failover, compare ] |
+| script-execution-computation-limit | uint64 | Maximum number of computation units a locally executed script can use. Default: 100000 |
+| script-execution-max-error-length | int | Maximum number characters to include in error message strings. additional characters are truncated. Default: 1000 |
+| script-execution-log-time-threshold | duration | Emit a log for any scripts that take over this threshold. Default: 1s |
+| script-execution-timeout | duration | The timeout value for locally executed scripts. Default: 10s |
+| script-execution-min-height | uint64 | Lowest block height to allow for script execution. Default: no limit |
+| script-execution-max-height | uint64 | Highest block height to allow for script execution. default: no limit |
+| register-cache-type | string | Type of backend cache to use for registers [lru, arc, 2q] |
+| register-cache-size | uint | Number of registers to cache for script execution. Default: 0 (no cache) |
+| program-cache-size | uint | [experimental] number of blocks to cache for cadence programs. use 0 to disable cache. Default: 0. Note: this is an experimental feature and may cause nodes to become unstable under certain workloads. Use with caution. |
+
+# Resources
+
+FLIP: [https://github.com/onflow/flips/blob/main/protocol/20230309-accessnode-event-streaming-api.md](https://github.com/onflow/flips/blob/main/protocol/20230309-accessnode-event-streaming-api.md)
+
+Protobuf: [https://github.com/onflow/flow/blob/master/protobuf/flow/executiondata/executiondata.proto](https://github.com/onflow/flow/blob/master/protobuf/flow/executiondata/executiondata.proto)
+
+=== networks/network-architecture/user-safety.md ===
+---
+title: User safety
+sidebar_label: User safety
+sidebar_position: 4
+---
+
+# User Safety with Flow
+
+The monolithic node design of common L1s such as Bitcoin and Ethereum overly privileges operator control over block production.
+This makes the chain vulnerable to censorship and MEV attacks. This problem is exacerbated by L2s with centralized sequencers. ERC-4337 is also susceptible to MEV on the user operations via bundlers.
+
+
+
+Flow’s multi-role architecture provides censorship & MEV resistance by design:
+- Transactions are randomly assigned to collection nodes for inclusion in collections and eventually in blocks. Each collection node only sees a subset of transactions.
+
+
+- There is already a distinct separation between the proposers (represented by the collection nodes) and the builders (represented by the consensus nodes). This separation essentially provides an inherent implementation of "proposer-builder separation," a concept currently being explored by Ethereum. With this separation, even if the collection nodes were to reorder the transactions, there is no incentive for the consensus nodes to prefer one collection node’s proposal over another.
+
+
+
+
+=== networks/network-architecture/sustainability.md ===
+---
+title: Sustainability
+sidebar_label: Sustainability
+sidebar_position: 3
+---
+
+# Sustainability with Flow
+
+It's no secret that Proof of Stake blockchains are better for the environment.
+As Web3 becomes more widely adopted, we engaged with Deloitte Canada to validate how much energy it uses.
+And the results are astounding: Flow uses just 0.18 GWh annually, based on 2021 usage – or in simpler terms, minting an NFT on Flow takes less energy than a Google search or Instagram post.
+
+
+In addition to operating on a Proof of Stake consensus system, Flow’s multi-role node architecture securely divides the processing between specialized node types, making the network significantly more efficient than other blockchain architectures.
+As network usage grows, vertical scaling is only needed for the execution nodes (as they execute transactions and persist all the chain state).
+Because the increase in energy and hardware consumption over time is restricted to a small subset of the nodes in the network, this drastically limits the environmental footprint of the chain.
+
+The overall energy use of the network won’t increase significantly even if the activity increases by 100x or more, making the per-transaction energy footprint decrease over time.
+
+Read more about it [here](https://flow.com/post/flow-blockchain-sustainability-energy-deloitte-report-nft).
+
+=== networks/network-architecture/solving-blockchain-trilemma.md ===
+---
+title: Solving the blockchain trilemma
+sidebar_label: Solving the blockchain trilemma
+sidebar_position: 2
+---
+
+# Solving the blockchain trilemma
+
+In a monolithic architecture, all nodes perform every task. As network usage grows, the transaction processing capacity of the individual nodes becomes a limiting factor, restricting the network’s throughput and latency. The amount of data that can be stored on-chain is limited since nodes have a finite storage capacity. The only way to scale monolithic blockchains is by increasing the capacity of each node by adding more CPU, memory, and storage (i.e. vertical scaling, an approach taken by Solana). However, this solution comes at the cost of decentralization. As nodes scale vertically, they become more expensive to run, and eventually, only a few operators can afford to run such high-performance, high-capacity nodes. Worse, energy consumption for every node in the network increases over time, making the chain environmentally unsustainable.
+
+Through its multi-role architecture, Flow implements a modular pipeline for processing transactions. This design allows the network to scale by tuning the level of decentralization at each specific step without sharding the state and fragmenting the network into smaller security zones.
+
+The modular pipeline is composed of Collection, Consensus, Execution and Verification Nodes.
+
+
+
+
+## Separating Consensus from Compute
+
+At a high level, the pipeline essentially separates consensus from transaction computation. Non-deterministic (or “subjective”) processes such as determining the inclusion and order of transactions are decided by the broadly decentralized consensus committee. The deterministic (or “objective”) task of computing the result of those ordered transactions is done independently by a small number of specialized execution nodes.
+
+Collection and consensus are highly decentralized and achieve high levels of redundancy through a large number of lightweight, cost-effective nodes, numbering in the thousands, operated by several hundred different operators. These steps guarantee resilient transaction ordering (assuming that a malicious actor can only compromise a limited number of nodes).
+
+In comparison, transaction execution has low decentralization and redundancy (10 or less) with more powerful and expensive nodes. To accommodate for the anticipated growth of on-chain state without sharding, only the execution nodes have to be scaled vertically. All other node types can continue to run low-cost hardware. The execution nodes may eventually be scaled up to small data centers.
+
+
+
+Low decentralization for transaction execution might appear to compromise decentralization of the whole network, as it is conceivable that a malicious actor might compromise a dominant fraction of nodes participating in execution. However, correctness of the transaction results is still guaranteed by the verification step, which also requires reasonably high redundancy, again with a large number of lighter and less expensive verification nodes to withstand compromisation attempts.
+
+Every node in Flow makes the protocol stronger, and the network can grow as needed to achieve different objectives:
+- More censorship resistance? Add more collection nodes
+- More decentralized block production? Add more consensus nodes
+- Need to accommodate higher transaction throughput and state storage? Scale up execution nodes
+- Do node operators want to reinforce network security with modest node hardware and low stake? Add more verification nodes.
+- Need access to chain data locally? Add access nodes.
+
+In contrast, when traditional Layer 1 blockchains add more nodes to increase decentralization, they do so without providing any additional benefits.
+
+
+
+> Flow’s architectural goals are to provide a throughput of at least 1M TPS, ingest at least ½ GB of transaction data per second and store and serve a very large state of one Patebyte and beyond.
+
+Thus, Flow’s multi-role architecture solves the blockchain trilemma:
+
+1. **Scalability**: Scale to thousands of times higher throughput and on-chain storage capacity.
+
+2. **Decentralization**: Except for the execution nodes, all nodes are light weight and low cost, lowering the barrier to entry and ensuring participation from a diverse set of node operators—big and small
+
+3. **Security**: Maintain a shared non-sharded execution environment for all operations on the network and use a secure in-built platform to build on.
+
+
+
+=== networks/network-architecture/index.md ===
+---
+title: Flow's Network Architecture
+sidebar_position: 1
+---
+
+Flow has pioneered a new paradigm of multi-role architecture that solves the core problem of today’s blockchains.
+The result is a scalable, decentralized, and secure network which ensures user safety and long-term sustainability.
+
+
+
+
+
+
+
+To better understand the architecture, lets first understand the problems with the current blockchain. Then lets look at how Flow multi-role architecture solves these problems.
+
+# What are the biggest problems solved by Flow's Multi-role Architecture?
+
+## 1. The blockchain trilemma
+
+A blockchain should be fully decentralized, highly scalable and extremely secure. However a well-known problem with all blockchain is the blockchain trilemma - optimizing for any one edge comes at the cost of the other two.
+
+You can have a chain that is decentralized and secure but not scalable e.g. Bitcoin and Ethereum or you can have a chain that is scalable and secure but not as decentralized e.g. Solana, Aptos and Sui.
+While multi-chain systems like Cosmos, Layer 2 solutions (L2s) like Polygon, and cross-chain bridges offer innovative approaches to address these challenges, they divide the trust into separate and independent security zones and such zones with fewer validators can be more vulnerable to attacks and therefore less secure.
+
+
+
+## 2. Disadvantaging end-users
+Most blockchains, regardless of the number of participating nodes, inherently disadvantage individual end-users. This is because (colluding) nodes can censor user transactions or unfairly extract value from users in a phenomenon commonly known as Miner Extractable Value [MEV]. As a result, individual end users can end up paying an “invisible tax” or otherwise seeing their transactions fail due to MEV.
+
+
+## 3. Energy inefficient and unsustainable
+It is well established that Proof-of-Work chains like Bitcoin consume massive amounts of energy, require perpetual hardware upgrades for the miners to stay competitive, and are therefore extremely harmful to the environment. A Proof-of-Stake chain’s environmental impact is less severe, but as web3 applications achieve mainstream adoption, every node in these chains will have to provide more and more hardware resources to meet the increasing throughput demand and the ever growing on-chain state. Vertically scaling the nodes implies higher energy consumption and environmental footprint.
+
+## Multi-role Architecture on Flow
+
+
+
+In first-generation smart contract blockchains like Ethereum and Bitcoin, every node in the network performs all of the work associated with processing every transaction (including the entire network’s history, account balances, smart contract code, etc.). While highly secure, it’s also incredibly inefficient, and does not scale throughput (transaction per second, transaction latency) and capacity (on-chain data storage).
+
+Most second-generation blockchain networks focus on improving performance in one of two ways:
+
+1. They compromise decentralization by requiring that participating nodes run on powerful servers (e.g. Solana); or
+2. They dramatically increase smart developer complexity by breaking up the network through mechanisms such as sharding (e.g. L2s such as Polygon).
+
+The first approach is vulnerable to platform risk and cartel-like behavior. The second approach outsources the challenges of scaling the platform, effectively handing off the complexities of bridging the different strongly-federated ecosystems to application developers.
+
+Flow offers a new path: pipelining applied to blockchain networks.
+
+Pipelining is a well-established technique across various fields, from manufacturing to CPU design, for significantly increasing productivity.
+Flow leverages this concept by distributing the tasks typically handled by a full node in a monolithic blockchain architecture across four specialized roles: Collection, Consensus, Execution, and Verification.
+This division of labor between nodes occurs within the different validation stages for each transaction, rather than distributing transactions across different nodes as is done with sharding.
+In other words, every Flow node still participates in the validation of every transaction, but they do so only at one of the stages of validation.
+They can therefore specialize—and greatly increase the efficiency—for their particular stage of focus.
+
+### Flow node roles and what they do
+
+| | Node type | Responsibility | What do the nodes of this role do? |
+|------------------------------------------|:--------------:|:--------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------|
+|  | Collection | Collection nodes act as a censorship-resistant data availability layer, which caches transactions for subsequent execution. | Collection nodes order transactions into batches known as collection. |
+|  | Consensus | The consensus committee serves as the security authority in the network and orchestrates Flow's transaction processing pipeline. | Consensus nodes order collections into blocks and commit execution results after verification. |
+|  | Execution | Execution nodes provide the computational resources for executing transactions and maintaining the state. | Execution nodes execute the transaction and record state changes. |
+|  | Verification | Verification nodes ensure that transactions are truthfully executed. | Verification nodes verify the work of the execution nodes. They either approve or disagree with their results, reporting their findings to the consensus nodes. |
+|  | Access | Access Nodes route transactions into the network and replicate (parts of) the state and transaction results for external clients to query. | Access node serve the API calls to send and read data from the chain. |
+
+### Further reading
+1. [Primer on multi-role architecture](https://flow.com/primer#primer-multinode)
+2. [Technical papers](https://flow.com/technical-paper)
+3. [Core protocol vision](https://flow.com/core-protocol-vision)
+4. [Medium article from Jan which deep dives into the Flow architecture](https://jan-bernatik.medium.com/introduction-to-flow-blockchain-7532977c8af8)
+
+In the next section, lets look at how Flow multi-role architecture solves those three big problems with blockchains.
+
+=== networks/flow-port/staking-guide.md ===
+---
+title: Flow Port Staking Guide
+---
+
+This guide provides step-by-step instructions for using the Flow Port to stake your FLOW tokens and start earning rewards.
+Currently, Flow Port only supports staking or delegating using tokens held in Blocto or Ledger wallets.
+If you're new to the concepts of staking and delegating you can [read this guide](../../networks/staking/index.md) to learn more.
+
+## First Step
+
+When you arrive in Port, select **Stake & Delegate** from the left-hand menu. You should be taken to this page.
+
+
+
+From here you can decide whether to stake or delegate.
+
+- Select **Stake** if you plan to stake a node you're running.
+- Select **Delegate** to delegate your stake to another Node Operator. You don't need to know which Node Operator, you'll be provided with a list to choose from. If you are not running your own node you scan skip directly to the [delegation section](#delegating)
+
+## Stake a Node
+
+Users who will be running their own nodes can stake them using the Flow Port.
+
+#### Prerequisites
+
+In order to stake your node, you'll need to have the required amount of FLOW for your node type.
+You'll also need the following information about your node:
+
+- Node ID
+- Network Address
+- Networking Key
+- Staking Key
+- Machine Account Public Key (for collection/consensus nodes only)
+
+If you don't have this information, go [here](../../networks/node-ops/node-operation/node-bootstrap.md#step-1---run-genesis-bootstrap) for instructions on how to acquire it.
+
+### Begin Staking
+
+First, select the type of node you'll be running by choosing from the list. You must have the required amount of locked FLOW in your account.
+
+
+
+Once you selected your node type, click next and specify how much you'd like to stake. The minimum amount for your node type is required,
+but you may stake as much as you like beyond that. Here's the screen you should see:
+
+
+
+Clicking next will take you to the final screen, where you'll need to enter information about your node you previously obtained.
+If you don't have this information, go [here](../../networks/node-ops/node-operation/node-bootstrap.md#step-1---run-genesis-bootstrap) for instructions on how to acquire it.
+Here's the screen you should see:
+
+
+
+Clicking next will take you to a confirmation screen. This is your chance to double-check that you've entered your information correctly. If you're ready, check the
+box confirming your information and click submit to send the transaction that will stake your node! You should see a transaction status screen like this:
+
+
+
+**Note:** If your transaction fails, double-check the information you provided.
+
+If you return to the home screen, you'll be able to see your staking request in progress!
+
+
+
+## Delegating
+
+Delegating is the process of staking your locked FLOW to nodes which are being run by another party.
+
+#### Prerequisites
+
+In order to delegate your stake to another node, you'll need to know the **node operator ID** of the operator who is running the nodes you wish to stake.
+Here is a list of node operator IDs you can delegate to: [List of Available Node Operators](https://github.com/onflow/flow/blob/master/nodeoperators/NodeOperatorList.md)
+
+### Enter a Node Operator ID
+
+Simply enter the ID of the node operator of your choice and click next.
+
+
+
+### Enter an amount
+
+Next you'll enter an amount of FLOW you would like to delegate. When delegating you may send any amount to the node operator.
+
+
+
+Click next to reach the confirmation screen. Confirm the details of your delegation request and click submit!
+
+
+
+Once your transaction is submitted, you can monitor its status from this screen, or return to the Flow Port home screen.
+
+
+
+**Note:** If you transaction fails, double-check the information you provided.
+
+That's it! You've successfully delegated stake to your chosen node operator!
+
+## Returning to Port
+
+Within Flow Port, navigate to the ‘Stake & Delegate’ page to see details about your existing staked and/or delegated tokens.
+This will also show you the rewards you have earned for your staked/delegated tokens.
+
+
+
+From here, you can do a few different things with your rewards:
+
+- You can choose to **re-stake** them to the associated node.
+- You can choose to **withdraw** them to your wallet.
+
+## Re-staking
+
+Flow Port will not automatically re-stake your rewards.
+To re-stake your rewards, simply hover your cursor over the 3 dots next to the rewards field:
+
+
+
+Click on the Restake option. This will take you to a screen that looks like the below. Input the amount of rewards you want to re-stake, acknowledge the transaction inputs and click submit:
+
+
+
+Once the transition is processed, you can reference the Stake & Delegate page again to see the pending stake now:
+
+
+
+## Withdraw your Rewards
+
+To withdraw your rewards, simply hover your cursor over the 3 dots next to the rewards field, and click on ‘Withdraw’.
+
+
+
+Input the amount that you want to withdraw to your wallet, acknowledge the transaction inputs and click submit:
+
+
+
+Once the transition is processed, you can now see the withdrawn rewards in your balance and you are now free to do other actions with them (send them to other accounts, delegate to a node, etc).
+
+
+=== networks/flow-port/index.md ===
+---
+title: Flow Port
+description: How to use Flow Port
+---
+
+Flow Port is an account management tool for Flow. Flow Port allows you to create an account using a wallet provider, manage your account and assets across Flow's VMs and perform staking and delegating actions on Flow.
+
+Typically, your wallet provider will support most of these features. However, should your wallet provider not do so, or should you wish to use this tool for any other reason, Flow Foundation makes it available for you.
+
+## Creating an Account
+In order to access Flow Port, you must have a valid Flow address. If you do not have a Flow address you can create one by installing a [Flow compatible wallet](../../ecosystem/wallets).
+
+### Flow Wallet
+
+#### Creating Account Through Flow Port: Navigate To Flow Port
+
+ 1. Using Google Chrome, Navigate to [Flow Port](https://port.onflow.org/).
+
+ 2. Click on 'Sign Up'
+
+ 3. Click on Flow Wallet and choose Chrome extension or Mobile
+
+ 4. You should be logged into Flow Port! You can now see your account address in Flow Port and access Flow features for your account
+
+### Ledger
+#### Before You Start
+
+ 1. Ensure you have:
+
+ - a.) [Ledger Live](https://www.ledger.com/ledger-live) installed on your computer
+
+ - b.) [Initialized](https://support.ledger.com/hc/en-us/articles/360017362160-Flow-FLOW-?support=true) your Ledger Device.
+
+#### Install the Flow App
+
+ 1. Connect your Ledger Device to your computer and open Ledger Live.
+
+ 2. Make sure your Ledger device firmware is up to date. You can check this by clicking on **‘Manager’** from the side navigation bar. Choose to install the update if one is available
+
+ - a.) NOTE: Sometimes the install option doesn't show up, or it is not clickable. If this is the case, wait for a little bit of time to see if it appears, or restart the ledger live app if necessary.
+
+ 3. On the Manager screen in Ledger Live and search for ‘Flow’.
+
+ 4. You should see the Flow App. Install it and follow the instructions on the device.
+
+ - a.) NOTE: If the Flow App does not appear, it may be because you are on an outdated version. Please ensure you are on the most updated version.
+
+#### Navigate to Flow Port to Create an Address
+
+ 1. Navigate to [Flow Port](https://port.onflow.org/).
+
+ 2. Click on 'Sign Up' if you need to create a new Flow Account.
+
+ 3. Click on Ledger.
+
+ 4. Follow the prompts on the screen. Plug in your Ledger device and open the Flow App.
+
+ 5. Click on Create an account. Follow the prompts on your Ledger device.
+
+ 6. Once your account address is created, you will be automatically logged into Flow Port.
+
+## Staking & Delegating
+
+For a detailed walkthrough on how to use Flow Port for staking and delegating, please read the [Flow Port staking walkthrough](./staking-guide.md)
+### How Do I Stake or Delegate?
+
+So you have decided you want to be a part of the Flow Network. Welcome! You are joining a group of people from all around the world that are a part of a movement centered around bringing decentralization, user empowerment, and transparency into the world. Below is a step-by-step guide that will assist you in the staking & delegation process.
+
+### Staking via a Custody Provider
+
+If you are using a custody provider who controls your account and private keys for you, such as Kraken, Finoa, or Coinlist, they all have different policies and processes for what you need to do to stake your tokens, the rewards you receive, and the fees that they take from your staking rewards.
+
+### Starting a Manual Staking Transaction
+ 1. You need to have FLOW in order to stake. Please see the [FLOW Token](../../build//core-contracts//03-flow-token.md) reference for information on how to become a FLOW holder.
+
+ 2. Once you have FLOW tokens in your account, you can start staking through [Flow Port](https://port.onflow.org/) or, if applicable, with your [custody provider](#staking-via-a-custody-provider).
+
+ 3. If you are using Flow Port, log-in with your Flow account address and navigate to the Stake/Delegate page. See the Manual Staking/Delegating section below for more information about what to do next.
+
+### Manual Staking/Delegating
+If you are not using a custody provider, there is more responsibility that you have to accept, because you have complete control of your tokens. You need to ensure that you are well informed about the staking process and potentially node operation process because you will have to manage those on your own. Please read the [staking documentation](../../networks/staking/index.md) before continuing with this guide.
+
+Below are the various options you can choose. Please be aware, that at this time you can only have 1 stake or 1 delegate per account. This means that if you want to do multiple stakes, multiple delegates, or a mixture of stakes and delegates, you will need to create multiple accounts to do so. Please read them carefully as it will help you understand which route is best for your situation:
+- Staking your own Node: You are responsible for running and maintaining a Flow Node. You are also solely responsible for providing the minimum stake for your selected node (minimum 135,000 FLOW) and you have the technical know-how and bandwidth to run and operate a node in the Flow protocol.
+- Delegating: You have FLOW tokens and you want to stake, without having to run your own node and/or have the full minimum stake required to run your own node. You can ‘delegate’ any amount of your FLOW tokens to an existing node operator and you will earn rewards.
+
+Please see a list [here](https://github.com/onflow/flow/blob/master/nodeoperators/NodeOperatorList.md) for all node operators that you can delegate to. This list will be updated as new node operators are onboarded onto the network.'
+
+### Staking Your Own Node
+ 1. Once you have navigated to the staking/delegating page in Flow Port, click on the 'Stake a Node' option.
+
+ 2. Next, select the type of node you will be running.
+
+ 3. Input the amount of Flow you wish to stake with that node. You must stake at least the minimum in order for your stake request to be successfully processed. You are able to provide the minimum stake across multiple transactions. Meaning, you could execute your stake transaction with half of the minumum required. Then, before the next epoch, you can choose to 'Add Flow' to that pending stake to get it to the minimum stake required.
+
+ 4. Run the [bootstrapping instructions](../../networks/node-ops/node-operation/node-bootstrap.md) and provide the remaining technical details needed to stake a node.
+
+### Delegating
+ 1. Once you have navigated to the staking/delegating page in Flow Port, click on the Delegate option.
+
+ 2. Next, you will specify which node operator you would like to delegate to and how many tokens you want to delegate to them.
+
+ 3. Execute the transaction. You will now see your pending delegation that will be processed during the next epoch.
+
+ 4. At this point, you can also cancel the pending delegation. On the pending delegation, you will see an `X` that you can click to initiate the cancelation transaction.
+
+## I Have Successfully Executed a Stake Transaction, Now What?
+ - Now that you have executed a stake transaction in either Flow Port or your custody provider’s portal, that transaction will sit in a pending status until it is processed, which will be at the next [Epoch](../../networks/staking/index.md#epochs) Date (which is currently weekly).
+ - During the next [Epoch](../../networks/staking/index.md#epochs), the transaction will be processed. If successful, the provided FLOW will be staked and the associated Node would be either **a)** included in the network protocol if it is a new node or **b)** continue to operate as is in the network protocol.
+ - You are now a part of Flow, and will begin to earn rewards for being a valued member of the network!
+
+## What Else Can I Do?
+ - Add additional stake to your existing stake. Any added FLOW will again sit in a pending status and be processed at the next epoch.
+ - Withdraw/re-stake your earned rewards. If you decide to withdraw your rewards, this action will happen instantly. If you decide to re-stake your rewards, the request will again sit in a pending status and will be processed at the next [Epoch](../../networks/staking/index.md#epochs).
+ - Withdraw Rewards and send your earnings to other accounts. If you decide that you want to withdraw your rewards and send those earnings to other accounts via the 'Send FLOW' function, you should first withdraw your rewards. Once in your account, you can send these funds to any other account via the 'Send FLOW' option.
+ - Request to be unstaked from the network. The unstake request will sit in a pending status for two epochs. Once it is processed, the amount that has been unstaked will sit in your unstaked FLOW amount and can now be withdrawn or re-staked.
+ - Change the node you are staked/delegated to. If your staked/delegated node has no FLOW actively staked and you have completely withdrawn all unstaked amounts and rewards associated with the node, then you can move your stake to a different node. Click on the `Change Node` button to initiate this process. Please note that this feature is only visible once you get your active stake/delegate into the appropriate status.
+
+## FAQs
+ 1. Why do I have multiple 'Keys' on my account?
+
+ If you created your account with Blocto, you will see that you have multiple keys that exist on your account in the 'Dashboard':
+
+ 1 with weight 1 (device key): This is generated on Blocto and sent to users' device when they login with email.
+ 1 with weight 999 (Blocto service key): This is kept in Blocto's secure key management service and is used to sign transaction.
+ 1 with weight 1000 (recovery key): This is kept in Blocto's secure key management service and is only used when user wants to switch to non-custodial mode.
+
+ Normally if a user wants to send a Flow transaction, it requires signature from both the key on users' device and a key from Blocto service. Making it harder for hackers to steal your assets.
+
+ 2. Where can I find a list of node operators to delegate to?
+
+ - a.) Please see a list [here](https://github.com/onflow/flow/blob/master/nodeoperators/NodeOperatorList.md) for all node operators that you can delegate to. This list will be updated as new node operators are onboarded onto the network.
+
+ 3. I am currently running a node on the network already and have already gone through the staking process once. Do I need to execute a new stake every time there is a new epoch?
+
+ - a.) Once you successfully stake your node and become part of the network, you do not need to submit a new staking request each and every epoch. Your node will be automatically staked from epoch to epoch. This also means that your Node ID will remain the same from epoch to epoch. If you want to unstake your node from the network, then you will follow the process of unstaking your node.
+
+ 4. I have a Blocto account and I see that I can stake both in Flow Port and in Blocto's mobile app. What is the difference?
+
+ - a.) If you go through Flow Port, you can choose any node operator within the Flow network to delegate any amount of your Flow Tokens to. If you go through Blocto's mobile site, you will only be able to stake to Blocto run nodes. You can read more about Blocto's staking process by referencing [here](https://guide.blocto.app/article/stake-flow-tokens-step-by-step-with-blocto).
+
+ 5. Do I need to use my Ledger device to view information about my account (e.g. my balance and current staked or delegated FLOW)?
+
+ - a.) No you do not! You only need your Ledger device to sign transactions. If you want to view your account, you can do so without your Ledger. You can do this by navigating directly to the appropriate desired page URL, while inputting your address into the URL itself. For quick reference, below is a list of these URLs and where you would input your address:
+ - Dashboard: https://port.onflow.org/account/[AccountAddress]
+ - Stake & Delegate: https://port.onflow.org/stake-delegate/[AccountAddress]
+
+ 6. I am clicking 'submit' to execute a transaction, but nothing is happening. How can I unblock myself?
+
+ - a.) Please disable any pop-up blockers and ad blockers you have and refresh the page. If you are still experiencing issues, please reach out via [Discord](https://discord.gg/flow) in the appropriate channel.
+
+
+=== networks/flow-networks/index.md ===
+---
+title: Flow Networks
+sidebar_position: 1
+---
+
+## About Flow Networks
+
+:::note
+
+This page provides information on Flow network RPCs. Flow EVM network RPCs can be found [here](../evm/networks)
+
+:::
+
+In addition to Mainnet, developers have access to the Testnet environment, which serves as an essential testing ground for applications and smart contracts prior to their deployment on Mainnet. This ensures that any potential issues can be identified and resolved in a controlled setting, mitigating risks associated with live deployment.
+
+Furthermore, during network upgrades, Testnet receives updates ahead of Mainnet. This preemptive update process allows developers to comprehensively test their apps against the latest versions of the nodes, enhancements to the Cadence programming language, and core contract upgrades. This strategy guarantees that when these updates are eventually applied to Mainnet, applications and smart contracts will operate seamlessly, enhancing overall network stability and user experience.
+
+### How To Access These Networks?
+
+| Network | GRPC | Web GRPC | REST |
+| ------- | -------------------------------------- | -------------------- | ------------------------- |
+| Mainnet | `access.mainnet.nodes.onflow.org:9000` | `mainnet.onflow.org` | `rest-mainnet.onflow.org` |
+| Testnet | `access.devnet.nodes.onflow.org:9000` | `testnet.onflow.org` | `rest-testnet.onflow.org` |
+
+For more information on how to access these networks, refer to the following guides:
+
+- [Flow Testnet](./accessing-testnet.md)
+- [Flow Mainnet](./accessing-mainnet.md)
+
+### Network
+
+There are two primary ways to access on-chain data within the Flow network; Access Nodes and Light nodes. Access Nodes are the node type that are most useful for developers, as they provide access to the Flow network via the following API endpoints:
+
+- [Flow Access API](../access-onchain-data/index.md)
+ - [Mainnet](./accessing-mainnet.md): `access.mainnet.nodes.onflow.org:9000`
+ - [Testnet](./accessing-testnet.md): `access.devnet.nodes.onflow.org:9000`
+- [Status Page](https://status.onflow.org/) - Network status page
+
+### Rate limits
+
+Rate limits for Flow Public Access nodes hosted by QuickNode are detailed [here](https://www.quicknode.com/docs/flow#endpoint-rate-limits).
+
+### Running Your Own Node
+
+If you’re getting started you don’t need to run your own node and you can use the above public nodes. The public access nodes are rate-limited, so as your product matures you might want to run your own node. There are multiple options available:
+
+- Start with a [Light (Observer) Node](../node-ops/light-nodes/observer-node.md).
+- You can also use a third-party provider like [Quicknode](https://www.quicknode.com/docs/flow).
+
+Check out [Running a Node](../node-ops/light-nodes/observer-node.md) for more information.
+
+
+=== networks/flow-networks/accessing-testnet.md ===
+---
+title: Flow Testnet
+sidebar_label: Testnet
+sidebar_position: 3
+description: Guide to Testnet access
+---
+
+## About Flow Testnet
+
+Flow Testnet is Flow's official testing and development network. It is intended to provide a staging and testing environment for dApp developers.
+It aims to balance similarity with Mainnet with being a productive development environment, resulting in the following key differences:
+
+- Testnet has significantly fewer validator nodes, resulting in a faster block rate compared to Mainnet
+- Testnet is configured with shorter epochs (about 12 hours, compared to 7 days on Mainnet)
+- Testnet receives software upgrades up to 2 weeks before Mainnet
+
+## Accessing Flow Testnet
+
+Flow Testnet is available for access at this URL:
+
+```
+access.devnet.nodes.onflow.org:9000
+```
+
+For example, to access the network using the [Flow Go SDK](https://github.com/onflow/flow-go-sdk):
+
+```go
+import "github.com/onflow/flow-go-sdk/client"
+
+func main() {
+ flowAccessAddress := "access.devnet.nodes.onflow.org:9000"
+ flowClient, _ := client.New(flowAccessAddress, grpc.WithInsecure())
+ // ...
+}
+```
+
+### Generating Testnet Key Pair
+
+You can generate a new key pair with the [Flow CLI](https://github.com/onflow/flow-cli) as follows:
+
+```sh
+> flow keys generate
+
+🙏 If you want to create an account on Testnet with the generated keys use this link:
+https://testnet-faucet.onflow.org/?key= cc1c3d72...
+
+
+🔴️ Store private key safely and don't share with anyone!
+Private Key 246256f3...
+Public Key cc1c3d72...
+```
+
+**Note: By default, this command generates an ECDSA key pair on the P-256 curve. Keep in mind, the CLI is intended for development purposes only and is not recommended for production use. Handling keys using a Key Management Service is the best practice.**
+
+## Account Creation and Token Funding Requests
+
+Accounts and tokens for testing can be obtained through the [testnet faucet](https://testnet-faucet.onflow.org/). If you generated the keypair through the CLI, you can click on the URL provided to create an account and request testnet FLOW tokens.
+
+## Important Smart Contract Addresses
+
+You can review [all available core contracts](../../build/core-contracts/index.md) deployed to the Testnet to identify which ones you want to import.
+
+
+=== networks/flow-networks/accessing-mainnet.md ===
+---
+title: Flow Mainnet
+sidebar_label: Mainnet
+sidebar_position: 2
+description: Guide to mainnet access
+---
+
+## Accessing Flow Mainnet
+
+The Flow Mainnet is available for access at this URL:
+
+```
+access.mainnet.nodes.onflow.org:9000
+```
+
+For example, to access the network using the [Flow Go SDK](https://github.com/onflow/flow-go-sdk):
+
+```go
+import "github.com/onflow/flow-go-sdk/client"
+
+func main() {
+ flowAccessAddress := "access.mainnet.nodes.onflow.org:9000"
+ flowClient, _ := client.New(flowAccessAddress, grpc.WithInsecure())
+ // ...
+}
+```
+
+## Account Creation
+
+You can follow the [Flow Port account creation steps](../../networks/flow-port/index.md) to create a new mainnet account.
+
+If you prefer watching a video, check out this tutorial:
+
+
+
+## Generating a Non-Custodial Account
+
+A non-custodial account will make sure you are the only one holding the keys to your account.
+
+You can follow the following steps to add a non-custodial account:
+
+First, generate a new key pair with the [Flow CLI](https://github.com/onflow/flow-cli):
+
+```sh
+> flow keys generate --network=mainnet
+
+🔴️ Store private key safely and don't share with anyone!
+Private Key 5b438...
+Public Key 1bdc5...
+```
+
+> **Note**: By default, this command generates an ECDSA key pair on the P-256 curve. Keep in mind the CLI is intended for development purposes only and is not recommended for production use. Handling keys using a Key Management Service is the best practice.
+
+Take a note of the public key and go back to Flow Port. Open the ["Create a new account" page](https://port.onflow.org/transaction?hash=a0a78aa7821144efd5ebb974bb52ba04609ce76c3863af9d45348db93937cf98&showcode=false&weight=1000&halg=3).
+
+On the page, enter your public key from the CLI, ensure the hash algorithm is set to `SHA3_256` and the weight is set to `1000`. Finally, check the box confirming correctness and hit 'Submit'.
+
+> **Important**: Your account needs to have at least 0.002 FLOW for the account creation. More details can be found [in this guide](../../build/basics/fees.md#storage).
+
+Once the transaction is sealed, you should scroll down to the events section and locate the `flow.AccountCreated` event with the newly generated address.
+
+
+
+Make sure to take a note of the address. If you want to verify the public key for this address, you can visit [flow-view-source](https://flow-view-source.com/).
+
+## Important Mainnet Smart Contract Addresses
+
+You can review [all available core contracts](../../build/core-contracts/index.md) deployed to the mainnet to identify which ones you want to import.
+
+
+=== networks/access-onchain-data/index.md ===
+---
+title: Flow Access API Specification
+sidebar_label: Access API
+sidebar_position: 1
+---
+
+The Access API is implemented as a [gRPC service](https://grpc.io/).
+
+A language-agnostic specification for this API is defined using [Protocol Buffers](https://developers.google.com/protocol-buffers), which can be used to generate client libraries in a variety of programming languages.
+
+- [Flow Access API protobuf source files](https://github.com/onflow/flow/tree/master/protobuf)
+
+## Flow Access Node Endpoints
+
+| Network | GRPC | Web GRPC | REST |
+| ------- | -------------------------------------- | -------------------- | ------------------------- |
+| Mainnet | `access.mainnet.nodes.onflow.org:9000` | `mainnet.onflow.org` | `rest-mainnet.onflow.org` |
+| Testnet | `access.devnet.nodes.onflow.org:9000` | `testnet.onflow.org` | `rest-testnet.onflow.org` |
+
+---
+
+## Ping
+
+`Ping` will return a successful response if the Access API is ready and available.
+
+```proto
+rpc Ping(PingRequest) returns (PingResponse)
+```
+
+If a ping request returns an error or times out, it can be assumed that the Access API is unavailable.
+
+#### Request
+
+```proto
+message PingRequest {}
+```
+
+#### Response
+
+```proto
+message PingResponse {}
+```
+
+---
+
+## Block Headers
+
+The following methods query information about [block headers](#block-header).
+
+### GetLatestBlockHeader
+
+`GetLatestBlockHeader` gets the latest sealed or unsealed [block header](#block-header).
+
+```proto
+rpc GetLatestBlockHeader (GetLatestBlockHeaderRequest) returns (BlockHeaderResponse)
+```
+
+#### Request
+
+```proto
+message GetLatestBlockHeaderRequest {
+ bool is_sealed = 1;
+}
+```
+
+#### Response
+
+```proto
+message BlockHeaderResponse {
+ entities.BlockHeader block = 1;
+ entities.BlockStatus block_status = 2;
+ entities.Metadata metadata = 3;
+}
+```
+
+### GetBlockHeaderByID
+
+`GetBlockHeaderByID` gets a [block header](#block-header) by ID.
+
+```proto
+rpc GetBlockHeaderByID (GetBlockHeaderByIDRequest) returns (BlockHeaderResponse)
+```
+
+#### Request
+
+```proto
+message GetBlockHeaderByIDRequest {
+ bytes id = 1;
+}
+```
+
+#### Response
+
+```proto
+message BlockHeaderResponse {
+ entities.BlockHeader block = 1;
+ entities.BlockStatus block_status = 2;
+ entities.Metadata metadata = 3;
+}
+```
+
+### GetBlockHeaderByHeight
+
+`GetBlockHeaderByHeight` gets a [block header](#block-header) by height.
+
+```proto
+rpc GetBlockHeaderByHeight (GetBlockHeaderByHeightRequest) returns (BlockHeaderResponse)
+```
+
+#### Request
+
+```proto
+message GetBlockHeaderByHeightRequest {
+ uint64 height = 1;
+}
+```
+
+#### Response
+
+```proto
+message BlockHeaderResponse {
+ entities.BlockHeader block = 1;
+ entities.BlockStatus block_status = 2;
+ entities.Metadata metadata = 3;
+}
+```
+
+---
+
+## Blocks
+
+The following methods query information about [full blocks](#block).
+
+### GetLatestBlock
+
+`GetLatestBlock` gets the full payload of the latest sealed or unsealed [block](#block).
+
+```proto
+rpc GetLatestBlock (GetLatestBlockRequest) returns (BlockResponse)
+```
+
+#### Request
+
+```proto
+message GetLatestBlockRequest {
+ bool is_sealed = 1;
+ bool full_block_response = 2;
+}
+```
+
+#### Response
+
+```proto
+message BlockResponse {
+ entities.Block block = 1;
+ entities.BlockStatus block_status = 2;
+ entities.Metadata metadata = 3;
+}
+```
+
+### GetBlockByID
+
+`GetBlockByID` gets a [full block](#block) by ID.
+
+```proto
+rpc GetBlockByID (GetBlockByIDRequest) returns (BlockResponse)
+```
+
+#### Request
+
+```proto
+message GetBlockByIDRequest {
+ bytes id = 1;
+ bool full_block_response = 2;
+}
+```
+
+#### Response
+
+```proto
+message BlockResponse {
+ entities.Block block = 1;
+ entities.BlockStatus block_status = 2;
+ entities.Metadata metadata = 3;
+}
+```
+
+### GetBlockByHeight
+
+`GetBlockByHeight` gets a [full block](#block) by height.
+
+```proto
+rpc GetBlockByHeight (GetBlockByHeightRequest) returns (BlockResponse)
+```
+
+#### Request
+
+```proto
+message GetBlockByHeightRequest {
+ uint64 height = 1;
+ bool full_block_response = 2;
+}
+```
+
+#### Response
+
+```proto
+message BlockResponse {
+ entities.Block block = 1;
+ entities.BlockStatus block_status = 2;
+ entities.Metadata metadata = 3;
+}
+```
+
+---
+
+## Collections
+
+The following methods query information about [collections](#collection).
+
+### GetCollectionByID
+
+`GetCollectionByID` gets a [collection](#collection) by ID.
+
+```proto
+rpc GetCollectionByID (GetCollectionByIDRequest) returns (CollectionResponse)
+```
+
+#### Request
+
+```proto
+message GetCollectionByIDRequest {
+ bytes id = 1;
+}
+```
+
+#### Response
+
+```proto
+message CollectionResponse {
+ entities.Collection collection = 1;
+ entities.Metadata metadata = 2;
+}
+```
+
+---
+
+### GetFullCollectionByID
+
+`GetFullCollectionByID` gets a collection by ID, which contains a set of [transactions](#transaction).
+
+```proto
+rpc GetFullCollectionByID(GetFullCollectionByIDRequest) returns (FullCollectionResponse);
+```
+
+#### Request
+
+```proto
+message GetFullCollectionByIDRequest {
+ bytes id = 1;
+}
+```
+
+#### Response
+
+```proto
+message FullCollectionResponse {
+ repeated entities.Transaction transactions = 1;
+ entities.Metadata metadata = 2;
+}
+```
+
+---
+
+## Transactions
+
+The following methods can be used to submit [transactions](#transaction) and fetch their results.
+
+### SendTransaction
+
+`SendTransaction` submits a transaction to the network.
+
+```proto
+rpc SendTransaction (SendTransactionRequest) returns (SendTransactionResponse)
+```
+
+`SendTransaction` determines the correct cluster of collection nodes that is responsible for collecting the transaction based on the hash of the transaction and forwards the transaction to that cluster.
+
+#### Request
+
+`SendTransactionRequest` message contains the transaction that is being request to be executed.
+
+```proto
+message SendTransactionRequest {
+ entities.Transaction transaction = 1;
+}
+```
+
+#### Response
+
+`SendTransactionResponse` message contains the ID of the submitted transaction.
+
+```proto
+message SendTransactionResponse {
+ bytes id = 1;
+ entities.Metadata metadata = 2;
+}
+```
+
+### GetTransaction
+
+`GetTransaction` gets a [transaction](#transaction) by ID.
+
+If the transaction is not found in the access node cache, the request is forwarded to a collection node.
+
+_Currently, only transactions within the current epoch can be queried._
+
+```proto
+rpc GetTransaction (GetTransactionRequest) returns (TransactionResponse)
+```
+
+#### Request
+
+`GetTransactionRequest` contains the ID of the transaction that is being queried.
+
+```proto
+message GetTransactionRequest {
+ bytes id = 1;
+ bytes block_id = 2;
+ bytes collection_id = 3;
+ entities.EventEncodingVersion event_encoding_version = 4;
+}
+```
+
+#### Response
+
+`TransactionResponse` contains the basic information about a transaction, but does not include post-execution results.
+
+```proto
+message TransactionResponse {
+ entities.Transaction transaction = 1;
+ entities.Metadata metadata = 2;
+}
+```
+
+### GetTransactionsByBlockID
+
+`GetTransactionsByBlockID` gets all the [transactions](#transaction) for a specified block.
+
+```proto
+rpc GetTransactionsByBlockID(GetTransactionsByBlockIDRequest) returns (TransactionsResponse);
+```
+
+#### Request
+
+```proto
+message GetTransactionsByBlockIDRequest {
+ bytes block_id = 1;
+ entities.EventEncodingVersion event_encoding_version = 2;
+}
+```
+
+#### Response
+
+```proto
+message TransactionsResponse {
+ repeated entities.Transaction transactions = 1;
+ entities.Metadata metadata = 2;
+}
+```
+
+### GetTransactionResult
+
+`GetTransactionResult` gets the execution result of a transaction.
+
+```proto
+rpc GetTransactionResult (GetTransactionRequest) returns (TransactionResultResponse)
+```
+
+#### Request
+
+```proto
+message GetTransactionRequest {
+ bytes id = 1;
+ bytes block_id = 2;
+ bytes collection_id = 3;
+ entities.EventEncodingVersion event_encoding_version = 4;
+}
+```
+
+#### Response
+
+```proto
+message TransactionResultResponse {
+ entities.TransactionStatus status = 1;
+ uint32 status_code = 2;
+ string error_message = 3;
+ repeated entities.Event events = 4;
+ bytes block_id = 5;
+ bytes transaction_id = 6;
+ bytes collection_id = 7;
+ uint64 block_height = 8;
+ entities.Metadata metadata = 9;
+ uint64 computation_usage = 10;
+}
+```
+### GetTransactionResultByIndex
+
+`GetTransactionResultByIndex` gets a transaction's result at a specified block and index.
+
+```proto
+rpc GetTransactionResultByIndex(GetTransactionByIndexRequest) returns (TransactionResultResponse);
+```
+
+#### Request
+
+```proto
+message GetTransactionByIndexRequest {
+ bytes block_id = 1;
+ uint32 index = 2;
+ entities.EventEncodingVersion event_encoding_version = 3;
+}
+```
+
+#### Response
+
+```proto
+message TransactionResultResponse {
+ entities.TransactionStatus status = 1;
+ uint32 status_code = 2;
+ string error_message = 3;
+ repeated entities.Event events = 4;
+ bytes block_id = 5;
+ bytes transaction_id = 6;
+ bytes collection_id = 7;
+ uint64 block_height = 8;
+ entities.Metadata metadata = 9;
+ uint64 computation_usage = 10;
+}
+```
+
+### GetTransactionResultsByBlockID
+
+`GetTransactionResultsByBlockID` gets all the transaction results for a specified block.
+
+```proto
+rpc GetTransactionResultsByBlockID(GetTransactionsByBlockIDRequest) returns (TransactionResultsResponse);
+```
+
+#### Request
+
+```proto
+message GetTransactionsByBlockIDRequest {
+ bytes block_id = 1;
+ entities.EventEncodingVersion event_encoding_version = 2;
+}
+```
+
+#### Response
+
+```proto
+message TransactionResultsResponse {
+ repeated TransactionResultResponse transaction_results = 1;
+ entities.Metadata metadata = 2;
+}
+```
+
+### GetSystemTransaction
+
+`GetSystemTransaction` gets the system transaction for a block.
+
+```proto
+rpc GetSystemTransaction(GetSystemTransactionRequest) returns (TransactionResponse);
+```
+
+#### Request
+
+```proto
+message GetSystemTransactionRequest {
+ bytes block_id = 1;
+}
+```
+
+#### Response
+
+```proto
+message TransactionResponse {
+ entities.Transaction transaction = 1;
+ entities.Metadata metadata = 2;
+}
+```
+
+### GetSystemTransactionResult
+
+`GetSystemTransactionResult` gets the system transaction result for a block.
+
+```proto
+rpc GetSystemTransactionResult(GetSystemTransactionResultRequest) returns (TransactionResultResponse);
+```
+
+#### Request
+
+```proto
+message GetSystemTransactionResultRequest {
+ bytes block_id = 1;
+ entities.EventEncodingVersion event_encoding_version = 2;
+}
+```
+
+#### Response
+
+```proto
+message TransactionResultResponse {
+ entities.TransactionStatus status = 1;
+ uint32 status_code = 2;
+ string error_message = 3;
+ repeated entities.Event events = 4;
+ bytes block_id = 5;
+ bytes transaction_id = 6;
+ bytes collection_id = 7;
+ uint64 block_height = 8;
+ entities.Metadata metadata = 9;
+ uint64 computation_usage = 10;
+}
+```
+
+---
+
+## Accounts
+
+### GetAccount
+
+`GetAccount` gets an [account](#account) by address at the latest sealed block.
+
+⚠️ Warning: this function is deprecated. It behaves identically to `GetAccountAtLatestBlock` and will be removed in a future version.
+
+```proto
+rpc GetAccount(GetAccountRequest) returns (GetAccountResponse)
+```
+
+#### Request
+
+```proto
+message GetAccountRequest {
+ bytes address = 1;
+}
+```
+
+#### Response
+
+```proto
+message GetAccountResponse {
+ entities.Account account = 1;
+ entities.Metadata metadata = 2;
+}
+```
+
+### GetAccountAtLatestBlock
+
+`GetAccountAtLatestBlock` gets an [account](#account) by address.
+
+The access node queries an execution node for the account details, which are stored as part of the sealed execution state.
+
+```proto
+rpc GetAccountAtLatestBlock(GetAccountAtLatestBlockRequest) returns (AccountResponse)
+```
+
+#### Request
+
+```proto
+message GetAccountAtLatestBlockRequest {
+ bytes address = 1;
+}
+```
+
+#### Response
+
+```proto
+message AccountResponse {
+ entities.Account account = 1;
+ entities.Metadata metadata = 2;
+}
+```
+
+### GetAccountAtBlockHeight
+
+`GetAccountAtBlockHeight` gets an [account](#accounts) by address at the given block height.
+
+The access node queries an execution node for the account details, which are stored as part of the execution state.
+
+```proto
+rpc GetAccountAtBlockHeight(GetAccountAtBlockHeightRequest) returns (AccountResponse)
+```
+
+#### Request
+
+```proto
+message GetAccountAtBlockHeightRequest {
+ bytes address = 1;
+ uint64 block_height = 2;
+}
+```
+
+#### Response
+
+```proto
+message AccountResponse {
+ entities.Account account = 1;
+ entities.Metadata metadata = 2;
+}
+```
+
+### GetAccountBalanceAtLatestBlock
+
+`GetAccountBalanceAtLatestBlock` gets an account's balance by address from the latest sealed block.
+
+```proto
+rpc GetAccountBalanceAtLatestBlock(GetAccountBalanceAtLatestBlockRequest) returns (AccountBalanceResponse);
+```
+
+#### Request
+
+```proto
+message GetAccountBalanceAtLatestBlockRequest {
+ bytes address = 1
+}
+```
+
+#### Response
+
+```proto
+message AccountBalanceResponse {
+ uint64 balance = 1;
+ entities.Metadata metadata = 2;
+}
+```
+
+### GetAccountBalanceAtBlockHeight
+
+`GetAccountBalanceAtBlockHeight` gets an account's balance by address at the given block height.
+
+```proto
+rpc GetAccountBalanceAtBlockHeight(GetAccountBalanceAtBlockHeightRequest) returns (AccountBalanceResponse);
+```
+
+#### Request
+
+```proto
+message GetAccountBalanceAtBlockHeightRequest {
+ bytes address = 1;
+ uint64 block_height = 2;
+}
+```
+
+#### Response
+
+```proto
+message AccountBalanceResponse {
+ uint64 balance = 1;
+ entities.Metadata metadata = 2;
+}
+```
+
+### GetAccountKeyAtLatestBlock
+
+`GetAccountKeyAtLatestBlock` gets an account's public key by address and key index from the latest sealed block.
+
+```proto
+rpc GetAccountKeyAtLatestBlock(GetAccountKeyAtLatestBlockRequest) returns (AccountKeyResponse);
+```
+
+#### Request
+
+```proto
+message GetAccountKeyAtLatestBlockRequest {
+ // address of account
+ bytes address = 1;
+ // index of key to return
+ uint32 index = 2;
+}
+```
+
+#### Response
+
+```proto
+message AccountKeyResponse {
+ entities.AccountKey account_key = 1;
+ entities.Metadata metadata = 2;
+}
+```
+
+### GetAccountKeyAtBlockHeight
+
+`GetAccountKeyAtBlockHeight` gets an account's public key by address and key index at the given block height.
+
+```proto
+rpc GetAccountKeyAtBlockHeight(GetAccountKeyAtBlockHeightRequest) returns (AccountKeyResponse);
+```
+
+#### Request
+
+```proto
+message GetAccountKeyAtBlockHeightRequest {
+ // address of account
+ bytes address = 1;
+ // height of the block
+ uint64 block_height = 2;
+ // index of key to return
+ uint32 index = 3;
+}
+```
+
+#### Response
+
+```proto
+message AccountKeyResponse {
+ entities.AccountKey account_key = 1;
+ entities.Metadata metadata = 2;
+}
+```
+
+### GetAccountKeysAtLatestBlock
+
+`GetAccountKeysAtLatestBlock` gets an account's public keys by address from the latest sealed block.
+
+```proto
+rpc GetAccountKeysAtLatestBlock(GetAccountKeysAtLatestBlockRequest) returns (AccountKeysResponse);
+```
+
+#### Request
+
+```proto
+message GetAccountKeysAtLatestBlockRequest {
+ // address of account
+ bytes address = 1;
+}
+```
+
+#### Response
+
+```proto
+message AccountKeysResponse {
+ repeated entities.AccountKey account_keys = 1;
+ entities.Metadata metadata = 2;
+}
+```
+
+### GetAccountKeysAtBlockHeight
+
+`GetAccountKeysAtBlockHeight` gets an account's public keys by address at the given block height.
+
+```proto
+rpc GetAccountKeysAtBlockHeight(GetAccountKeysAtBlockHeightRequest) returns (AccountKeysResponse);
+```
+
+#### Request
+
+```proto
+message GetAccountKeysAtBlockHeightRequest {
+ // address of account
+ bytes address = 1;
+ uint64 block_height = 2;
+}
+```
+
+#### Response
+
+```proto
+message AccountKeysResponse {
+ repeated entities.AccountKey account_keys = 1;
+ entities.Metadata metadata = 2;
+}
+```
+
+##
+
+## Scripts
+
+### ExecuteScriptAtLatestBlock
+
+`ExecuteScriptAtLatestBlock` executes a read-only Cadence script against the latest sealed execution state.
+
+This method can be used to read execution state from the blockchain. The script is executed on an execution node and the return value is encoded using the [JSON-Cadence data interchange format](https://cadencelang.dev/docs/1.0/json-cadence-spec).
+
+```proto
+rpc ExecuteScriptAtLatestBlock (ExecuteScriptAtLatestBlockRequest) returns (ExecuteScriptResponse)
+```
+
+This method is a shortcut for the following:
+
+```
+header = GetLatestBlockHeader()
+value = ExecuteScriptAtBlockID(header.ID, script)
+```
+
+#### Request
+
+```proto
+message ExecuteScriptAtLatestBlockRequest {
+ bytes script = 1;
+ repeated bytes arguments = 2;
+}
+```
+
+#### Response
+
+```proto
+message ExecuteScriptResponse {
+ bytes value = 1;
+ entities.Metadata metadata = 2;
+ uint64 computation_usage = 3;
+}
+```
+
+### ExecuteScriptAtBlockID
+
+`ExecuteScriptAtBlockID` executes a ready-only Cadence script against the execution state at the block with the given ID.
+
+This method can be used to read account state from the blockchain. The script is executed on an execution node and the return value is encoded using the [JSON-Cadence data interchange format](https://cadencelang.dev/docs/1.0/json-cadence-spec).
+
+```proto
+rpc ExecuteScriptAtBlockID (ExecuteScriptAtBlockIDRequest) returns (ExecuteScriptResponse)
+```
+
+#### Request
+
+```proto
+message ExecuteScriptAtBlockIDRequest {
+ bytes block_id = 1;
+ bytes script = 2;
+ repeated bytes arguments = 3;
+}
+```
+
+#### Response
+
+```proto
+message ExecuteScriptResponse {
+ bytes value = 1;
+ entities.Metadata metadata = 2;
+ uint64 computation_usage = 3;
+}
+```
+
+### ExecuteScriptAtBlockHeight
+
+`ExecuteScriptAtBlockHeight` executes a ready-only Cadence script against the execution state at the given block height.
+
+This method can be used to read account state from the blockchain. The script is executed on an execution node and the return value is encoded using the [JSON-Cadence data interchange format](https://cadencelang.dev/docs/1.0/json-cadence-spec).
+
+```proto
+rpc ExecuteScriptAtBlockHeight (ExecuteScriptAtBlockHeightRequest) returns (ExecuteScriptResponse)
+```
+
+#### Request
+
+```proto
+message ExecuteScriptAtBlockHeightRequest {
+ uint64 block_height = 1;
+ bytes script = 2;
+ repeated bytes arguments = 3;
+}
+```
+
+#### Response
+
+```proto
+message ExecuteScriptResponse {
+ bytes value = 1;
+ entities.Metadata metadata = 2;
+ uint64 computation_usage = 3;
+}
+```
+
+---
+
+## Events
+
+The following methods can be used to query for on-chain [events](#event).
+
+### GetEventsForHeightRange
+
+`GetEventsForHeightRange` retrieves [events](#event) emitted within the specified block range.
+
+```proto
+rpc GetEventsForHeightRange(GetEventsForHeightRangeRequest) returns (GetEventsForHeightRangeResponse)
+```
+
+Events can be requested for a specific sealed block range via the `start_height` and `end_height` (inclusive) fields and further filtered by event type via the `type` field.
+
+If `start_height` is greater than the current sealed chain height, then this method will return an error.
+
+If `end_height` is greater than the current sealed chain height, then this method will return events up to and including the latest sealed block.
+
+The event results are grouped by block, with each group specifying a block ID, height and block timestamp.
+
+Event types are name-spaced with the address of the account and contract in which they are declared.
+
+#### Request
+
+```proto
+message GetEventsForHeightRangeRequest {
+ string type
+ uint64 start_height = 2;
+ uint64 end_height = 3;
+ entities.EventEncodingVersion event_encoding_version = 4;
+}
+```
+
+#### Response
+
+```proto
+message EventsResponse {
+ message Result {
+ bytes block_id = 1;
+ uint64 block_height = 2;
+ repeated entities.Event events = 3;
+ google.protobuf.Timestamp block_timestamp = 4;
+ }
+ repeated Result results = 1;
+ entities.Metadata metadata = 2;
+}
+```
+
+### GetEventsForBlockIDs
+
+`GetEventsForBlockIDs` retrieves [events](#event) for the specified block IDs and event type.
+
+```proto
+rpc GetEventsForBlockIDs(GetEventsForBlockIDsRequest) returns (GetEventsForBlockIDsResponse)
+```
+
+Events can be requested for a list of block IDs via the `block_ids` field and further filtered by event type via the `type` field.
+
+The event results are grouped by block, with each group specifying a block ID, height and block timestamp.
+
+#### Request
+
+```proto
+message GetEventsForBlockIDsRequest {
+ string type = 1;
+ repeated bytes block_ids = 2;
+ entities.EventEncodingVersion event_encoding_version = 3;
+}
+```
+
+#### Response
+
+```proto
+message EventsResponse {
+ message Result {
+ bytes block_id = 1;
+ uint64 block_height = 2;
+ repeated entities.Event events = 3;
+ google.protobuf.Timestamp block_timestamp = 4;
+ }
+ repeated Result results = 1;
+ entities.Metadata metadata = 2;
+}
+```
+
+---
+
+## Network Parameters
+
+Network parameters provide information about the Flow network. Currently, it only includes the chain ID.
+The following method can be used to query for network parameters.
+
+### GetNetworkParameters
+
+`GetNetworkParameters` retrieves the network parameters.
+
+```proto
+rpc GetNetworkParameters (GetNetworkParametersRequest) returns (GetNetworkParametersResponse)
+```
+
+#### Request
+
+```proto
+message GetNetworkParametersRequest {}
+```
+
+#### Response
+
+```proto
+message GetNetworkParametersResponse {
+ string chain_id = 1;
+}
+```
+
+| Field | Description |
+| -------- | ------------------------------------------------------------------------------------------------------------ |
+| chain_id | Chain ID helps identify the Flow network. It can be one of `flow-mainnet`, `flow-testnet` or `flow-emulator` |
+
+---
+
+### GetNodeVersionInfo
+
+`GetNodeVersionInfo` gets information about a node's current versions.
+
+```proto
+rpc GetNodeVersionInfo (GetNodeVersionInfoRequest) returns (GetNodeVersionInfoResponse);
+```
+
+#### Request
+
+```proto
+message GetNodeVersionInfoRequest {}
+```
+
+#### Response
+
+```proto
+message GetNodeVersionInfoResponse {
+ entities.NodeVersionInfo info = 1;
+}
+```
+
+---
+
+## Protocol state snapshot
+
+The following method can be used to query the latest protocol state [snapshot](https://github.com/onflow/flow-go/blob/master/state/protocol/snapshot.go).
+
+### GetLatestProtocolStateSnapshot
+
+`GetLatestProtocolStateSnapshot` retrieves the latest Protocol state snapshot serialized as a byte array.
+It is used by Flow nodes joining the network to bootstrap a space-efficient local state.
+
+```proto
+rpc GetLatestProtocolStateSnapshot (GetLatestProtocolStateSnapshotRequest) returns (ProtocolStateSnapshotResponse);
+```
+
+#### Request
+
+```proto
+message GetLatestProtocolStateSnapshotRequest {}
+```
+
+#### Response
+
+```proto
+message ProtocolStateSnapshotResponse {
+ bytes serializedSnapshot = 1;
+ entities.Metadata metadata = 2;
+}
+```
+
+### GetProtocolStateSnapshotByBlockID
+
+`GetProtocolStateSnapshotByBlockID` retrieves the latest sealed protocol state snapshot by block ID.
+Used by Flow nodes joining the network to bootstrap a space-efficient local state.
+
+```proto
+rpc GetProtocolStateSnapshotByBlockID(GetProtocolStateSnapshotByBlockIDRequest) returns (ProtocolStateSnapshotResponse);
+```
+
+#### Request
+
+```proto
+message GetProtocolStateSnapshotByBlockIDRequest {
+ bytes block_id = 1;
+}
+```
+
+#### Response
+
+```proto
+message ProtocolStateSnapshotResponse {
+ bytes serializedSnapshot = 1;
+ entities.Metadata metadata = 2;
+}
+```
+
+### GetProtocolStateSnapshotByHeight
+
+`GetProtocolStateSnapshotByHeight` retrieves the latest sealed protocol state snapshot by block height.
+Used by Flow nodes joining the network to bootstrap a space-efficient local state.
+
+```proto
+rpc GetProtocolStateSnapshotByHeight(GetProtocolStateSnapshotByHeightRequest) returns (ProtocolStateSnapshotResponse);
+```
+
+#### Request
+
+```proto
+message GetProtocolStateSnapshotByHeightRequest {
+ uint64 block_height = 1;
+}
+```
+
+#### Response
+
+```proto
+message ProtocolStateSnapshotResponse {
+ bytes serializedSnapshot = 1;
+ entities.Metadata metadata = 2;
+}
+```
+
+## Execution results
+
+The following method can be used to query the for [execution results](https://github.com/onflow/flow-go/blob/master/model/flow/execution_result.go) for a given block.
+
+### GetExecutionResultForBlockID
+
+`GetExecutionResultForBlockID` retrieves execution result for given block. It is different from Transaction Results,
+and contain data about chunks/collection level execution results rather than particular transactions.
+Particularly, it contains `EventsCollection` hash for every chunk which can be used to verify the events for a block.
+
+```proto
+rpc GetExecutionResultForBlockID(GetExecutionResultForBlockIDRequest) returns (ExecutionResultForBlockIDResponse);
+```
+
+#### Request
+
+```proto
+message GetExecutionResultForBlockIDRequest {
+ bytes block_id = 1;
+}
+```
+
+#### Response
+
+```proto
+message ExecutionResultForBlockIDResponse {
+ flow.ExecutionResult execution_result = 1;
+ entities.Metadata metadata = 2;
+}
+```
+
+### GetExecutionResultByID
+
+`GetExecutionResultByID` returns Execution Result by its ID. It is different from Transaction Results,
+and contain data about chunks/collection level execution results rather than particular transactions.
+Particularly, it contains `EventsCollection` hash for every chunk which can be used to verify the events for a block.
+
+```proto
+rpc GetExecutionResultByID(GetExecutionResultByIDRequest) returns (ExecutionResultByIDResponse);
+```
+
+#### Request
+
+```proto
+message GetExecutionResultByIDRequest {
+ bytes id = 1;
+}
+```
+
+#### Response
+
+```proto
+message ExecutionResultByIDResponse {
+ flow.ExecutionResult execution_result = 1;
+ entities.Metadata metadata = 2;
+}
+```
+
+
+## Entities
+
+Below are in-depth descriptions of each of the data entities returned or accepted by the Access API.
+
+### Block
+
+```proto
+message Block {
+ bytes id = 1;
+ bytes parent_id = 2;
+ uint64 height = 3;
+ google.protobuf.Timestamp timestamp = 4;
+ repeated CollectionGuarantee collection_guarantees = 5;
+ repeated BlockSeal block_seals = 6;
+ repeated bytes signatures = 7;
+ repeated ExecutionReceiptMeta execution_receipt_metaList = 8;
+ repeated ExecutionResult execution_result_list = 9;
+ BlockHeader block_header = 10;
+ bytes protocol_state_id = 11;
+}
+```
+
+| Field | Description |
+|----------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| id | SHA3-256 hash of the entire block payload |
+| height | Height of the block in the chain |
+| parent_id | ID of the previous block in the chain |
+| timestamp | Timestamp of when the proposer claims it constructed the block. **NOTE**: It is included by the proposer, there are no guarantees on how much the time stamp can deviate from the true time the block was published. Consider observing blocks' status changes yourself to get a more reliable value |
+| collection_guarantees | List of [collection guarantees](#collection-guarantee) |
+| block_seals | List of [block seals](#block-seal) |
+| signatures | BLS signatures of consensus nodes |
+| execution_receipt_metaList | List of [execution-receipt-meta](#execution-receipt-meta) |
+| execution_result_list | List of [execution results](#execution-result) |
+| block_header | A summary of a [block](#block-header) |
+| protocol_state_id | The root hash of protocol state. |
+
+The detailed semantics of block formation are covered in the [block formation guide](../../build/basics/blocks.md).
+
+### Block Header
+
+A block header is a summary of a [block](#block) and contains only the block ID, height, and parent block ID.
+
+```proto
+message BlockHeader {
+ bytes id = 1;
+ bytes parent_id = 2;
+ uint64 height = 3;
+ google.protobuf.Timestamp timestamp = 4;
+ bytes payload_hash = 5;
+ uint64 view = 6;
+ repeated bytes parent_voter_ids = 7;
+ bytes parent_voter_sig_data = 8;
+ bytes proposer_id = 9;
+ bytes proposer_sig_data = 10;
+ string chain_id = 11;
+ bytes parent_voter_indices = 12;
+ TimeoutCertificate last_view_tc = 13;
+ uint64 parent_view = 14;
+}
+```
+
+| Field | Description |
+|-----------------------|-------------------------------------------------------------------------------------------------------------------|
+| id | SHA3-256 hash of the entire block payload |
+| parent_id | ID of the previous block in the chain |
+| height | Height of the block in the chain |
+| timestamp | The time at which this block was proposed |
+| payload_hash | A hash of the payload of this block |
+| view | View number during which this block was proposed. |
+| parent_voter_ids | An array that represents all the voters ids for the parent block |
+| parent_voter_sig_data | An aggregated signature over the parent block |
+| chain_id | Chain ID helps identify the Flow network. It can be one of `flow-mainnet`, `flow-testnet` or `flow-emulator` |
+| parent_voter_indices | A bitvector that represents all the voters for the parent block |
+| last_view_tc | A timeout certificate for previous view, it can be nil. It has to be present if previous round ended with timeout |
+| parent_view | A number at which parent block was proposed |
+
+### Block Seal
+
+A block seal is an attestation that the execution result of a specific [block](#block) has been verified and approved by a quorum of verification nodes.
+
+```proto
+message BlockSeal {
+ bytes block_id = 1;
+ bytes execution_receipt_id = 2;
+ repeated bytes execution_receipt_signatures = 3;
+ repeated bytes result_approval_signatures = 4;
+}
+```
+
+| Field | Description |
+| ---------------------------- | ---------------------------------------------------------------------- |
+| block_id | ID of the block being sealed |
+| execution_receipt_id | ID execution receipt being sealed |
+| execution_receipt_signatures | BLS signatures of verification nodes on the execution receipt contents |
+| result_approval_signatures | BLS signatures of verification nodes on the result approval contents |
+
+### Block Status
+
+```proto
+enum BlockStatus {
+ UNKNOWN = 0;
+ FINALIZED = 1;
+ SEALED = 2;
+}
+```
+
+| Value | Description |
+|------------|------------------------------------------------|
+| UNKNOWN | The block status is not known |
+| FINALIZED | The consensus nodes have finalized the block |
+| SEALED | The verification nodes have verified the block |
+
+### Collection
+
+A collection is a batch of [transactions](#transaction) that have been included in a block. Collections are used to improve consensus throughput by increasing the number of transactions per block.
+
+```proto
+message Collection {
+ bytes id = 1;
+ repeated bytes transaction_ids = 2;
+}
+```
+
+| Field | Description |
+|------------------|---------------------------------------------------|
+| id | SHA3-256 hash of the collection contents |
+| transaction_ids | Ordered list of transaction IDs in the collection |
+
+### Collection Guarantee
+
+A collection guarantee is a signed attestation that specifies the collection nodes that have guaranteed to store and respond to queries about a collection.
+
+```proto
+message CollectionGuarantee {
+ bytes collection_id = 1;
+ repeated bytes signatures = 2;
+ bytes reference_block_id = 3;
+ bytes signature = 4;
+ repeated bytes signer_ids = 5; // deprecated!! value will be empty. replaced by signer_indices
+ bytes signer_indices = 6;
+}
+```
+
+| Field | Description |
+|---------------------|--------------------------------------------------------------------|
+| collection_id | SHA3-256 hash of the collection contents |
+| signatures | BLS signatures of the collection nodes guaranteeing the collection |
+| reference_block_id | Defines expiry of the collection |
+| signature | Guarantor signatures |
+| signer_ids | An array that represents all the signer ids |
+| signer_indices | Encoded indices of the signers |
+
+### Transaction
+
+A transaction represents a unit of computation that is submitted to the Flow network.
+
+```proto
+message Transaction {
+ bytes script = 1;
+ repeated bytes arguments = 2;
+ bytes reference_block_id = 3;
+ uint64 gas_limit = 4;
+ ProposalKey proposal_key = 5;
+ bytes payer = 6;
+ repeated bytes authorizers = 7;
+ repeated Signature payload_signatures = 8;
+ repeated Signature envelope_signatures = 9;
+}
+
+message TransactionProposalKey {
+ bytes address = 1;
+ uint32 key_id = 2;
+ uint64 sequence_number = 3;
+}
+
+message TransactionSignature {
+ bytes address = 1;
+ uint32 key_id = 2;
+ bytes signature = 3;
+}
+```
+
+| Field | Description |
+| ----------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
+| script | Raw source code for a Cadence script, encoded as UTF-8 bytes |
+| arguments | Arguments passed to the Cadence script, encoded as [JSON-Cadence](https://cadencelang.dev/docs/1.0/json-cadence-spec) bytes |
+| reference_block_id | Block ID used to determine transaction expiry |
+| [proposal_key](#proposal-key) | Account key used to propose the transaction |
+| payer | Address of the payer account |
+| authorizers | Addresses of the transaction authorizers |
+| signatures | [Signatures](#transaction-signature) from all signer accounts |
+
+The detailed semantics of transaction creation, signing and submission are covered in the [transaction submission guide](../../build/basics/transactions.md#signing-a-transaction).
+
+#### Proposal Key
+
+The proposal key is used to specify a sequence number for the transaction. Sequence numbers are covered in more detail [here](../../build/basics/transactions.md#sequence-numbers).
+
+| Field | Description |
+| --------------- | ------------------------------------------------------------------------------------------- |
+| address | Address of proposer account |
+| key_id | ID of proposal key on the proposal account |
+| sequence_number | [Sequence number](../../build/basics/transactions.md#sequence-numbers) for the proposal key |
+
+#### Transaction Signature
+
+| Field | Description |
+| --------- | ----------------------------------------- |
+| address | Address of the account for this signature |
+| key_id | ID of the account key |
+| signature | Raw signature byte data |
+
+#### Transaction Status
+
+```proto
+enum TransactionStatus {
+ UNKNOWN = 0;
+ PENDING = 1;
+ FINALIZED = 2;
+ EXECUTED = 3;
+ SEALED = 4;
+ EXPIRED = 5;
+}
+```
+
+| Value | Description |
+| --------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
+| UNKNOWN | The transaction status is not known. |
+| PENDING | The transaction has been received by a collector but not yet finalized in a block. |
+| FINALIZED | The consensus nodes have finalized the block that the transaction is included in |
+| EXECUTED | The execution nodes have produced a result for the transaction |
+| SEALED | The verification nodes have verified the transaction (the block in which the transaction is) and the seal is included in the latest block |
+| EXPIRED | The transaction was submitted past its expiration block height. |
+
+### Account
+
+An account is a user's identity on Flow. It contains a unique address, a balance, a list of public keys and the code that has been deployed to the account.
+
+```proto
+message Account {
+ bytes address = 1;
+ uint64 balance = 2;
+ bytes code = 3;
+ repeated AccountKey keys = 4;
+ map contracts = 5;
+}
+```
+
+| Field | Description |
+| --------- | --------------------------------------------------------------------------- |
+| address | A unique account identifier |
+| balance | The account balance |
+| code | The code deployed to this account (**deprecated**, use `contracts` instead) |
+| keys | A list of keys configured on this account |
+| contracts | A map of contracts or contract interfaces deployed on this account |
+
+The `code` and `contracts` fields contain the raw Cadence source code, encoded as UTF-8 bytes.
+
+More information on accounts can be found [here](../../build/basics/accounts.md).
+
+#### Account Key
+
+An account key is a reference to a public key associated with a Flow account. Accounts can be configured with zero or more public keys, each of which can be used for signature verification when authorizing a transaction.
+
+```proto
+message AccountKey {
+ uint32 index = 1;
+ bytes public_key = 2;
+ uint32 sign_algo = 3;
+ uint32 hash_algo = 4;
+ uint32 weight = 5;
+ uint32 sequence_number = 6;
+ bool revoked = 7;
+}
+```
+
+| Field | Description |
+| --------------- |---------------------------------------------------------------------------|
+| id | Index of the key within the account, used as a unique identifier |
+| public_key | Public key encoded as bytes |
+| sign_algo | [Signature algorithm](../../build/basics/accounts.md#signature-and-hash-algorithms) |
+| hash_algo | [Hash algorithm](../../build/basics/accounts.md#signature-and-hash-algorithms) |
+| weight | [Weight assigned to the key](../../build/basics/accounts.md#account-keys) |
+| sequence_number | [Sequence number for the key](../../build/basics/transactions.md#sequence-numbers) |
+| revoked | Flag indicating whether or not the key has been revoked |
+
+More information on account keys, key weights and sequence numbers can be found [here](../../build/basics/accounts.md).
+
+### Event
+
+An event is emitted as the result of a [transaction](#transaction) execution. Events are either user-defined events originating from a Cadence smart contract, or built-in Flow system events.
+
+```proto
+message Event {
+ string type = 1;
+ bytes transaction_id = 2;
+ uint32 transaction_index = 3;
+ uint32 event_index = 4;
+ bytes payload = 5;
+}
+```
+
+| Field | Description |
+| ----------------- | ------------------------------------------------------------------------------------------------- |
+| type | Fully-qualified unique type identifier for the event |
+| transaction_id | ID of the transaction the event was emitted from |
+| transaction_index | Zero-based index of the transaction within the block |
+| event_index | Zero-based index of the event within the transaction |
+| payload | Event fields encoded as [JSON-Cadence values](https://cadencelang.dev/docs/1.0/json-cadence-spec) |
+
+### Execution Result
+
+Execution result for a particular block.
+
+```proto
+message ExecutionResult {
+ bytes previous_result_id = 1;
+ bytes block_id = 2;
+ repeated Chunk chunks = 3;
+ repeated ServiceEvent service_events = 4;
+}
+```
+
+| Field | Description |
+| ------------------ | ---------------------------------------------------- |
+| previous_result_id | Identifier of parent block execution result |
+| block_id | ID of the block this execution result corresponds to |
+| chunks | Zero or more chunks |
+| service_events | Zero or more service events |
+
+### Execution Receipt Meta
+
+ExecutionReceiptMeta contains the fields from the Execution Receipts that vary from one executor to another
+
+```proto
+message ExecutionReceiptMeta {
+ bytes executor_id = 1;
+ bytes result_id = 2;
+ repeated bytes spocks = 3;
+ bytes executor_signature = 4;
+}
+```
+
+| Field | Description |
+|----------------------|--------------------------------------|
+| executor_id | Identifier of the executor node |
+| result_id | Identifier of block execution result |
+| spocks | SPoCK |
+| executor_signature | Signature of the executor |
+
+#### Chunk
+
+Chunk described execution information for given collection in a block
+
+```proto
+message Chunk {
+ uint32 CollectionIndex = 1;
+ bytes start_state = 2;
+ bytes event_collection = 3;
+ bytes block_id = 4;
+ uint64 total_computation_used = 5;
+ uint32 number_of_transactions = 6;
+ uint64 index = 7;
+ bytes end_state = 8;
+ bytes execution_data_id = 9;
+ bytes state_delta_commitment = 10;
+}
+```
+
+| Field | Description |
+|-------------------------|------------------------------------------------------|
+| CollectionIndex | Identifier of a collection |
+| start_state | State commitment at start of the chunk |
+| event_collection | Hash of events emitted by transactions in this chunk |
+| block_id | Identifier of a block |
+| total_computation_used | Total computation used by transactions in this chunk |
+| number_of_transactions | Number of transactions in a chunk |
+| index | Index of chunk inside a block (zero-based) |
+| end_state | State commitment after executing chunk |
+| execution_data_id | Identifier of a execution data |
+| state_delta_commitment | A commitment over sorted list of register changes |
+
+#### Service Event
+
+Special type of events emitted in system chunk used for controlling Flow system.
+
+```proto
+message ServiceEvent {
+ string type = 1;
+ bytes payload = 2;
+}
+```
+
+| Field | Description |
+| ------- | ----------------------------------- |
+| type | Type of an event |
+| payload | JSON-serialized content of an event |
+
+## Subscriptions
+
+### SubscribeEvents
+
+`SubscribeEvents` streams events for all blocks starting at the requested start block, up until the latest available block. Once the latest is
+reached, the stream will remain open and responses are sent for each new block as it becomes available.
+
+Events within each block are filtered by the provided [EventFilter](#eventfilter), and only those events that match the filter are returned. If no filter is provided,
+all events are returned.
+
+Responses are returned for each block containing at least one event that matches the filter. Additionally, heatbeat responses (SubscribeEventsResponse
+with no events) are returned periodically to allow clients to track which blocks were searched. Clients can use this information to determine
+which block to start from when reconnecting.
+
+```proto
+rpc SubscribeEvents(SubscribeEventsRequest) returns (stream SubscribeEventsResponse)
+```
+
+#### Request
+
+```proto
+message SubscribeEventsRequest {
+ bytes start_block_id = 1;
+ uint64 start_block_height = 2;
+ EventFilter filter = 3;
+ uint64 heartbeat_interval = 4;
+ entities.EventEncodingVersion event_encoding_version = 5;
+}
+```
+
+| Field | Description |
+| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| start_block_id | The first block to search for events. Only one of start_block_id and start_block_height may be provided, otherwise an InvalidArgument error is returned. If neither are provided, the latest sealed block is used |
+| start_block_height | Block height of the first block to search for events. Only one of start_block_id and start_block_height may be provided, otherwise an InvalidArgument error is returned. If neither are provided, the latest sealed block is used |
+| filter | Filter to apply to events for each block searched. If no filter is provided, all events are returned |
+| heartbeat_interval | Interval in block heights at which the server should return a heartbeat message to the client |
+| event_encoding_version | Preferred event encoding version of the block events payload. Possible variants: CCF, JSON-CDC |
+
+#### Response
+
+```proto
+message SubscribeEventsResponse {
+ bytes block_id = 1;
+ uint64 block_height = 2;
+ repeated entities.Event events = 3;
+ google.protobuf.Timestamp block_timestamp = 4;
+ uint64 message_index = 5;
+}
+```
+
+### SubscribeExecutionData
+
+`SubscribeExecutionData` streams execution data for all blocks starting at the requested start block, up until the latest available block. Once the latest is reached, the stream will remain open and responses are sent for each new execution data as it becomes available.
+
+```proto
+rpc SubscribeExecutionData(SubscribeExecutionDataRequest) returns (stream SubscribeExecutionDataResponse)
+```
+
+#### Request
+
+```proto
+message SubscribeExecutionDataRequest {
+ bytes start_block_id = 1;
+ uint64 start_block_height = 2;
+ entities.EventEncodingVersion event_encoding_version = 3;
+}
+```
+
+| Field | Description |
+| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| start_block_id | The first block to get execution data for. Only one of start_block_id and start_block_height may be provided, otherwise an InvalidArgument error is returned. If neither are provided, the latest sealed block is used |
+| start_block_height | Block height of the first block to get execution data for. Only one of start_block_id and start_block_height may be provided, otherwise an InvalidArgument error is returned. If neither are provided, the latest sealed block is used |
+| event_encoding_version | Preferred event encoding version of the block events payload. Possible variants: CCF, JSON-CDC |
+
+#### Response
+
+```proto
+message SubscribeExecutionDataResponse {
+ uint64 block_height = 1;
+ entities.BlockExecutionData block_execution_data = 2;
+ google.protobuf.Timestamp block_timestamp = 3;
+}
+```
+
+## Execution data
+
+### EventFilter
+
+`EventFilter` defines the filter to apply to block events. Filters are applied as an OR operation, i.e. any event matching any of the filters is returned.
+If no filters are provided, all events are returned. If there are any invalid filters, the API will return an InvalidArgument error.
+
+```proto
+message EventFilter {
+ repeated string event_type = 1;
+ repeated string contract = 2;
+ repeated string address = 3;
+}
+```
+
+| Field | Description |
+| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| event_type | A list of full event types to include. Event types have 2 formats: _ Protocol events: `flow.[event name]` _ Smart contract events: `A.[contract address].[contract name].[event name]` |
+| contract | A list of contracts who's events should be included. Contracts have the following name formats: _ Protocol events: `flow` _ Smart contract events: `A.[contract address].[contract name]` This filter matches on the full contract including its address, not just the contract's name |
+| address | A list of addresses who's events should be included. Addresses must be Flow account addresses in hex format and valid for the network the node is connected to. i.e. only a mainnet address is valid for a mainnet node. Addresses may optionally include the `0x` prefix |
+
+
+## Execution data streaming API
+
+### Execution Data API
+
+The `ExecutionDataAPI` provides access to block execution data over gRPC, including transactions, events, and register data (account state). It’s an optional API, which makes use of the Execution Sync protocol to trustlessly download data from peers on the network.
+
+[execution data protobuf file](https://github.com/onflow/flow/blob/master/protobuf/flow/executiondata/executiondata.proto)
+
+
+> The API is disabled by default. To enable it, specify a listener address with the cli flag `--state-stream-addr`.
+
+
+
+ℹ️ Currently, the api must be started on a separate port from the regular gRPC endpoint. There is work underway to add support for using the same port.
+
+
+
+Below is a list of the available CLI flags to control the behavior of the API
+
+| Flag | Type | Description |
+|----------------------------------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| state-stream-addr | string | Listener address for API. e.g. 0.0.0.0:9003. If no value is provided, the API is disabled. Default is disabled. |
+| execution-data-cache-size | uint32 | Number of block execution data objects to store in the cache. Default is 100. |
+| state-stream-global-max-streams | uint32 | Global maximum number of concurrent streams. Default is 1000. |
+| state-stream-max-message-size | uint | Maximum size for a gRPC response message containing block execution data. Default is 20*1024*1024 (20MB). |
+| state-stream-event-filter-limits | string | Event filter limits for ExecutionData SubscribeEvents API. These define the max number of filters for each type. e.g. EventTypes=100,Addresses=20,Contracts=50. Default is 1000 for each. |
+| state-stream-send-timeout | duration | Maximum wait before timing out while sending a response to a streaming client. Default is 30s. |
+| state-stream-send-buffer-size | uint | Maximum number of unsent responses to buffer for a stream. Default is 10. |
+| state-stream-response-limit | float64 | Max number of responses per second to send over streaming endpoints. This effectively applies a rate limit to responses to help manage resources consumed by each client. This is mostly used when clients are querying data past data. e.g. 3 or 0.5. Default is 0 which means no limit. |
+
+
+ℹ️ This API provides access to Execution Data, which can be very large (100s of MB) for a given block. Given the large amount of data, operators should consider their expected usage patters and tune the available settings to limit the resources a single client can use. It may also be useful to use other means of managing traffic, such as reverse proxies or QoS tools.
+
+
+
+=== networks/access-onchain-data/access-http-api.md ===
+---
+redirect: /http-api
+title: Access HTTP API ↗️
+sidebar_position: 2
+---
+
+# Access HTTP API
+
+Go to [HTTP API](/http-api)
+
+
+
+
+=== networks/access-onchain-data/websockets-stream-api/unsubscribe-message.md ===
+---
+title: Unsubscribe request message format
+sidebar_label: Unsubscribing from topic
+sidebar_position: 3
+---
+
+# Unsubscribe message format
+
+Unsubscribe requests must be sent as JSON in text frames, one request per frame.
+
+### Example of unsubscribe request
+
+```json
+{
+ "subscription_id": "some-id-1",
+ "action": "unsubscribe"
+}
+```
+
+### Example of successful response
+
+```json
+{
+ "subscription_id": "some-id-1",
+ "action": "unsubscribe"
+}
+```
+
+### Example of error response
+
+```json
+{
+ "error": {
+ "code": 404,
+ "message": "subscription not found"
+ }
+}
+```
+
+### Request fields
+
+| Name | Type | Required | Description |
+|-------------------|--------|----------|-----------------------------------------------------------------------|
+| `subscription_id` | STRING | YES | Unique identifier of the subscription |
+| `action` | STRING | YES | Action to perform. Must be `unsubscribe` to initiate a unsubscription |
+
+
+=== networks/access-onchain-data/websockets-stream-api/subscribe-message.md ===
+---
+title: Subscribe request message format
+sidebar_label: Subscribing to topic
+sidebar_position: 2
+---
+
+# Subscribe request format
+
+Subscribe requests must be sent as JSON in text frames, one request per frame.
+
+
+### Example of subscribe request
+
+```json
+{
+ "subscription_id": "some-id-1",
+ "action": "subscribe",
+ "topic": "block_digests",
+ "arguments": {
+ "block_status": "finalized",
+ "start_block_height": "99416580"
+ }
+}
+```
+
+### Example of successful response
+
+```json
+{
+ "subscription_id": "some-id-1",
+ "action": "subscribe"
+}
+```
+
+### Example of failed response
+
+```json
+{
+ "subscription_id": "some-id-1",
+ "error": {
+ "code": 400,
+ "message": "invalid message"
+ }
+}
+```
+
+### Example of messages provided by subscription (if successful)
+
+```json
+{
+ "subscription_id": "some-id-1",
+ "topic": "block_digests",
+ "payload": {
+ "id": "0x1234...",
+ "height:": "123456789",
+ "timestamp": "2025-01-02T10:00:00Z"
+ }
+}
+```
+
+### Example of messages provided by subscription (if error)
+
+```json
+{
+ "subscription_id": "some-id-1",
+ "error": {
+ "code": 500,
+ "message": "internal error"
+ }
+}
+```
+
+### Request fields:
+
+| Name | Type | Required | Description |
+| ----------------- | ------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `subscription_id` | STRING | NO | Optional unique identifier for the subscription. Max length of ID generated by client is 20 characters. Server will generate a unique ID if omitted |
+| `action` | STRING | YES | Action to perform. Must be `subscribe` to initiate a subscription |
+| `topic` | STRING | YES | The topic to subscribe to, such as `blocks`, `block_digests`, etc. See more details on [Supported Topics](supported-topics/index.md) page. |
+| `arguments` | STRING | NO | Additional topic specific parameters for the subscription, such as `start_block_id`, `start_block_height` or other. |
+
+You can use `subscription_id` as a client-generated identifier to track responses asynchronously.
+If you don't provide `subscription_id`, the server will generate one and include it in the response.
+
+
+=== networks/access-onchain-data/websockets-stream-api/postman-example.md ===
+---
+title: Connecting to WebSockets via Postman UI
+sidebar_label: Connecting to WebSockets via Postman UI
+sidebar_position: 6
+---
+
+This tutorial will guide you through connecting to a WebSocket using Postman and sending a subscription message.
+
+## Step 1: Open Postman
+
+Ensure you have Postman installed and opened on your system. If you don’t have it yet, download it from [Postman’s official website](https://www.postman.com/downloads/).
+
+## Step 2: Create a New WebSocket Request
+
+1. In Postman, click on **File** > **New...** > **WebSocket**.
+![pe_1]()
+2. Enter the WebSocket URL in **Enter URL** field : `wss://rest-mainnet.onflow.org/v1/ws` or `wss://rest-testnet.onflow.org/v1/ws`
+3. Click **Connect** button to establish the WebSocket connection.
+![pe_2]()
+
+## Step 3: Send a Subscription Message
+
+1. Once connected, go to the **Messages** tab.
+2. Enter the JSON message into the text box. In this example the [digests block subscription](./supported-topics/block_digests_topic.md) will be established. For other available topics check [Supported topics page](./supported-topics/index.md).
+3. Click **Send** to subscribe to the WebSocket topic.
+![pe_3]()
+
+## Step 4: View Responses
+
+- After sending the message, you should start receiving responses in the **Response** bottom tab.
+- Each message received from the server will be displayed in real-time.
+
+![pe_4]()
+
+## Step 5: Disconnect
+
+- When you are done, click **Disconnect** to close the WebSocket connection.
+
+## Troubleshooting
+
+- Ensure WebSocket URL is correct and active.
+- In case of an error validate your JSON message for any syntax errors before sending and check correctness of all arguments on [Supported topics page](./supported-topics/index.md).
+
+Congratulations! You have successfully connected to a WebSocket server using Postman and sent a subscription message.
+
+
+
+
+
+
+
+
+
+=== networks/access-onchain-data/websockets-stream-api/list-subscriptions-message.md ===
+---
+title: List subscriptions request message format
+sidebar_label: Listing subscriptions
+sidebar_position: 5
+---
+
+# List subscriptions message format
+
+List subscriptions requests must be sent as JSON in text frames, one request per frame.
+This message is different from others as it doesn't require you to provide subscription ID.
+Thus, the response for this message is different too.
+
+### Example of request
+
+```json
+{
+ "action": "list_subscriptions"
+}
+```
+
+### Example of response
+
+```json
+{
+ "subscriptions": [
+ {
+ "subscription_id": "some-id-1",
+ "topic": "blocks",
+ "arguments": {
+ "block_status": "finalized",
+ "start_block_height": "123456789"
+ }
+ },
+ {
+ "subscription_id": "some-id-2",
+ "topic": "events",
+ "arguments": {}
+ }
+ ]
+}
+```
+
+If there are no active subscriptions, `subscriptions` array will be empty.
+
+### Request fields
+
+| Name | Type | Required | Description |
+|----------|--------|----------|-----------------------------------------------------------------------------------------|
+| `action` | STRING | YES | Action to perform. Must be `list_subscriptions` to initiate a list subscription request |
+
+
+=== networks/access-onchain-data/websockets-stream-api/index.md ===
+---
+title: Overview
+sidebar_label: Overview
+sidebar_position: 1
+---
+
+# Websockets Stream API
+
+## Overview
+
+The Stream API allows clients to receive real-time updates from the Flow blockchain via WebSocket connections. It
+supports subscribing to various topics, such as blocks, events, and transactions, enabling low-latency access to live
+data.
+
+### Important Information
+
+- **Endpoint**: The WebSocket server is available at:
+ - Mainnet: `wss://rest-mainnet.onflow.org/v1/ws`
+ - Testnet: `wss://rest-testnet.onflow.org/v1/ws`
+- **Limits**:
+ - Each connection supports up to 20 concurrent subscriptions. Exceeding this limit will result in an error.
+ - Each subscription may provide up to 20 responses per second.
+ - After 1 minute of inactivity (no data sent or received) the connection is closed.
+
+- **Supported Topics**: See more details on [Supported Topics](supported-topics/index.md) page.
+ - [`block_digests`](supported-topics/block_digests_topic.md)
+ - [`block_headers`](supported-topics/block_headers_topic.md)
+ - [`blocks`](supported-topics/blocks_topic.md)
+ - [`events`](supported-topics/events_topic.md)
+ - [`account_statuses`](supported-topics/account_statuses_topic.md)
+ - [`transaction_statuses`](supported-topics/transaction_statuses_topic.md)
+ - [`send_and_get_transaction_statuses`](supported-topics/send_and_get_transaction_statuses_topic.md)
+
+- **Notes**: Always handle errors gracefully and close unused subscriptions to maintain efficient connections.
+
+---
+
+## Setting Up a WebSocket Connection
+
+Use any WebSocket client library to connect to the endpoint. Below is an example using JavaScript:
+
+```javascript
+const ws = new WebSocket('wss://rest-mainnet.onflow.org/ws');
+
+ws.onopen = () => {
+ console.log('Connected to WebSocket server');
+};
+
+ws.onclose = () => {
+ console.log('Disconnected from WebSocket server');
+};
+
+ws.onerror = (error) => {
+ console.error('WebSocket error:', error);
+};
+```
+
+---
+
+## Subscribing to Topics
+
+To receive data from a specific topic, send a subscription request in JSON format over the WebSocket connection.
+
+### Request Format
+
+```json
+{
+ "subscription_id": "some-id-42",
+ "action": "subscribe",
+ "topic": "blocks",
+ "arguments": {
+ "block_status": "sealed",
+ "start_block_height": "123456789"
+ }
+}
+```
+
+- **`subscription_id`**(optional): A unique identifier for the subscription (a string with maximum length constraint of 20 characters). If omitted, the server generates one.
+- **`action`**: The action to perform. Supported actions include: `subscribe`, `unsubscribe`, `list_subscriptions`.
+- **`topic`**: The topic to subscribe to. See the supported topics in the Overview.
+- **`arguments`**: Additional topic specific arguments for subscriptions, such as `start_block_height`, `start_block_id`, and others. See more details about arguments for each topic on [Supported Topics](supported-topics/index.md) page.
+
+### Successful Response Format
+
+```json
+{
+ "subscription_id": "some-id-42",
+ "action": "subscribe"
+}
+```
+
+---
+
+## Unsubscribing from Topics
+
+To stop receiving data from a specific topic, send an unsubscribe request.
+
+### Request Format
+
+```json
+{
+ "subscription_id": "some-id-42",
+ "action": "unsubscribe"
+}
+```
+
+### Successful Response Format
+
+```json
+{
+ "subscription_id": "some-id-42",
+ "action": "unsubscribe"
+}
+```
+
+---
+
+## Listing Active Subscriptions
+
+You can retrieve a list of all active subscriptions for the current WebSocket connection.
+
+### Request Format
+
+```json
+{
+ "action": "list_subscriptions"
+}
+```
+
+### Successful Response Format
+
+```json
+{
+ "subscriptions": [
+ {
+ "subscription_id": "some-id-1",
+ "topic": "blocks",
+ "arguments": {
+ "block_status": "sealed",
+ "start_block_height": "123456789"
+ }
+ },
+ {
+ "subscription_id": "some-id-2",
+ "topic": "events",
+ "arguments": {}
+ }
+ ]
+}
+```
+
+---
+
+## Errors Example
+
+If a request is invalid or cannot be processed, the server responds with an error message.
+
+### OK Response
+
+```json
+{
+ "subscription_id": "some-id-42",
+ "topic": "block_digests",
+ "payload": {
+ "id": "0x1234...",
+ "height:": "123456789",
+ "timestamp": "2025-01-02T10:00:00Z"
+ }
+}
+```
+
+### Error Response
+
+```json
+{
+ "subscription_id": "some-id-42",
+ "error": {
+ "code": 500,
+ "message": "Access Node failed"
+ }
+}
+```
+
+### Common Error Codes
+
+- **400**: Invalid message format or arguments
+- **404**: Subscription not found
+- **500**: Internal server error
+
+### Asynchronous environments
+
+If you're working in an asynchronous environment, the Streaming API ensures **first-in first-out** message processing,
+so responses will be returned in the same order the requests were received over the connection.
+You can leverage this feature to simplify your code and maintain consistency.
+
+Additionally, you can specify a custom `subscription_id` in the subscribe request to easily identify the correct response. It must not be an empty string and must follow a maximum length constraint of 20 characters.
+
+=== networks/access-onchain-data/websockets-stream-api/common-errors.md ===
+---
+title: Common errors
+sidebar_label: Common errors
+sidebar_position: 7
+---
+
+This document outlines the possible errors returned from the WebSocket API. Understanding these errors will help properly handle error cases in client implementation.
+
+## Error Structure
+
+All errors returned by the WebSocket API follow this structure:
+
+```json
+{
+ "subscriptionID": "string",
+ "error": {
+ "code": number,
+ "message": "string"
+ },
+ "action": "string"
+}
+```
+
+Where:
+- `subscriptionID`: The ID of the subscription related to the error (if applicable)
+- `error.code`: HTTP status code indicating the error type
+- `error.message`: Human-readable description of the error
+- `action`: The action that was being performed when the error occurred (`subscribe`, `unsubscribe`, or `list_subscription`)
+
+
+### Message Format Errors
+
+**Status Code:** 400 Bad Request
+
+These errors occur when the server cannot parse or validate your incoming message.
+
+| Error Message | Description | When to Expect |
+|---------------|-------------|---------------|
+| *"error reading message: ..."* | The raw message could not be read from the WebSocket connection | When sending malformed JSON or when the connection is disrupted |
+| *"error parsing message: ..."* | The message was read but could not be processed | When the message structure doesn't match the expected format |
+| *"error unmarshalling base message: ..."* | The message JSON could not be processed into the expected format | When required fields are missing or of incorrect type |
+| *"error unmarshalling subscribe message: ..."* | The message JSON could not be processed into a subscribe request | When sending a malformed subscribe request |
+| *"error unmarshalling unsubscribe message: ..."* | The message JSON could not be processed into an unsubscribe request | When sending a malformed unsubscribe request |
+| *"error unmarshalling list subscriptions message: ..."* | The message JSON could not be processed into a list subscriptions request | When sending a malformed list subscriptions request |
+| *"unknown action type: ..."* | The action specified in the message is not recognized | When specifying an action other than `subscribe`, `unsubscribe`, or `list_subscription` |
+
+## Subscription-Related Errors
+
+### Subscribe Action Errors
+
+**Action:** `subscribe`
+
+| Error Message | Status Code | Description | When to Expect |
+|---------------|-------------|-------------|---------------|
+| *"error creating new subscription: maximum number of subscriptions reached"* | 429 Too Many Requests | The maximum number of active subscriptions per connection has been reached | When trying to create more subscriptions than allowed by the server |
+| *"error parsing subscription id: ..."* | 400 Bad Request | The provided subscription ID is invalid | When providing a malformed subscription ID |
+| *"subscription ID is already in use: ..."* | 400 Bad Request | The provided subscription ID is already being used | When trying to reuse an existing subscription ID |
+| *"error creating data provider: ..."* | 400 Bad Request | The subscription could not be created | When providing an invalid topic or arguments for your subscription |
+
+### Unsubscribe Action Errors
+
+**Action:** "unsubscribe"
+
+| Error Message | Status Code | Description | When to Expect |
+|---------------|-------------|-------------|---------------|
+| *"error parsing subscription id: ..."* | 400 Bad Request | The provided subscription ID is invalid | When providing a malformed subscription ID |
+| *"subscription not found"* | 404 Not Found | The specified subscription does not exist | When trying to unsubscribe from a non-existent subscription |
+
+### Subscription Runtime Errors
+
+**Action:** "subscribe"
+
+| Error Message | Status Code | Description | When to Expect |
+|---------------|-------------|-------------|---------------|
+| *"internal error: ..."* | 500 Internal Server Error | An error occurred while processing your subscription | When there's an issue with the subscription after it was successfully created |
+
+## Error Handling Best Practices
+
+1. **Always check for errors in responses**: Every response from the WebSocket API should be checked for the presence of an error object.
+
+2. **Handle subscription limits**: Be prepared to handle the case where the maximum number of subscriptions has been reached.
+
+3. **Log detailed error information**: Log the complete error object for debugging purposes.
+
+4. **Validate messages before sending**: Ensure your messages conform to the expected format to avoid parsing errors.
+
+=== networks/access-onchain-data/websockets-stream-api/supported-topics/transaction_statuses_topic.md ===
+---
+title: Transaction statuses
+sidebar_label: Transaction statuses
+sidebar_position: 7
+---
+
+Provides updates on transaction status changes for already sent transactions.
+
+## Example Request
+
+```json
+{
+ "subscription_id": "some-id",
+ "action": "subscribe",
+ "topic": "transaction_statuses",
+ "arguments": {
+ "tx_id": "fe3784095bc194dca02e4b14e7e6a1e0519d10b7bc907453e5b5dc276259a106"
+ }
+}
+```
+
+### Request Arguments
+
+| Name | Type | Required | Description |
+| ------- | ------ | -------- | -------------------------------------------------------- |
+| `tx_id` | STRING | YES | The ID of the transaction to monitor for status changes. |
+
+
+## Example Response
+
+```json
+{
+ "subscription_id": "some-id",
+ "topic": "transaction_statuses",
+ "payload": {
+ "transaction_result": {
+ "block_id": "b668e472c404e471cba8bab5246ca98f90d8492e80c81aae4cccbfae6e734aad",
+ "collection_id": "efdcbf3b2b02b20cdfa7f2669034da05e44232ea68e41d3ed14756472081f9b9",
+ "execution": "Success",
+ "status": "Sealed",
+ "status_code": 0,
+ "error_message": "",
+ "computation_used": "0",
+ "events": [
+ {
+ "type": "A.0b2a3299cc857e29.TopShot.Withdraw",
+ "transaction_id": "fe3784095bc194dca02e4b14e7e6a1e0519d10b7bc907453e5b5dc276259a106",
+ "transaction_index": "4",
+ "event_index": "0",
+ "payload": "eyJ2YWx1ZSI6eyJpZCI6IkEuMGIyYTMyOTljYzg1N2UyOS5Ub3BTaG90LldpdGhkcmF3IiwiZmllbGRzIjpbeyJ2YWx1ZSI6eyJ2YWx1ZSI6IjQwOTQ3MzE4IiwidHlwZSI6IlVJbnQ2NCJ9LCJuYW1lIjoiaWQifSx7InZhbHVlIjp7InZhbHVlIjp7InZhbHVlIjoiMHg2N2Q5OTk5MWMxMzRlODQ4IiwidHlwZSI6IkFkZHJlc3MifSwidHlwZSI6Ik9wdGlvbmFsIn0sIm5hbWUiOiJmcm9tIn1dfSwidHlwZSI6IkV2ZW50In0K"
+ },
+ // Full response is cut down due to its large size; see `_links` for the full response. ...
+ {
+ "type": "A.f919ee77447b7497.FlowFees.FeesDeducted",
+ "transaction_id": "fe3784095bc194dca02e4b14e7e6a1e0519d10b7bc907453e5b5dc276259a106",
+ "transaction_index": "4",
+ "event_index": "22",
+ "payload": "eyJ2YWx1ZSI6eyJpZCI6IkEuZjkxOWVlNzc0NDdiNzQ5Ny5GbG93RmVlcy5GZWVzRGVkdWN0ZWQiLCJmaWVsZHMiOlt7InZhbHVlIjp7InZhbHVlIjoiMC4wMDAwNDc5OCIsInR5cGUiOiJVRml4NjQifSwibmFtZSI6ImFtb3VudCJ9LHsidmFsdWUiOnsidmFsdWUiOiIxLjAwMDAwMDAwIiwidHlwZSI6IlVGaXg2NCJ9LCJuYW1lIjoiaW5jbHVzaW9uRWZmb3J0In0seyJ2YWx1ZSI6eyJ2YWx1ZSI6IjAuMDAwMDAxODgiLCJ0eXBlIjoiVUZpeDY0In0sIm5hbWUiOiJleGVjdXRpb25FZmZvcnQifV19LCJ0eXBlIjoiRXZlbnQifQo="
+ }
+ ],
+ "_links": {
+ "_self": "/v1/transaction_results/fe3784095bc194dca02e4b14e7e6a1e0519d10b7bc907453e5b5dc276259a106"
+ }
+ },
+ "message_index": 3
+ }
+}
+```
+
+
+
+=== networks/access-onchain-data/websockets-stream-api/supported-topics/send_and_get_transaction_statuses_topic.md ===
+---
+title: Send and get transaction statuses
+sidebar_label: Send and get transaction statuses
+sidebar_position: 8
+---
+
+Sends a transaction and provides updates on its status changes.
+
+## Example Request
+
+```json
+{
+ "subscription_id": "some-id-7",
+ "action": "subscribe",
+ "topic": "send_and_get_transaction_statuses"
+ "arguments": {
+ "arguments": [],
+ "authorizers": ["dba05362251g43g4"],
+ "envelope_signatures": [
+ {
+ "address": "dba05362251g43g4",
+ "key_index": "0",
+ "signature": "PJPVEOCtPKubTEpPqd4zrrSXo1RhpABAMDuzIchgBje8gyh04XuWY4f/tu+c0llDhOU/5sQBokeOTdygaS6eTQ=="
+ }
+ ],
+ "gas_limit": "1000",
+ "payer": "dba05362251g43g4",
+ "proposal_key": {
+ "address": "dba05362251g43g4",
+ "key_index": "0",
+ "sequence_number": "0"
+ },
+ "reference_block_id": "817d7c1d2c13a4bd37c182747a4116b45cd175c0ba4878071c33f0f278b37dd7",
+ "script": "CgkJCXRyYW5zYWN0aW9uIHsKCQkJCXByZXBhcmUoYWNjOiAmQWNjb3VudCkge30KCQkJCWV4ZWN1dGUgewoJCQkJCWxvZygidGVzdCIpCgkJCQl9CgkJCX0KCQk="
+ }
+}
+```
+
+| Name | Type | REQUIRED | Description |
+| --------------------- | ------ | -------- | ------------------------------------------------------------------------- |
+| `script` | STRING | YES | Base64-encoded content of the Cadence script. |
+| `arguments` | LIST | YES | A list of arguments, each encoded as Base64. |
+| `reference_block_id` | STRING | YES | BlockID for the transaction's reference block |
+| `gas_limit` | STRING | YES | The limit on the amount of computation a transaction can perform. |
+| `payer` | STRING | YES | The 8-byte address of an account. |
+| `proposal_key` | OBJECT | YES | A required object representing the proposal key. |
+| `authorizers` | LIST | YES | A list of authorizers, each represented as a hexadecimal-encoded address. |
+| `payload_signatures` | LIST | NO | A list of Base64-encoded signatures. |
+| `envelope_signatures` | LIST | YES | A list of Base64-encoded signatures. |
+
+## Example Response
+
+```json
+{
+ "subscription_id": "some-id",
+ "topic": "send_and_get_transaction_statuses",
+ "payload": {
+ "transaction_result": {
+ "block_id": "7ad167602487665db095f7cb0b95139e5dcaf3ad2479ee4d14cade35b7d4bbdc",
+ "collection_id": "d0855ed45c16be2831ab9892ec8a9ddfd10a0e01e683466971cfd87c759bf7d1",
+ "execution": "Failure",
+ "status": "Sealed",
+ "status_code": 1,
+ "error_message": "[Error Code: 1009] error caused by: 1 error occurred:\n\t* transaction verification failed: [Error Code: 1006] invalid proposal key: public key 0 on account dba05362251g43g4 does not have a valid signature: [Error Code: 1009] invalid envelope key: public key 0 on account dba05362251g43g4 does not have a valid signature: signature is not valid\n\n",
+ "computation_used": "0",
+ "events": [],
+ "_links": {
+ "_self": "/v1/transaction_results/92014de98466a6304ecd821c95ee2612e248c22419d243e6e3ff4d138dffde04"
+ }
+ },
+ "message_index": 3
+ }
+}
+```
+
+=== networks/access-onchain-data/websockets-stream-api/supported-topics/index.md ===
+---
+title: Supported topics
+sidebar_label: Supported topics
+sidebar_position: 1
+---
+
+# Supported Topics
+
+In this section, there is a list of topics that client can subscribe to in order to receive updates on different states of the Flow blockchain.
+
+It is possible to subscribe to each topic multiple times with different configurations based on input arguments.
+
+The responses for all topics are aligned with the [Flow REST API](/http-api) responses.
+
+=== networks/access-onchain-data/websockets-stream-api/supported-topics/events_topic.md ===
+---
+title: Events
+sidebar_label: Events
+sidebar_position: 5
+---
+
+Provides blockchain events. The response can be configured using additional arguments to filter and retrieve only filtered events instead of all events.
+
+## Example Request
+
+Started from latest block for event types `flow.AccountKeyAdded` and `flow.AccountKeyRemoved`:
+
+```json
+{
+ "subscription_id": "some-id",
+ "action": "subscribe",
+ "topic": "events",
+ "arguments": {
+ "event_types": [
+ "flow.AccountKeyAdded",
+ "flow.AccountKeyRemoved"
+ ]
+ }
+}
+```
+
+Started from block height `106197172` for contracts `A.f919ee77447b7497.FlowFees` and `A.1654653399040a61.FlowToken` with heartbeat interval equal 10 blocks:
+
+```json
+{
+ "subscription_id": "some-id",
+ "action": "subscribe",
+ "topic": "events",
+ "arguments": {
+ "start_block_height": "106197172",
+ "heartbeat_interval": "10",
+ "contracts": [
+ "A.f919ee77447b7497.FlowFees",
+ "A.1654653399040a61.FlowToken"
+ ]
+ }
+}
+```
+
+Started from block id `44774d980c75d9380caaf4c65a2ee6c4bde9a1e6da6aa858fe2dc5e4a7aff773` for account addresses `0xe544175ee0461c4b` and `2d4c3caffbeab845` with heartbeat interval equal 5 blocks:
+
+```json
+{
+ "subscription_id": "some-id",
+ "action": "subscribe",
+ "topic": "events",
+ "arguments": {
+ "start_block_id": "44774d980c75d9380caaf4c65a2ee6c4bde9a1e6da6aa858fe2dc5e4a7aff773",
+ "heartbeat_interval": "5",
+ "addresses": [
+ "0xe544175ee0461c4b",
+ "2d4c3caffbeab845"
+ ]
+ }
+}
+```
+
+### Request Arguments
+
+| Name | Type | Required | Description |
+| -------------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------ |
+| `start_block_id` | STRING | NO | The ID of the block from which the subscription starts. If this argument is set, it is **not** possible to set `start_block_height`. | |
+| `start_block_height` | STRING | NO | The height of the block from which the subscription starts. If this argument is set, it is **not** possible to set `start_block_id` |
+| `heartbeat_interval` | STRING | NO | Maximum number of blocks between messages after which a response with no events is returned. This helps the client track progress for sparse event filters. |
+| `event_types` | LIST | NO | A comma-separated list of event types to include. |
+| `addresses` | LIST | NO | A comma-separated list of addresses who's events should be included. The format could be `"0xe544175ee0461c4b"` or `"e544175ee0461c4b"`. |
+| `contracts` | LIST | NO | A comma-separated list of contracts who's events should be included. The format is `"A.f919ee77447b7497.FlowFees"` |
+
+If neither `start_block_id` nor `start_block_height` is set, the subscription will start from the latest block based on its status.
+
+## Example Response
+
+```json
+{
+ "subscription_id": "some-id",
+ "topic": "events",
+ "payload": {
+ "block_id": "660ce05ff19193a08c24730cdc0d747da76dfcc39fbab523d970270f2d5c9a3c",
+ "block_height": "106197288",
+ "block_timestamp": "2025-03-11T12:46:03.588742664Z",
+ "events": [
+ {
+ "type": "flow.AccountKeyAdded",
+ "transaction_id": "7d9290e54437b4b9a5de416c04af6d597fcf5bf1cefcf618232ad86e5f71322b",
+ "transaction_index": "1",
+ "event_index": "14",
+ "payload": "2IGChNigg0BpUHVibGljS2V5goJpcHVibGljS2V52IvYiQyCcnNpZ25hdHVyZUFsZ29yaXRobdiIQQLYpINBAW1IYXNoQWxnb3JpdGhtgYJocmF3VmFsdWXYiQzYpINBAnJTaWduYXR1cmVBbGdvcml0aG2BgmhyYXdWYWx1ZdiJDNiig0EDdGZsb3cuQWNjb3VudEtleUFkZGVkhYJnYWRkcmVzc9iJA4JpcHVibGljS2V52IhAgmZ3ZWlnaHTYiReCbWhhc2hBbGdvcml0aG3YiEEBgmhrZXlJbmRleNiJBILYiEEDhUhbvtriVP1Dy4KYQBUYNhhKGHoYZhicGHwYwxgYGKcYqxhqGIcYZxiCGKMXGDgYRRjnGGQYjBieGIIYxhiUGIgY+BjjGM0YlxhBGL0Y2hiyGHUY8hjoGBwYMhiUGC4YIxjtGNkYJhgoGPMYNxgmGF0YqhgjGP0YlRh2GMoYTxihGOIYsBizGEsYVIECGwAAABdCgQcAgQPCQA=="
+ },
+ {
+ "type": "flow.AccountKeyAdded",
+ "transaction_id": "7d9290e54437b4b9a5de416c04af6d597fcf5bf1cefcf618232ad86e5f71322b",
+ "transaction_index": "1",
+ "event_index": "15",
+ "payload": "2IGChNigg0BpUHVibGljS2V5goJpcHVibGljS2V52IvYiQyCcnNpZ25hdHVyZUFsZ29yaXRobdiIQQLYpINBAW1IYXNoQWxnb3JpdGhtgYJocmF3VmFsdWXYiQzYpINBAnJTaWduYXR1cmVBbGdvcml0aG2BgmhyYXdWYWx1ZdiJDNiig0EDdGZsb3cuQWNjb3VudEtleUFkZGVkhYJnYWRkcmVzc9iJA4JpcHVibGljS2V52IhAgmZ3ZWlnaHTYiReCbWhhc2hBbGdvcml0aG3YiEEBgmhrZXlJbmRleNiJBILYiEEDhUhbvtriVP1Dy4KYQBg2GMoY4QYYUhiTGNkYjBinGFsYuhiPGEQYcBjrGKoYdRhsGCkYVRivGMIYRxj6GCUYpRj1GJ4YeRipDgoYPBiLGKAYdgkY8RhVGC4YKxhHGDYYVRiqGOcIGGsYOhhwGIgEGKwYyhj4AxgxGLwYpxhuGMQYtxjsGKeBAhsAAAAXSHboAIEDwkEB"
+ },
+ {
+ "type": "flow.AccountKeyAdded",
+ "transaction_id": "7d9290e54437b4b9a5de416c04af6d597fcf5bf1cefcf618232ad86e5f71322b",
+ "transaction_index": "1",
+ "event_index": "16",
+ "payload": "2IGChNigg0BpUHVibGljS2V5goJpcHVibGljS2V52IvYiQyCcnNpZ25hdHVyZUFsZ29yaXRobdiIQQLYpINBAW1IYXNoQWxnb3JpdGhtgYJocmF3VmFsdWXYiQzYpINBAnJTaWduYXR1cmVBbGdvcml0aG2BgmhyYXdWYWx1ZdiJDNiig0EDdGZsb3cuQWNjb3VudEtleUFkZGVkhYJnYWRkcmVzc9iJA4JpcHVibGljS2V52IhAgmZ3ZWlnaHTYiReCbWhhc2hBbGdvcml0aG3YiEEBgmhrZXlJbmRleNiJBILYiEEDhUhbvtriVP1Dy4KYQBjTABhfGC8YmBiZGLoYwBjEGI0YwBjJGJwYVRhxGJ0YxRjKCRj6AxhaEBiEGI0YfBj3GM0YPhiDGFIYrBg/GMgYnBh0GFQYNBhAGFEYZxi/GNMIGB8YeRhEGKQYbRhHGHAYShjyGEYYnhjrGCEYZBjBGLYYYxg5GBwYkoECGgX14QCBA8JBAg=="
+ }
+ ],
+ "message_index": 11
+ }
+}
+```
+
+
+=== networks/access-onchain-data/websockets-stream-api/supported-topics/blocks_topic.md ===
+---
+title: Blocks
+sidebar_label: Blocks
+sidebar_position: 4
+---
+
+Provides full block information each time a new block appears on the blockchain.
+
+## Example Request
+
+Started from latest block:
+
+```json
+{
+ "subscription_id": "some-id",
+ "action": "subscribe",
+ "topic": "blocks",
+ "arguments": {
+ "block_status": "sealed"
+ }
+}
+```
+
+Started from block height `106192109`:
+
+```json
+{
+ "subscription_id": "some-id",
+ "action": "subscribe",
+ "topic": "blocks",
+ "arguments": {
+ "block_status": "sealed",
+ "start_block_height": "106192109"
+ }
+}
+```
+
+Started from block id `83a8229cbe552f9b10160163394986dc7d99790ad3fedf7db4153d7d7863a3fa`:
+
+```json
+{
+ "subscription_id": "some-id",
+ "action": "subscribe",
+ "topic": "blocks",
+ "arguments": {
+ "block_status": "sealed",
+ "start_block_id": "83a8229cbe552f9b10160163394986dc7d99790ad3fedf7db4153d7d7863a3fa"
+ }
+}
+```
+
+### Request Arguments
+
+| Name | Type | Required | Description |
+| -------------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------ |
+| `block_status` | STRING | YES | The status of blocks to subscribe to. Supported values are: `sealed`, `finalized`. |
+| `start_block_id` | STRING | NO | The ID of the block from which the subscription starts. If this argument is set, it is **not** possible to set `start_block_height`. | |
+| `start_block_height` | STRING | NO | The height of the block from which the subscription starts. If this argument is set, it is **not** possible to set `start_block_id` |
+
+If neither `start_block_id` nor `start_block_height` is set, the subscription will start from the latest block based on its status.
+
+## Example Response
+
+```json
+{
+ "subscription_id": "some-id",
+ "topic": "blocks",
+ "payload": {
+ "header": {
+ "id": "7a7bc4dc574f67f0dc01a6c96cfbabe73ead23f76ac8130e620996779a500925",
+ "parent_id": "70b7f0a8c14e9f374eaf2f37da4dee7815c8639b3f9e67c301e84cf7fb51070c",
+ "height": "106195712",
+ "timestamp": "2025-03-11T12:25:00.450424315Z",
+ "parent_voter_signature": "+GyIAAAAAAAAAACwobZq2GxrWxPUuNJwo5T1pFWvwcAF4/ue8e7j7eFTcRhtReHV+dWnneyGtJdpuaIagLCEfjHvfItzt3J/kXsbdEFeycVBeznP4LIHs0XWWkeRn+yds4NAM8jltmGGBnvgJ68="
+ },
+ "payload": {
+ "collection_guarantees": [
+ {
+ "collection_id": "74d146368179f95a49531072cda799d1c0905523fd5a35c224eefbd92fab6a90",
+ "signer_indices": "71d9de679d7ff457a0",
+ "signature": ""
+ },
+ {
+ "collection_id": "b4b40fa4bd5a98cc5f61924aa63a98c588f56447cec5bcdad538e0a855f1a0f3",
+ "signer_indices": "710746ee7fd5f7a540",
+ "signature": ""
+ }
+ ],
+ "block_seals": [
+ {
+ "block_id": "71418383aefda2df4da5fabb03d5ff0e8778f83783c5566c1110ba4a4d6e8de3",
+ "result_id": "35f480934324280f6eebd6016b143bc28cecb8f71fcd8262153320ad93b16c61",
+ "final_state": "\"0cc68829215fb9d69641537a317787b4ff805fe07d2f9ce12534b87d7d0f1335\"",
+ "aggregated_approval_signatures": [
+ {
+ "verifier_signatures": [
+ "rF6XjkIxY8lYD1vZvUycBtT+9DNY4d0U+p1q6WxiA8siYuFawrThkEIkLA3lYPjz"
+ ],
+ "signer_ids": [
+ "80a0eaa9eb5fd541b2abbd1b5ffa79f0ae9a36973322556ebd4bdd3e1d9fe4cd"
+ ]
+ },
+ {
+ "verifier_signatures": [
+ "j2Y94dVrZZT1qNuK1ZbTOxj5HfNZxmV5zVBA3uwTKrQ4FFQ6gN0na1nXhZDJN1po"
+ ],
+ "signer_ids": [
+ "e7e46cd698170b1f86bc9116dded0ac7df6ea0d86c41788c599fa77072059ea1"
+ ]
+ },
+ {
+ "verifier_signatures": [
+ "jp1/x2dr+LVS6Wl3ScaabsxD8745sb1kec3FUrj0SVXGEFnS7AUvG5RTKfsdF6m3"
+ ],
+ "signer_ids": [
+ "49c9f946170d5fb40c2af953b1534fae771905865b142ab6ac9685b8ba5b51c1"
+ ]
+ },
+ {
+ "verifier_signatures": [
+ "rogMdMXwEKJvMUxdHcFqseW9VGVmNzya51kI8yoc8M0kPfuRfENqfgY1NuQBVn3N"
+ ],
+ "signer_ids": [
+ "a1e6a5d9385d549f546803566747463e616e1d02ade2fcadba1b49c492ec8f29"
+ ]
+ },
+ {
+ "verifier_signatures": [
+ "seNSZjDBI7P4730jLcMWp1cq5XjSoSao9KLmrevSz2voQ+92Fcf7HqcSIpiF5CLi"
+ ],
+ "signer_ids": [
+ "8f8d77ba98d1606b19fce8f6d35908bfc29ea171c02879162f6755c05e0ca1ee"
+ ]
+ }
+ ]
+ },
+ {
+ "block_id": "9735518c51b170372fc3d04a6e360fef8b7f987fdb5f1e0f84d9a065d21a550c",
+ "result_id": "328efa584043b0042b32b5e53c4d3c56988387440d94e9507d0a8d24a0f31e82",
+ "final_state": "\"e1fb1b23de61b1cd83f22ffbcdd14a1844332d2e730e01df519c43ea3565bc3a\"",
+ "aggregated_approval_signatures": [
+ {
+ "verifier_signatures": [
+ "tchbJMwDd92Ui2UXnGPL20rEsTrkHQIYsYPZDAgR7O/9lRZh/u/5Y/7JN9+AiMwP"
+ ],
+ "signer_ids": [
+ "0a29d8eb288d9bb0a0a4f2f9ff180ec83617659998ce363814048ec1683083e0"
+ ]
+ },
+ {
+ "verifier_signatures": [
+ "q07CVWjMP1ocBmShFFZ9K5SYIwBitF8g5gajVkOJ0t+O8twzbtW7SjWPY8NIWKyp"
+ ],
+ "signer_ids": [
+ "446ae6d5ebdf6bc45aee29ed3b8da8dcf155afff87296401a3c0a28206121bcc"
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "_expandable": {},
+ "_links": {
+ "_self": "/v1/blocks/7a7bc4dc574f67f0dc01a6c96cfbabe73ead23f76ac8130e620996779a500925"
+ },
+ "block_status": "BLOCK_SEALED"
+ }
+}
+```
+
+
+=== networks/access-onchain-data/websockets-stream-api/supported-topics/block_headers_topic.md ===
+---
+title: Block headers
+sidebar_label: Block headers
+sidebar_position: 3
+---
+
+Provides block headers without the payload, each time a new block appears on the blockchain.
+
+## Example Request
+
+Started from latest block:
+
+```json
+{
+ "subscription_id": "some-id",
+ "action": "subscribe",
+ "topic": "block_headers",
+ "arguments": {
+ "block_status": "finalized"
+ }
+}
+```
+
+Started from block height `106195326`:
+
+```json
+{
+ "subscription_id": "some-id",
+ "action": "subscribe",
+ "topic": "block_headers",
+ "arguments": {
+ "block_status": "finalized",
+ "start_block_height": "106195326"
+ }
+}
+```
+
+Started from block id `cb27b014fa105a1e0e64d56cfbe2d7e140f4adf32938e38c3459592d01a72e91`:
+
+```json
+{
+ "subscription_id": "some-id",
+ "action": "subscribe",
+ "topic": "block_headers",
+ "arguments": {
+ "block_status": "finalized",
+ "start_block_id": "cb27b014fa105a1e0e64d56cfbe2d7e140f4adf32938e38c3459592d01a72e91"
+ }
+}
+```
+
+### Request Arguments
+
+| Name | Type | Required | Description |
+| -------------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------ |
+| `block_status` | STRING | YES | The status of blocks to subscribe to. Supported values are: `sealed`, `finalized`. |
+| `start_block_id` | STRING | NO | The ID of the block from which the subscription starts. If this argument is set, it is **not** possible to set `start_block_height`. | |
+| `start_block_height` | STRING | NO | The height of the block from which the subscription starts. If this argument is set, it is **not** possible to set `start_block_id` |
+
+If neither `start_block_id` nor `start_block_height` is set, the subscription will start from the latest block based on its status.
+
+## Example Response
+
+```json
+{
+ "subscription_id": "some-id",
+ "topic": "block_headers",
+ "payload": {
+ "id": "5cd0b1d0a0f0017c25647a6e2454a59aafa90682f2329449a610e19673ba07de",
+ "parent_id": "72ecd7cf6b18488b3597e677c5fa620d2dfad981fdd81b5cdb1851490b0cff56",
+ "height": "106195236",
+ "timestamp": "2025-03-11T12:18:39.702990376Z",
+ "parent_voter_signature": "+GyIAAAAAAAAAACwsabEiORFcP/ru95TABxwxXsxnUtJNoUbGB1xKKNtpR/LNUqDL5TyIQjL3xBl5KtKgLCFde8F5DHtUSGYSQUzaGhv+IoQgh1wgbXlY/soY5T30/HwmrucwD925EKOJAQUj7s="
+ }
+}
+```
+
+
+=== networks/access-onchain-data/websockets-stream-api/supported-topics/block_digests_topic.md ===
+---
+title: Block digests
+sidebar_label: Block digests
+sidebar_position: 2
+---
+
+Provides a summarized version of block information, including only the block ID, height, and timestamp, each time a new block appears on the blockchain.
+
+## Example Request
+
+Started from latest block:
+
+```json
+{
+ "subscription_id": "some-id",
+ "action": "subscribe",
+ "topic": "block_digests",
+ "arguments": {
+ "block_status": "sealed"
+ }
+}
+```
+
+Started from block height `106192109`:
+
+```json
+{
+ "subscription_id": "some-id",
+ "action": "subscribe",
+ "topic": "block_digests",
+ "arguments": {
+ "block_status": "sealed",
+ "start_block_height": "106192109"
+ }
+}
+```
+
+Started from block id `37193c008576c5f9e3fb9738d4cc53c9ca021ca593e437eb79107c13ec5a1758`:
+
+```json
+{
+ "subscription_id": "some-id",
+ "action": "subscribe",
+ "topic": "block_digests",
+ "arguments": {
+ "block_status": "sealed",
+ "start_block_id": "37193c008576c5f9e3fb9738d4cc53c9ca021ca593e437eb79107c13ec5a1758"
+ }
+}
+```
+
+### Request Arguments
+
+| Name | Type | Required | Description |
+| -------------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------ |
+| `block_status` | STRING | YES | The status of blocks to subscribe to. Supported values are: `sealed`, `finalized`. |
+| `start_block_id` | STRING | NO | The ID of the block from which the subscription starts. If this argument is set, `start_block_height` MUST be empty. | |
+| `start_block_height` | STRING | NO | The height of the block from which the subscription starts. If this argument is set, `start_block_id` MUST be empty. |
+
+If neither `start_block_id` nor `start_block_height` is set, the subscription will start from the latest block based on its status.
+
+## Example Response
+
+```json
+{
+ "subscription_id": "some-id",
+ "topic": "block_digests",
+ "payload": {
+ "block_id": "311ca4b8530fad041356ace3ba27cd6ca8bed53d166b4cefdde4c3ae414940d5",
+ "height": "106190012",
+ "timestamp": "2025-03-11T11:08:58.504803374Z"
+ }
+}
+```
+
+=== networks/access-onchain-data/websockets-stream-api/supported-topics/account_statuses_topic.md ===
+---
+title: Account statuses
+sidebar_label: Account statuses
+sidebar_position: 6
+---
+
+Provides accounts statuses updates. The response can be configured using additional arguments to filter and retrieve only filtered account statuses instead of all core account events.
+
+## Example Request
+
+Started from latest block for event types `flow.AccountKeyAdded` and `flow.AccountKeyRemoved`:
+
+```json
+{
+ "subscription_id": "some-id",
+ "action": "subscribe",
+ "topic": "account_statuses",
+ "arguments": {
+ "event_types": [
+ "flow.AccountKeyAdded",
+ "flow.AccountKeyRemoved"
+ ]
+ }
+}
+```
+
+Started from block height `106219488` for all accounts events with heartbeat interval equal 10 blocks:
+
+```json
+{
+ "subscription_id": "some-id",
+ "action": "subscribe",
+ "topic": "account_statuses",
+ "arguments": {
+ "start_block_height": "106219488",
+ "heartbeat_interval": "10"
+ }
+}
+```
+
+Started from block id `f1ba2fb02daf02c7a213b6b0f75774aaf54180ae67fb62bdf22ae37295fe1120` for account addresses `0xe544175ee0461c4b` and `2d4c3caffbeab845` with heartbeat interval equal 5 blocks:
+
+```json
+{
+ "subscription_id": "some-id",
+ "action": "subscribe",
+ "topic": "account_statuses",
+ "arguments": {
+ "start_block_id": "f1ba2fb02daf02c7a213b6b0f75774aaf54180ae67fb62bdf22ae37295fe1120",
+ "heartbeat_interval": "5",
+ "account_addresses": [
+ "0xe544175ee0461c4b",
+ "2d4c3caffbeab845"
+ ]
+ }
+}
+```
+
+### Request Arguments
+
+| Name | Type | Required | Description |
+| -------------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------ |
+| `start_block_id` | STRING | NO | The ID of the block from which the subscription starts. If this argument is set, it is **not** possible to set `start_block_height`. | |
+| `start_block_height` | STRING | NO | The height of the block from which the subscription starts. If this argument is set, it is **not** possible to set `start_block_id` |
+| `heartbeat_interval` | STRING | NO | Maximum number of blocks between messages after which a response with no events is returned. This helps the client track progress for sparse event filters. |
+| `event_types` | LIST | NO | A comma-separated list of event types to include. See the list of possible event types value [below](#the-list-of-possible-core-event-types). |
+| `account_addresses` | LIST | NO | A comma-separated list of addresses who's events should be included. The format could be `"0xe544175ee0461c4b"` or `"e544175ee0461c4b"`. |
+
+If neither `start_block_id` nor `start_block_height` is set, the subscription will start from the latest block based on its status.
+
+#### The list of possible core event types
+
+- `flow.AccountCreated` emitted when a new account gets created.
+- `flow.AccountKeyAdded` emitted when a key gets added to an account.
+- `flow.AccountKeyRemoved` emitted when a key gets removed from an account.
+- `flow.AccountContractAdded` emitted when a contract gets deployed to an account.
+- `flow.AccountContractUpdated` emitted when a contract gets updated on an account.
+- `flow.AccountContractRemoved` emitted when a contract gets removed from an account.
+- `flow.InboxValuePublished` emitted when a Capability is published from an account.
+- `flow.InboxValueUnpublished` emitted when a Capability is unpublished from an account.
+- `flow.InboxValueClaimed` emitted when a Capability is claimed by an account.
+
+## Example Response
+
+```json
+{
+ "subscription_id": "some-id",
+ "topic": "account_statuses",
+ "payload": {
+ "block_id": "ab20d1a3574177e69636eea73e7db4e74cffb2754cb14ca0bf18c2b96e8b68b9",
+ "height": "106219247",
+ "account_events": {
+ "0x37d2b958f6970c48": [
+ {
+ "type": "flow.AccountKeyAdded",
+ "transaction_id": "19af79cf2fe081491f1e7b0bf490869c8baece742c6606b4a51383515131b5f0",
+ "transaction_index": "1",
+ "event_index": "14",
+ "payload": "2IGChNigg0BpUHVibGljS2V5goJpcHVibGljS2V52IvYiQyCcnNpZ25hdHVyZUFsZ29yaXRobdiIQQLYpINBAW1IYXNoQWxnb3JpdGhtgYJocmF3VmFsdWXYiQzYpINBAnJTaWduYXR1cmVBbGdvcml0aG2BgmhyYXdWYWx1ZdiJDNiig0EDdGZsb3cuQWNjb3VudEtleUFkZGVkhYJnYWRkcmVzc9iJA4JpcHVibGljS2V52IhAgmZ3ZWlnaHTYiReCbWhhc2hBbGdvcml0aG3YiEEBgmhrZXlJbmRleNiJBILYiEEDhUg30rlY9pcMSIKYQBjBGFoYKhg8GLoAGEIHGHAYYREYoBirGKsYiRhrGDAY3xiTGLkUGJYYdRixGOwYjxjNGCkAExhRGCoY/xgfEBh/GJ0YtxjBGH8YLxiqGD4JGKIY6xgmDhiUGDEYqRhvGCYY8hitGMEWGKwY6RiEGF4YQRhBGKGBAhsAAAAXSHboAIEBwkA="
+ }
+ ]
+ },
+ "message_index": 4
+ }
+}
+```
+
+
+=== growth/index.md ===
+---
+sidebar_position: 1
+title: Growth
+description: Get advice, support, and resources for each stage of development for your project.
+---
+
+At each stage of your project, you can get advice, support, and resources from the Flow ecosystem. Here's a breakdown of _what you are doing_ and _what support we offer_ at each stage:
+
+## Product Idea
+
+You've got an **idea** for an app, game, or project that you want to build on Flow.
+
+### What you are doing
+
+* Developing the idea in a written format, such as a pitch deck, whitepaper, design doc, or business plan
+* Writing software
+* Joining a hackathon or buildathon
+
+### What support we offer
+
+* Technical support
+* Product support
+* Marketing support for your launch
+* DevRel
+
+## MVP/Demo/Hackathon Project Complete
+
+You've got something that works in a place others can use it and experience key features of your product.
+
+### What you are doing
+
+* Writing software
+* Integrating with service providers
+* Getting user feedback and improving your product
+
+### What support we offer
+
+* Direct contact with Flow Foundation through a DevRel Lead.
+* Feedback and Guidence from the Flow Foundation team
+
+## Live product on mainnet
+
+Real people are using your app regularly and doing the types of things that you are or will eventually generate revenue from (even if it's still a small number of users).
+
+### What you are doing
+
+* Acquiring users
+* Tracking metrics
+* Improving your product
+* Raising funds
+* Micro grants
+
+### What support we offer
+
+* BizDev Support (intros, etc)
+* Dedicated slack or tg channel
+* DevRel
+
+## Product market fit
+
+You've got an app and are meeting the needs of regular customers. Core features are implemented, edge cases are handled, and most of your asterisks are resolved.
+
+### What you are doing
+
+* Acquiring users
+* Tracking metrics
+* Improving your product
+
+### What support we offer
+
+* Fundraising support (intros to investor network)
+* Grants tied to bigger ecosystem milestones
+* DevRel
+
+
+=== evm/using.mdx ===
+---
+title: Using Flow EVM
+sidebar_label: Using Flow EVM
+sidebar_position: 4
+---
+
+import BrowserOnly from '@docusaurus/BrowserOnly';
+import { AddNetworkButton } from '@site/src/components/addNetworkButton';
+
+# Using Flow
+
+## EVM Wallets
+
+Applications deployed to Flow EVM will work with popular EVM-compatible wallets such as [MetaMask](https://chromewebstore.google.com/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn), all you need to do is add the correct [RPC endpoint](./networks) as a custom network.
+
+### [MetaMask](https://metamask.io)
+
+
+ {() => {
+ // ******* If Chain Id changes, update the Chain ID in the AddNetworkButton component *******
+ return ;
+ }}
+
+Manual method: Add Flow EVM as a custom network to MetaMask:
+
+1. Open the MetaMask browser extension
+2. Open the network selection dropdown menu by clicking the dropdown button at the top of the extension
+3. Click the **`Add network`** button
+4. Click **`Add a network manually`**
+5. In the **`Add a network manually`** dialog that appears, enter the following information:
+
+| Name | Value |
+| --------------- | ------------------------------------ |
+| Network Name | Flow EVM |
+| Description | The public RPC url for Flow Mainnet |
+| RPC Endpoint | https://mainnet.evm.nodes.onflow.org |
+| Chain ID | 747 |
+| Currency Symbol | FLOW |
+| Block Explorer | https://evm.flowscan.io/ |
+
+6. Tap the Save button to save Flow EVM as a network.
+
+You should now be able to connect to the Flow EVM by selecting it from the network selection dropdown menu.
+
+To additionally add the Flow EVM Testnet to MetaMask, follow the same steps as above, but use the following information:
+
+| Name | Value |
+| --------------- | ------------------------------------ |
+| Network Name | Flow EVM Testnet |
+| Description | The public RPC url for Flow Testnet |
+| RPC Endpoint | https://testnet.evm.nodes.onflow.org |
+| Chain ID | 545 |
+| Currency Symbol | FLOW |
+| Block Explorer | https://evm-testnet.flowscan.io |
+
+Use the [Flow Testnet Faucet](https://faucet.flow.com/fund-account) to fund your account for testing.
+
+## Flow Native Wallets
+
+### [Flow Wallet](https://wallet.flow.com)
+
+Flow Wallet is available on [Android](https://play.google.com/store/apps/details?id=com.flowfoundation.wallet) and [iOS](https://apps.apple.com/ca/app/flow-wallet-nfts-and-crypto/id6478996750), with desktop support using the Flow Wallet [Chrome extension](https://chromewebstore.google.com/detail/flow-reference-wallet/hpclkefagolihohboafpheddmmgdffjm). In addition to being able to transact in both EVM and Cadence environments, Flow Wallet will also allow you to view and move assets between EVM and Cadence, making it possible to manage all your assets in one place.
+
+To use the Flow Wallet Chrome extension:
+
+1. Open the Flow Wallet browser extension and create your account.
+2. Connect to an app using Flow Wallet.
+
+## EVM Specification
+
+- Flow EVM is a virtual EVM-based blockchain using the latest EVM byte-code interpreter `Geth v1.13`
+- Utilizes `FLOW` token for transactions, with balances denominated in `Atto-FLOW` (1 `FLOW` = 10^18 `Atto-FLOW`)
+- The [EVM Gateway](https://github.com/onflow/flow-evm-gateway) exposes the standard EVM API (Ethereum JSON-RPC)
+- Read more about the implementation in [FLIP 223: EVM integration interface](https://github.com/onflow/flips/blob/main/protocol/20231116-evm-support.md)
+
+## JSON-RPC Methods
+
+
+
+| Method | Status | Notes |
+| ----------------------------------------- | ------ | ----------- |
+| [web3_clientVersion] | ✅ |
+| [web3_sha3] | ✅ |
+| [net_listening] | ✅ |
+| [net_peerCount] | ✅ |
+| [net_version] | ✅ |
+| [eth_accounts] | 🚧 | Unsupported |
+| [eth_blockNumber] | ✅ |
+| [eth_call] | ✅ |
+| [eth_chainId] | ✅ |
+| [eth_coinbase] | ✅ |
+| [eth_estimateGas] | ✅ |
+| [eth_gasPrice] | ✅ |
+| [eth_getBalance] | ✅ |
+| [eth_getBlockByHash] | ✅ |
+| [eth_getBlockByNumber] | ✅ |
+| [eth_getBlockTransactionCountByHash] | ✅ |
+| [eth_getBlockTransactionCountByNumber] | ✅ |
+| [eth_getBlockReceipts] | ✅ |
+| [eth_getCode] | ✅ |
+| [eth_getFilterChanges] | ✅ |
+| [eth_getFilterLogs] | ✅ |
+| [eth_getLogs] | ✅ |
+| [eth_getProof] | 🚧 | Unsupported |
+| [eth_getStorageAt] | ✅ |
+| [eth_getTransactionByBlockHashAndIndex] | ✅ |
+| [eth_getTransactionByBlockNumberAndIndex] | ✅ |
+| [eth_getTransactionByHash] | ✅ |
+| [eth_getTransactionCount] | ✅ |
+| [eth_getTransactionReceipt] | ✅ |
+| [eth_getUncleByBlockHashAndIndex] | ✅ |
+| [eth_getUncleByBlockNumberAndIndex] | ✅ |
+| [eth_getUncleCountByBlockHash] | ✅ |
+| [eth_getUncleCountByBlockNumber] | ✅ | |
+| [eth_newBlockFilter] | ✅ |
+| [eth_newFilter] | ✅ |
+| [eth_newPendingTransactionFilter] | ✅ |
+| [eth_sendRawTransaction] | ✅ |
+| [eth_sendTransaction] | 🚧 | Unsupported |
+| [eth_sign] | 🚧 | Unsupported |
+| [eth_signTransaction] | 🚧 | Unsupported |
+| [eth_syncing] | ✅ |
+| [eth_uninstallFilter] | ✅ |
+| [eth_maxPriorityFeePerGas] | ✅ |
+| [eth_feeHistory] | ✅ |
+| [debug_traceTransaction] | ✅ |
+| [debug_traceBlockByNumber] | ✅ |
+| [debug_traceBlockByHash] | ✅ |
+| [debug_traceCall] | ✅ |
+
+**Legend**: ❌ = not supported. 🚧 = work in progress. ✅ = supported.
+
+Read more about the [EVM Gateway](https://github.com/onflow/flow-evm-gateway) on Flow and how it implements the Ethereum JSON-RPC API.
+
+[web3_clientVersion]: https://ethereum.org/en/developers/docs/apis/json-rpc/#web3_clientversion
+[web3_sha3]: https://ethereum.org/en/developers/docs/apis/json-rpc/#web3_sha3
+[net_listening]: https://ethereum.org/en/developers/docs/apis/json-rpc/#net_listening
+[net_peerCount]: https://ethereum.org/en/developers/docs/apis/json-rpc/#net_peercount
+[net_version]: https://ethereum.org/en/developers/docs/apis/json-rpc/#net_version
+[eth_accounts]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_accounts
+[eth_blockNumber]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_blocknumber
+[eth_call]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_call
+[eth_chainId]: https://eips.ethereum.org/EIPS/eip-695
+[eth_coinbase]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_coinbase
+[eth_compileLLL]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_compilelll
+[eth_compileSerpent]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_compileserpent
+[eth_compileSolidity]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_compile_solidity
+[eth_estimateGas]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_estimategas
+[eth_gasPrice]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gasprice
+[eth_getBalance]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getbalance
+[eth_getBlockByHash]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getblockbyhash
+[eth_getBlockByNumber]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getblockbynumber
+[eth_getBlockTransactionCountByHash]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbyhash
+[eth_getBlockTransactionCountByNumber]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbynumber
+[eth_getCode]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getcode
+[eth_getCompilers]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getcompilers
+[eth_getFilterChanges]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getfilterchanges
+[eth_getFilterLogs]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getfilterlogs
+[eth_getLogs]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getlogs
+[eth_getProof]: https://eips.ethereum.org/EIPS/eip-1186
+[eth_getStorageAt]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getstorageat
+[eth_getTransactionByBlockHashAndIndex]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactionbyblockhashandindex
+[eth_getTransactionByBlockNumberAndIndex]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactionbyblocknumberandindex
+[eth_getTransactionByHash]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactionbyhash
+[eth_getTransactionCount]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactioncount
+[eth_getTransactionReceipt]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactionreceipt
+[eth_getUncleByBlockHashAndIndex]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getunclebyblockhashandindex
+[eth_getUncleByBlockNumberAndIndex]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getunclebyblocknumberandindex
+[eth_getUncleCountByBlockHash]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getunclecountbyblockhash
+[eth_getUncleCountByBlockNumber]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getunclecountbyblocknumber
+[eth_getWork]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getwork
+[eth_hashrate]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_hashrate
+[eth_mining]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_mining
+[eth_newBlockFilter]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_newblockfilter
+[eth_newFilter]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_newfilter
+[eth_newPendingTransactionFilter]: https://openethereum.github.io/JSONRPC-eth-module.html#eth_newpendingtransactionfilter
+[eth_pendingTransactions]: https://github.com/ethereum/wiki/issues/685
+[eth_protocolVersion]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_protocolversion
+[eth_sendRawTransaction]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sendrawtransaction
+[eth_sendTransaction]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sendtransaction
+[eth_sign]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign
+[eth_signTransaction]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_signtransaction
+[eth_signTypedData]: https://eips.ethereum.org/EIPS/eip-712
+[eth_submitHashrate]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_submithashrate
+[eth_submitWork]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_submitwork
+[eth_syncing]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_syncing
+[eth_uninstallFilter]: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_uninstallfilter
+[db_getHex]: https://ethereum.org/en/developers/docs/apis/json-rpc/#db_gethex
+[db_getString]: https://ethereum.org/en/developers/docs/apis/json-rpc/#db_getstring
+[db_putHex]: https://ethereum.org/en/developers/docs/apis/json-rpc/#db_puthex
+[db_putString]: https://ethereum.org/en/developers/docs/apis/json-rpc/#db_putstring
+[shh_addToGroup]: https://ethereum.org/en/developers/docs/apis/json-rpc/#shh_addtogroup
+[shh_getFilterChanges]: https://ethereum.org/en/developers/docs/apis/json-rpc/#shh_getfilterchanges
+[shh_getMessages]: https://ethereum.org/en/developers/docs/apis/json-rpc/#shh_getmessages
+[shh_hasIdentity]: https://ethereum.org/en/developers/docs/apis/json-rpc/#shh_hasidentity
+[shh_newFilter]: https://ethereum.org/en/developers/docs/apis/json-rpc/#shh_newfilter
+[shh_newGroup]: https://ethereum.org/en/developers/docs/apis/json-rpc/#shh_newgroup
+[shh_newIdentity]: https://ethereum.org/en/developers/docs/apis/json-rpc/#shh_newidentity
+[shh_post]: https://ethereum.org/en/developers/docs/apis/json-rpc/#shh_post
+[shh_uninstallFilter]: https://ethereum.org/en/developers/docs/apis/json-rpc/#shh_uninstallfilter
+[shh_version]: https://ethereum.org/en/developers/docs/apis/json-rpc/#shh_post
+[txpool_content]: https://geth.ethereum.org/docs/rpc/ns-txpool#txpool_content
+[txpool_inspect]: https://geth.ethereum.org/docs/rpc/ns-txpool#txpool_inspect
+[txpool_status]: https://geth.ethereum.org/docs/rpc/ns-txpool#txpool_status
+[parity_pendingTransactions]: https://openethereum.github.io/JSONRPC-parity-module#parity_pendingtransactions
+[EIP-1186]: https://eips.ethereum.org/EIPS/eip-1186
+
+
+=== evm/quickstart.md ===
+---
+title: EVM Quickstart
+description: Deploy your first contract on Flow testnet and connect it to a rainbowkit/wagmi/viem app
+sidebar_position: 5
+keywords:
+ - Flow EVM
+ - EVM quickstart
+ - Hardhat
+ - Flowscan
+ - Flow Wallet
+ - smart contracts
+ - contract deployment
+ - Flow Faucet
+ - OpenZeppelin
+ - ERC-20
+---
+
+# EVM Quickstart
+
+Flow EVM is an EVM-equivalent blockchain that combines the advantages of Flow, including security, low-cost gas, and native VRF with compatibility with exiting blockchain applications tools, and contracts. If it works on another EVM-equivalent blockchain, it should work on Flow EVM!
+
+This guide is a self-contained quickstart that will walk you through deploying a contract on Flow EVM testnet with [Hardhat] and testing it with [testnet Flowscan].
+
+If you prefer, check out our tutorials for [Remix] and [Foundry] for information on how to deploy a contract with those platforms.
+
+## Objectives
+
+After completing this guide, you'll be able to:
+
+- Fund a wallet with testnet tokens from the [Flow Faucet]
+- Deploy a contract on Flow EVM Testnet
+- Interact with a contract using [Flowscan]
+- Utilize automatically sponsored gas with the [Flow Wallet] on testnet **and mainnet**
+
+## Prerequisites
+
+### Traditional Cryptocurrency Wallet
+
+EVM [Accounts] created by the Flow wallet have unique properties that allow for powerful features, but they do **not** have recovery phrases or private keys that can be exported in a way that's compatible with [Hardhat]. As a result, you'll need to use a traditional EOA and [MetaMask], or the wallet of your choice, to deploy your contracts.
+
+## Deploy Your Contract
+
+For this exercise, we'll use a [Button Clicker Contract] that's relatively simple, but includes several [OpenZeppelin] contracts. This way, we can walk through the process to configure your project to use these common imports.
+
+:::info
+
+If you **really** want to speedrun this tutorial, fork the [Button Clicker Contract] repo, run `npm install`, add a `.env` with your deploy wallet key as `DEPLOY_WALLET_1`, and deploy with `npx hardhat ignition deploy ./ignition/modules/ClickToken.ts --network flowTestnet`.
+
+Then skip to the frontend section.
+
+:::
+
+### Hardhat Setup
+
+Open a terminal window and navigate either to the folder where you wish to create your project folder, or an empty project folder. Run:
+
+```bash
+npx hardhat init
+```
+
+
+
+Select `Create a TypeScript project (with Viem)`
+
+Enter `.` if you ran the command from an empty folder, or enter a path.
+
+Choose the defaults for the remaining options, then open the project in your editor.
+
+### Environment Setup
+
+Add a `.env` and in it, add an environment variable called `DEPLOY_WALLET_1` with your deployment wallet's [private key].
+
+```text
+DEPLOY_WALLET_1=
+```
+
+:::danger
+
+The [private key] functions the same as the recovery phrase for a wallet. Anyone with the key can drain the wallet at any time! Use separate wallets for development and never commit a key to a repo.
+
+:::
+
+### Hardhat Config
+
+We'll be using [OpenZeppelin Contracts], so install them, then open the project in your editor:
+
+```bash
+npm install --save-dev @openzeppelin/hardhat-upgrades
+npm install --save-dev @nomicfoundation/hardhat-ethers ethers # peer dependencies
+```
+
+Then install the contracts themselves:
+
+```bash
+npm install --save-dev @openzeppelin/contracts
+```
+
+You'll also need `dotenv` to better protect your wallet key, so go ahead and add that too:
+
+```bash
+npm install dotenv
+```
+
+Open `hardhat.config`. Below the imports, add the `require` statements for the contracts and `dotenv`:
+
+```tsx
+require('@openzeppelin/hardhat-upgrades');
+require('dotenv').config();
+```
+
+The default config is pretty bare. We'll need to add quite a few items. We'll do these one at a time, then provide a complete copy at the end.
+
+First, add a `networks` property containing the network information for Flow Testnet and Mainnet:
+
+```tsx
+networks: {
+ flow: {
+ url: 'https://mainnet.evm.nodes.onflow.org',
+ accounts: [process.env.DEPLOY_WALLET_1 as string],
+ },
+ flowTestnet: {
+ url: 'https://testnet.evm.nodes.onflow.org',
+ accounts: [process.env.DEPLOY_WALLET_1 as string],
+ },
+},
+```
+
+Then, add an entry for `etherscan`:
+
+```tsx
+etherscan: {
+}
+```
+
+In it, add a property for `apiKey` and add keys for Flow Mainnet and Testnet. Note that the Etherscan API requires this to be here, but at the time of writing, API keys aren't actually needed. Any text can be used:
+
+```tsx
+apiKey: {
+ // Is not required by blockscout. Can be any non-empty string
+ 'flow': "abc",
+ 'flowTestnet': "abc"
+},
+```
+
+Next, add `customChains` and the network information for Flow:
+
+```tsx
+customChains: [
+ {
+ network: 'flow',
+ chainId: 747,
+ urls: {
+ apiURL: 'https://evm.flowscan.io/api',
+ browserURL: 'https://evm.flowscan.io/',
+ },
+ },
+ {
+ network: 'flowTestnet',
+ chainId: 545,
+ urls: {
+ apiURL: 'https://evm-testnet.flowscan.io/api',
+ browserURL: 'https://evm-testnet.flowscan.io/',
+ },
+ },
+];
+```
+
+You should end up with:
+
+```tsx
+import type { HardhatUserConfig } from 'hardhat/config';
+import '@nomicfoundation/hardhat-toolbox-viem';
+
+require('@openzeppelin/hardhat-upgrades');
+require('dotenv').config();
+
+const config: HardhatUserConfig = {
+ solidity: '0.8.28',
+ networks: {
+ flow: {
+ url: 'https://mainnet.evm.nodes.onflow.org',
+ accounts: [process.env.DEPLOY_WALLET_1 as string],
+ },
+ flowTestnet: {
+ url: 'https://testnet.evm.nodes.onflow.org',
+ accounts: [process.env.DEPLOY_WALLET_1 as string],
+ },
+ },
+ etherscan: {
+ apiKey: {
+ // Is not required by blockscout. Can be any non-empty string
+ flow: 'abc',
+ flowTestnet: 'abc',
+ },
+ customChains: [
+ {
+ network: 'flow',
+ chainId: 747,
+ urls: {
+ apiURL: 'https://evm.flowscan.io/api',
+ browserURL: 'https://evm.flowscan.io/',
+ },
+ },
+ {
+ network: 'flowTestnet',
+ chainId: 545,
+ urls: {
+ apiURL: 'https://evm-testnet.flowscan.io/api',
+ browserURL: 'https://evm-testnet.flowscan.io/',
+ },
+ },
+ ],
+ },
+};
+
+export default config;
+```
+
+### Contract Setup
+
+Delete `Lock.sol` and add `ClickToken.sol`. In it add, the [Button Clicker Contract].
+
+:::warning
+
+Hardhat only installs the most current version of Solidity. `^0.8.27` means that this contract requires 0.8.27 or **higher**. You generally **don't** want to include the `^` in your contracts unless you have a specific reason for doing so.
+
+:::
+
+We won't go into the details of the contract for this tutorial. It's a relatively simple [ERC-20] implementation that mints one token any time the `mintTo` function is called. Perfect for a Button Clicker game!
+
+### Deployment Setup
+
+Delete `Lock.ts` from the `ignition/modules` folder, and add `ClickToken.ts`. In it, add:
+
+```tsx
+// This setup uses Hardhat Ignition to manage smart contract deployments.
+// Learn more about it at https://hardhat.org/ignition
+
+import { buildModule } from '@nomicfoundation/hardhat-ignition/modules';
+
+const ClickerModule = buildModule('ClickTokenModule', (m) => {
+ const clickToken = m.contract('ClickToken');
+
+ return { clickToken };
+});
+
+export default ClickerModule;
+```
+
+### Obtain Testnet Funds
+
+Visit the [Flow Faucet] and follow the instructions to add testnet funds. Compared to other networks, the [Flow Faucet] grants a vast amount of tokens - enough gas for millions of transactions.
+
+### Deploy the Contract
+
+Deploy the contract with:
+
+```bash
+npx hardhat ignition deploy ./ignition/modules/ClickToken.ts --network flowTestnet
+```
+
+You should see something similar to:
+
+```bash
+✔ Confirm deploy to network flowTestnet (545)? … yes
+Hardhat Ignition 🚀
+
+Deploying [ ClickTokenModule ]
+
+Batch #1
+ Executed ClickTokenModule#ClickToken
+
+[ ClickTokenModule ] successfully deployed 🚀
+
+Deployed Addresses
+
+ClickTokenModule#ClickToken - 0x5Ff8221DfDD1F82fd538391D231502B4b927fbD7
+```
+
+### Verify the Contract
+
+Next, verify the contract with:
+
+```bash
+hardhat ignition verify chain-545 --include-unrelated-contracts
+```
+
+You'll see something similar to:
+
+```bash
+briandoyle@Mac button-clicker-contract % npx hardhat ignition verify chain-545 --include-unrelated-contracts
+Verifying contract "contracts/ClickToken.sol:ClickToken" for network flowTestnet...
+Successfully verified contract "contracts/ClickToken.sol:ClickToken" for network flowTestnet:
+ - https://evm-testnet.flowscan.io//address/0x64366c923d5046F8417Dcd8a0Cb4a789F8722387#code
+```
+
+## Testing the Contract
+
+Click the link to open the contract in [testnet Flowscan]. Click the `Connect` button and connect your wallet, then navigate to the `Contract` tab and `Read/Write contract`.
+
+
+
+Find the `mintTo` function and expand the UI to mint yourself a few tokens. You can click the `self` button to automatically add your address without needing to copy/paste.
+
+Once you've "earned" a few tokens, use `balanceOf` to see how many tokens you have. You can also use `getAllScores` to get a list of everyone with the tokens, and how many they have.
+
+### Testing with Free Gas
+
+If you don't have it yet, set up the [Flow Wallet], connect, and try minting some more tokens. You'll see that the wallet automatically sponsors your gas:
+
+
+
+Even better, the [Flow Wallet] is currently **sponsoring transactions on mainnet** too!
+
+## Conclusion
+
+In this tutorial, you learned how to:
+
+- Fund a wallet with testnet tokens from the [Flow Faucet]
+- Deploy a contract on Flow EVM Testnet using Hardhat
+- Interact with a contract using [Flowscan]
+- Utilize automatically sponsored gas with the [Flow Wallet] on testnet and mainnet
+
+You've now mastered the basics of deploying and interacting with EVM contracts on Flow. But this is just the beginning! Flow EVM's true power lies in its ability to combine the best of both worlds: EVM compatibility with Flow's native features.
+
+In our [Cross-VM Apps] tutorial series, you'll learn how to supercharge your EVM applications by integrating them with Flow Cadence. You'll discover how to:
+
+- Build hybrid applications that seamlessly connect to both Flow EVM and Flow Cadence
+- Use Cadence's powerful features to enhance your EVM contracts
+- Enable multi-call contract writes with a single signature
+- Take advantage of Flow's native features like VRF and sponsored transactions
+
+Ready to unlock the full potential of Flow EVM? Start with our [Batched Transactions] tutorial to learn how to build your first cross-VM application.
+
+[Cadence]: https://cadence-lang.org/docs
+[Next.js]: https://nextjs.org/docs/app/getting-started/installation
+[wagmi]: https://wagmi.sh/
+[viem]: https://viem.sh/
+[rainbowkit]: https://www.rainbowkit.com/
+[Hardhat]: https://hardhat.org/
+[Remix]: ./guides/remix.md
+[Foundry]: ./guides/foundry.md
+[Flow Faucet]: https://faucet.flow.com/fund-account
+[Flowscan]: https://evm-testnet.flowscan.io/
+[Flow Wallet]: https://wallet.flow.com/
+[Button Clicker Contract]: https://github.com/briandoyle81/button-clicker-contract/blob/main/contracts/ClickToken.sol
+[OpenZeppelin]: https://www.openzeppelin.com/
+[Ignition]: https://hardhat.org/ignition/docs/getting-started#overview
+[Accounts]: ../evm/accounts.md
+[MetaMask]: https://metamask.io
+[private key]: https://support.metamask.io/configure/accounts/how-to-export-an-accounts-private-key/
+[ERC-20]: https://ethereum.org/en/developers/docs/standards/tokens/erc-20/
+[testnet Flowscan]: https://evm-testnet.flowscan.io/
+[Cross-VM Apps]: ../tutorials/cross-vm-apps/introduction.md
+[Batched Transactions]: ../tutorials/cross-vm-apps/introduction.md
+[OpenZeppelin Contracts]: https://www.openzeppelin.com/contracts
+
+
+=== evm/networks.md ===
+---
+title: Network Information
+sidebar_label: Network Information
+sidebar_position: 5
+---
+
+# Network Information
+
+Flow EVM has the following public RPC nodes available:
+
+# Mainnet
+
+| Name | Value |
+| --------------- | ------------------------------------ |
+| Network Name | Flow EVM |
+| Description | The public RPC URL for Flow Mainnet |
+| RPC Endpoint | https://mainnet.evm.nodes.onflow.org |
+| Chain ID | 747 |
+| Currency Symbol | FLOW |
+| Block Explorer | https://evm.flowscan.io |
+
+# Testnet
+
+| Name | Value |
+| --------------- | ------------------------------------ |
+| Network Name | Flow EVM Testnet |
+| Description | The public RPC URL for Flow Testnet |
+| RPC Endpoint | https://testnet.evm.nodes.onflow.org |
+| Chain ID | 545 |
+| Currency Symbol | FLOW |
+| Block Explorer | https://evm-testnet.flowscan.io |
+
+
+=== evm/how-it-works.md ===
+---
+title: How Flow EVM Works
+sidebar_label: How it Works
+sidebar_position: 3
+---
+
+# How Flow EVM Works
+
+## Introduction
+
+The Flow network uses [Cadence](https://cadence-lang.org/) as its main execution environment. Cadence offers a safe, efficient, and developer-friendly experience for building smart contracts and decentralized applications. Cadence can be used to extend EVM apps built in solidity by unlocking gasless experiences, new business models and fine-tuned access control. With Flow offering full EVM support, existing applications and tools already deployed in the EVM ecosystem can simply onboard to the network with [no code changes](https://developers.flow.com/evm/about).
+
+Flow EVM is designed with these major goals in mind:
+
+- Supporting EVM equivalency: Ensure that any tools and applications deployed to or run on Ethereum can also be deployed and run on Flow.
+- Minimizing breaking changes to the Cadence ecosystem, software and tools
+- Maximum composability across environments: Allowing atomic and smooth interaction between EVM and Cadence environments.
+
+### EVM - A Smart Contract In Cadence
+
+To satisfy the design goals and thanks to the extensibility properties of the Cadence runtime, Flow EVM is designed as a higher-level environment incorporated as a smart contract deployed to Cadence. This smart contract is not owned by anyone and has its own storage space, allows Cadence to query, and is updated through EVM transactions. EVM transactions can be wrapped inside Cadence transactions and passed to the EVM contract for execution. The artifacts of EVM transaction execution (e.g. receipts and logs) are emitted as special Cadence events (TransactionExecuted, BlockExecuted) and available to the upstream process (Flow transaction) to enable atomic operations.
+
+The EVM environment has its own concept of blocks, and every Flow block includes at most one EVM Block. The EVM block is formed at the end of Flow Block execution and includes all the transaction executed during the EVM block execution. Note that since EVM blocks are formed on-chain and Flow provides fast finality, as long as the user of these events waits for Flow block finality, it doesn’t have to worry about EVM block forks, uncle chains, and other consensus-related challenges.
+
+### No Shared Memory Design
+
+The interaction between two environments is through atomic calls and none of the environments has access to the raw memory of the other. This maintains the security properties of each environment. Cadence can submit transactions to the EVM environment and EVM transactions can make calls to a special precompiled contract called Cadence Arch. You can read more about this in the Precompiled section.
+
+### No New Native Token
+
+Flow EVM uses the same native token as Cadence (FLOW token). No new token is minted at the genesis block of EVM and all the tokens have to be bridged over from the Cadence side into the EVM side. To facilitate this a native bridge is provided by the EVM contract.
+
+### EVM Equivalency
+
+Under the hood, Flow EVM uses [the standard EVM implementation](https://github.com/ethereum/go-ethereum) and regularly applies updates through Flow’s height-coordinated updates (e.g. Execution layer changes planned for the Ethereum Prague update). This means anything that can run on Ethereum after the Cancun upgrade can run on Flow EVM. This means many useful EIPs such as [EIP-1014](https://eips.ethereum.org/EIPS/eip-1014), [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559), [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844), [EIP-5656](https://eips.ethereum.org/EIPS/eip-5656), [EIP-6780](https://eips.ethereum.org/EIPS/eip-6780), … are supported automatically.
+
+Yet a small set of differences between Flow EVM and Ethereum might be seen (mostly of the nature of extension) for two reasons:
+
+- A set of extensions has been added to ensure seamless and easy interaction between the two environments.
+- Flow EVM is secured by the Flow network and benefits from its robust network properties, such as fast block production and finalization, making issues like handling uncle chains irrelevant.
+
+## Gateways
+
+As mentioned, Flow EVM runs on top of the Flow network and its consensus model. Flow EVM does not leverage `geth` or introduce new node types to the existing architecture. Operators wishing to participate in securing the network stake tokens and run one of the Flow node types.
+
+To support `web3.js` clients, the [EVM Gateway](https://github.com/onflow/flow-evm-gateway) honors the Ethereum [JSON-RPC specification](https://ethereum.org/en/developers/docs/apis/json-rpc/). The gateway integrates with Flow access nodes and can be run by anyone (unstaked). It serves two purposes:
+
+### Gateway As A Light Client
+
+The gateway follows Flow's block production, collecting, verifying and indexing EVM-related events. The gateway provides the necessary endpoints and services all JSON-RPC requests for third-party dapps interacting with Flow EVM. EVM events include all information needed to reconstruct the EVM state since the genesis block (replayability). By re-executing transactions, the gateway can collect traces and maintain a local and archival copy of the EVM state over time.
+
+### Gateway As a Sequencer
+
+As mentioned, Flow EVM can be seen as a higher-level environment built on top of Cadence. Thus, all EVM transactions are ultimately handled using a Flow transaction (a wrapped call to the EVM). The gateway accepts EVM transactions, runs an internal mempool of transactions, wraps batches of EVM transactions in Flow transactions, and submits them.
+
+Note that the safety of transaction execution is not dependent on the gateway; they only relay the transaction. The safety measures of the EVM environment (e.g., Nonce, etc.) ensure that each transaction is executed at most once. Since gateways are submitting Flow transactions, they have to pay the related transaction fees. Part of these fees is associated with the computation fees of the EVM transaction.
+
+To facilitate the repayment of fees, the `evm.run` function accepts a `coinbase` address, which collects gas fees from the transaction, and pays it to the address provided by the gateway node. Essentially, the transaction wrapper behaves similarly to a miner, receives the gas usage fees on an EVM address, and pays for the transaction fees. The gas price per unit of gas creates a marketplace for these 3rd parties to compete over transactions.
+
+**Censorship Resistance and MEV Protection**
+
+Since Flow EVM runs on the Flow network, it benefits from Flow’s protections against censorship and MEV attacks. The Flow network natively provides censorship & MEV resistance which is achieved by designating specific validators for building transaction bundles that are separated from the validators proposing blocks (proposer-builder separation). More details about this are available in Flow’s protocol [white papers](https://flow.com/technical-paper).
+For extra protection on the EVM side, the gateway software is designed to be fully configurable and as lightweight as possible. This enables anyone with an account on Flow (e.g., any application) to run their own instances.
+
+**Fee Market Change (EIP-1559)**
+
+[EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) is supported by the Flow EVM and Gateway nodes can decide on the inclusion of the transactions based on the tips or gas fees. The parameters for the EIP 1559 are adjustable by the Flow network. Currently, the base fee is set to zero, as EVM transactions are wrapped by the Flow transactions.
+
+## Block hash calculation difference
+
+Developers using the GoLang Ethereum client to integrate with Flow will find that the block hash calculated by the Flow EVM RPC endpoints `eth_getBlockByNumber` and `eth_getBlockByHash` differ from the hash calculated locally by `go-ethereum`. This is due to underlying
+differences in the `Block` implementation to support EVM on Flow. For more information see https://github.com/onflow/flow-evm-gateway/issues/719.
+
+## Opcodes
+
+Flow EVM supports opcodes listed [here](https://www.evm.codes/?fork=cancun), except for the following changes.
+
+- **COINBASE** (`block.coinbase`)
+ Similar to Ethereum it returns the address of block’s beneficiary address. In the case of Flow EVM, it returns the address of the current sequencer's fee wallet (see Gateway section for more details).
+
+- **PREVRANDAO** (`block.prevrandao`)
+ On Ethereum, this value provides access to beacon chain randomness (see [EIP-4399](https://eips.ethereum.org/EIPS/eip-4399)), Since Flow uses a different approach in consensus and verifiable randomness generation, this value is filled with a random number provided by the Flow protocol. While Flow EVM provides such opcode, it is recommended not to rely on this value for security-sensitive applications, as it is the case on Ethereum. In order to benefit from the full power of secure randomness on Flow, it's recommended to use the [Cadence Arch precompiles](https://github.com/onflow/docs/blob/main/docs/evm/how-it-works.md#precompiled-contracts).
+
+## Precompiled Contracts
+
+Besides all the precompiled contracts supported by Ethereum (see here for [the list](https://www.evm.codes/precompiled?fork=cancun)), Flow EVM has augmented this with a unique precompiled contract, the Cadence Arch, that provides access to the Cadence world.
+
+Cadence Arch is a multi-function smart contract (deployed at `0x0000000000000000000000010000000000000001`) that allows any smart contract on Flow EVM a limited set of interactions with the Cadence environment.
+
+Functions currently available on the Cadence Arch smart contract are:
+
+- `FlowBlockHeight() uint64` (signature: `0x53e87d66`) returns the current Flow block height, this could be used instead of Flow EVM block heights to trigger scheduled actions given it's more predictable when a block might be formed.
+- `VerifyCOAOwnershipProof(bytes32 _hash, bytes memory _signature)(bool success)` returns true if the proof is valid. An ownership proof verifies that a Flow wallet controls a COA account (see the next section for more details on COA).
+- `revertibleRandom() uint64` returns a safe pseudo-random value that is produced by the Flow VRF (using Flow internal randomness beacon). The function invokes Cadence's `revertibleRandom` described [here](https://developers.flow.com/build/advanced-concepts/randomness). Although the random value is safe, a transaction may revert its results in the case of an unfavourable outcome. The function should only be used by trusted calls where there is no issue with reverting the results. `getRandomSource` must be used instead with untrusted calls.
+- `getRandomSource(uint64) bytes32` should be used when implementing a [commit-reveal](https://developers.flow.com/build/advanced-concepts/randomness#commit-reveal-scheme) scheme. It returns a secure random source from the Cadence randomness history contract. Learn more about the secure usage of randomness on Flow [here](https://developers.flow.com/build/advanced-concepts/randomness).
+
+Here is a sample demonstrating how to call the Cadence Arch.
+
+```solidity
+ address constant public cadenceArch = 0x0000000000000000000000010000000000000001;
+
+ function flowBlockHeight() public view returns (uint64){
+ (bool ok, bytes memory data) = cadenceArch.staticcall(abi.encodeWithSignature("flowBlockHeight()"));
+ require(ok, "failed to fetch the flow block height through cadence arch");
+ uint64 output = abi.decode(data, (uint64));
+ return output;
+ }
+```
+
+## Special Addresses
+
+### Native Token Bridge
+
+Both Cadence and Flow EVM use the same token (FLOW) to run their operations. No new token is minted on the EVM side. Moving FLOW tokens easily across two environments has been supported natively by the EVM smart contract. Because the EVM have limited visibility into Cadence and to make tracking funds easier, every time Flow tokens are withdrawn from the Cadence side and deposited into an EVM address, the balance would be added to a special address `0x0000000000000000000000010000000000000000` (native token bridge) and then transferred to the destination EVM address. The bridge address always maintains a balance of zero. Clearly, this EOA address is a network address and is not controlled by public key.
+
+### Cadence-Owned Accounts (COAs)
+
+COA is a natively supported EVM smart contract wallet type that allows a Cadence resource to own and control an EVM address. This native wallet provides the primitives needed to bridge or control assets across Flow EVM and Cadence. From the EVM perspective, COAs are smart contract wallets that accept native token transfers and support several ERCs including [ERC-165](https://eips.ethereum.org/EIPS/eip-165), [ERC-721](https://eips.ethereum.org/EIPS/eip-721), [ERC-777](https://eips.ethereum.org/EIPS/eip-777), [ERC-1155](https://eips.ethereum.org/EIPS/eip-1155), [ERC-1271](https://eips.ethereum.org/EIPS/eip-1271).
+
+These smart contract wallets are only deployable through the Cadence environment and their address starts with the prefix `0x000000000000000000000002`. The address `0x0000000000000000000000020000000000000000` is reserved for COA factory, an address that deploys contracts for COA accounts.
+
+A COA is not controlled by a key. Instead, every COA account has a unique resource accessible on the Cadence side, and anyone who owns that resource submits transactions on behalf of this address. These direct transactions have COA’s EVM address as the `tx.origin` and a new EVM transaction type (`TxType = 0xff`) is used to differentiate these transactions from other types of EVM transactions (e.g, DynamicFeeTxType (`0x02`). Currently, to make integration and tracking of these transactions byte EVM ecosystem tools, these types of transactions are encoded as legacy EVM transactions (hash computation is based on legacy tx rlp encoding).
+Controlling through a resource makes a COA a powerful smart contract wallet. It makes the transfer of ownership of the EVM address super easy without the need to transfer all the assets that an EVM address owns. It also allows a Cadence smart contract to take ownership of an EVM address and makes fully decentralized exchange and bridges across environments possible.
+
+To learn more about how to interact with a COA from the Cadence side, [see here](https://developers.flow.com/evm/cadence/interacting-with-coa).
+
+## Proofs
+
+**Inclusion proof of execution artifacts (logs and receipts)**
+
+Similar to other EVM environments, proof can be constructed for artifacts such as receipts. As mentioned earlier, all the EVM execution artifacts are collected as part of a Cadence event. Cadence events are similar to EVM logs, and the root hash of all events (event commitment) of a block is included in Flow's block content. The Cadence event inclusion proof functionality enables constructing proofs for any artifact. For example, if one wants to construct an external proof for the inclusion of a specific EVM log or receipt, here are the steps:
+
+- Flow block validation: Anyone following the Flow blocks can validate the Flow block headers.
+
+- EVM block validation: Since each Flow block has the root hash of Cadence events emitted during block execution. It can construct and verify the inclusion of the specific Event. In this case, every time an EVM block is executed an `evm.BlockExecuted` event is emitted that contains the full EVM block information.
+
+- Receipt inclusion: Each EVM block includes the root hash for the receipts generated during block execution. Similar to other EVM chains, a proof can be constructed to prove inclusion of a log or receipt.
+
+**Inclusion proof of transactions**
+
+Each Flow EVM block (TransactionHashRoot) includes the Merkle root hash of all the transaction hashes executed during this block. Despite similar functionality, this root is a bit different than TransactionRoot provided by Ethereum, It is a commitment over the list of transaction hashes instead of transactions, so each leaf node in the Merkle tree has the transaction hash as the value instead of full RLP encoding of transaction. So verifying the proofs requires an extra calling to the hash function.
+
+**Account proofs**
+
+Another type of proof that EVM environments provide is proof for the state of accounts. These proofs depend on the trie structure of the execution environment. Flow EVM benefits from the advanced storage and proof system that makes Flow’s multi-role architecture possible.
+
+Flow’s state system provides ways to construct inclusion and non-inclusion proofs and one can construct proofs for EVM account’s meta data (account balances, nonce, … ). A less common proof type is proof over the storage state of an account (mostly used for smart contracts). The first release of Flow EVM won’t support these type of proofs.
+
+
+=== evm/fees.md ===
+---
+title: Fees
+sidebar_label: Fees
+sidebar_position: 6
+---
+
+:::info
+
+Are you a Cadence developer looking for information about Fees on Cadence? If so, check out the Cadence specific documentation [here](../build/basics/fees.md)
+
+:::
+
+EVM transactions are ultra low-cost and use the native FLOW token as gas. [Externally Owned Accounts (EOAs)](https://developers.flow.com/evm/build/accounts) function the same on Flow as other EVM networks like Ethereum.
+
+
+How Transaction Fees are Computed on EVM
+
+With Flow EVM, EVM operations can now be called within Cadence transactions. EVM operations also have an associated effort measured in gas which needs to be factored into the execution effort calculation in addition to the Flow computation for any EVM transaction.
+
+```
+Transaction fee on EVM = surge x [inclusion fee + (execution effort * unit cost)]
+```
+
+- `Surge' factor` dynamically accounts for network pressure and market conditions. This is currently constant at 1.0 but subject to change with community approval.
+- `Inclusion fee` accounts for the resources required to process a transaction due to its core properties (byte size, signatures). This is currently constant at 1E-6 FLOW, but subject to change with community approval.
+- `Execution fee` The fee that accounts for the operational cost of running the transaction script, processing the results, sending results for verification, generating verification receipts, etc. and is calculated as a product of `execution effort units` and the `cost per unit`.
+ - `Execution Effort (computation)` is based on transaction type and operations that are called during the execution of a transaction. The weights determine how “costly” (time consuming) each operation is.
+ - `Execution Effort Unit Cost` = `2.49E-07 FLOW` (currently constant, but subject to change with community approval)
+
+Calculation of Execution Effort
+
+```
+Execution Effort (computation) =
+ 0.00478 * function_or_loop_call +
+ 0.00246 * GetValue +
+ 0.00234 * SetValue +
+ 8.65988 * CreateAccount +
+ EVMGasUsageCost * EVMGasUsage
+```
+
+where
+
+```
+`EVMGasUsage` is reported by EVM as the cost in gas for executing the transaction within the EVM, for instance, 21K gas for a simple send transaction.
+```
+
+```
+`EVMGasUsageCost` - The ratio that converts EVM gas into Flow computation units (execution effort) is currently set at `1/5000` but subject to revision by community approval
+```
+
+**Note**: The weights and unit cost mentioned above have been updated recently to accommodate an increased computation limit on Flow, which now supports the deployment of larger EVM contracts. For detailed information, refer to the relevant [FLIP](https://github.com/onflow/flips/blob/main/governance/20240508-computation-limit-hike.md) and join the ongoing discussion on the community [forum post](https://forum.flow.com/t/proposing-transaction-fee-changes-and-flow-evm-gas-charges-for-flow-crescendo-launch/5817). These values may be adjusted in the future based on community feedback and evolving requirements.
+
+
+
+
+ Demonstration of Transaction Fees on EVM
+
+Assume a simple NFT transfer transaction that makes 31 cadence loop calls, reads 5668 bytes from the storage register, and saves 1668 bytes to the storage register.
+
+- 'function_or_loop_call' = 31
+- 'GetValue' = 5688
+- 'SetValue' = 1668
+- 'CreateAccount' = 0
+
+**Scenario 1 - Cadence-only Transaction**
+
+```
+Execution Effort = 0.00478 * (31) + 0.00246 * (5668) + 0.00234 *(1668) + 8.65988 *(0) + EVMGasUsageCost * EVMGasUsage
+```
+
+But since `EVMGasUsage` is 0 for a Cadence transaction,
+
+```
+Execution Effort = 18.04378
+```
+
+Thus
+
+```
+Transaction fee = [1E-6 FLOW + (18.04378 * 2.49E-07 FLOW)] x 1 = 5.5E-06 FLOW
+```
+
+**Scenario 2 - EVM Transaction**
+If the EVMGasUsage can be assumed to be 21,000 gas (typical for a simple transfer),
+
+```
+Execution Effort = 0.00478 * (31) + 0.00246 * (5668) + 0.00234 *(1668) + 8.65988 *(0) + 1/5000 * 21000 = 22.24378
+```
+
+Thus
+
+```
+Transaction fee = [1E-6 FLOW + (110.97 * 2.49E-07 FLOW)] x 1 = 6.55E-06 FLOW
+```
+
+**Note**: Please be aware that this example serves solely for illustrative purposes to elucidate the calculations. Actual transaction fees may differ due to various factors, including the byte size of the transaction.
+
+
+
+## Gasless Transactions
+
+Fees needed to execute transactions on a Web3 app are often a major challenge for new users and can be a barrier to adoption. Builders can easily extend their apps with Cadence to create ‘gasless’ experiences by specifying their app as the [sponsor](../build/advanced-concepts/account-abstraction.md#sponsored-transactions) instead of the user.
+
+To learn more about storage fee and transaction fee, visit [Flow Tokenomics page](https://flow.com/flow-tokenomics/technical-overview).
+
+
+=== evm/faucets.mdx ===
+---
+slug: /evm/faucets
+redirect: /ecosystem/faucets
+title: Faucets ↙
+sidebar_position: 10
+---
+
+# Faucets
+
+Go to [Faucets](../ecosystem/faucets.md)
+
+import {Redirect} from '@docusaurus/router';
+
+ ;
+
+
+=== evm/cross-chain-bridges.mdx ===
+---
+slug: /evm/cross-chain-bridges
+redirect: /ecosystem/bridges
+title: Cross-chain Bridges ↙
+sidebar_position: 8
+---
+
+# Cross-chain Bridges
+
+Go to [Bridges](../ecosystem/bridges.md)
+
+import {Redirect} from '@docusaurus/router';
+
+ ;
+
+
+=== evm/block-explorers.mdx ===
+---
+slug: /evm/block-explorers
+redirect: /ecosystem/block-explorers
+title: Block Explorers ↙
+sidebar_position: 11
+---
+
+# Faucets
+
+Go to [Block explorers](../ecosystem/block-explorers.md)
+
+import {Redirect} from '@docusaurus/router';
+
+ ;
+
+
+=== evm/accounts.md ===
+---
+title: Accounts
+sidebar_label: Accounts
+sidebar_position: 7
+---
+
+:::info
+
+Are you a Cadence developer looking for information about Accounts on Cadence? If so, check out the Cadence specific documentation [here](../build/basics/accounts.md)
+
+:::
+
+# Accounts
+
+There are three types of accounts used for Flow EVM.
+
+1. **Externally Owned Accounts (EOA)**: EOAs are controlled by private individuals using cryptographic keys and can initiate transactions directly. They are the primary account type for users to interact with the blockchain, holding and sending cryptocurrency or calling smart contract functions.
+2. **Contract Accounts**: These accounts hold smart contract code and are governed by this code's logic. Unlike EOAs, Contract Accounts do not initiate transactions on their own but can execute transactions in response to calls they receive from EOAs or other contracts.
+3. **Cadence Owned Accounts (COA)**: This is an account type unique to Flow EVM. These accounts are managed by [Cadence resources](https://cadence-lang.org/docs/language/resources) and can be used to interact with the Flow EVM from within the Cadence environment.
+
+EOAs and Contract accounts function the same as on other EVM networks. Users may interact with these accounts using the standard EVM JSON-RPC API ([see endpoints here](./using.mdx)). You can read more about EOAs and Contract accounts on the [Ethereum docs](https://ethereum.org/developers/docs/accounts).
+
+However, in order to leverage all the features of Cadence, developers will need to utilize Cadence Owned Accounts.
+
+:::danger
+
+🚨🚨🚨 **ASSET LOSS RISK** 🚨🚨🚨
+
+Cadence-Owned Accounts, easily identifiable by the leading zeroes (`0x00000000000000000000000`) **only exist on Flow**. The keys to these addresses are generated in a way that is not compatible with other networks.
+
+As a result, any assets sent to one of these addresses on another network **will be lost permanently!**
+
+We're working with major wallet providers to block such transfers, and recommend that all app and wallet developers do the same.
+
+:::
+
+## Cadence Owned Accounts
+
+A Cadence Owned Account (COA) is a natively supported EVM smart contract wallet type that allows a Cadence resource to own and control an EVM address. This native wallet type provides the primitives needed to bridge or control assets across Flow EVM and Cadence facilitating composability between environments.
+
+
+
+### Why use COAs?
+
+COAs create powerful new opportunities to improve the UX, functionality and utility of EVM applications by taking advantage of Cadence. Key benefits include:
+
+- **Enhanced Composability**: Applications written in Solidity can be extended and composed upon within Cadence. This allows developers to build upon existing EVM applications and deliver a more feature-rich user experience.
+
+- **Atomic Interactions**: Developers are able to execute multiple EVM transactions atomically from a COA. This is particularly useful for applications that require multiple transactions to be executed within a single block, or require all prior transactions' state changes to revert if a single transaction in the batch fails. This is not possible natively using EOAs or with `UserOperations` when using the ERC-4337 standard; in both cases each individual transaction is distinct and cannot be reverted back once state has changed.
+
+- **Native Account Abstraction**: COAs are controlled by Cadence resources, which are in turn owned by Flow accounts. [Flow accounts](./accounts.md) have built-in support for multi-signature authentication, key rotation, and account recovery. As a Cadence resource, COAs naturally inherit [these features](../build/advanced-concepts/account-abstraction.md).
+
+- **Fine-Grained Access Control**: As Cadence resources, access to a COA can be governed by more sophisticated policies than those available with basic EVM accounts. By utilizing powerful Cadence access control primitives such as [capabilities and entitlements](https://cadence-lang.org/docs/language/access-control), developers can restrict who is able to interact with a COA and what actions they are permitted to perform.
+
+### Differences from Traditional EVM Accounts
+
+COAs are smart contracts that are deployed to, and are fully accessible within, Flow EVM. However, unlike traditional EVM accounts (e.g. EOAs or smart contract accounts), COAs are owned by a Cadence resource. This means that COAs can be created and controlled natively within the Cadence execution environment.
+
+Unlike EOAs, COAs do not have an associated key, but are assigned a 20-byte EVM address upon creation from Cadence. This address is based on the UUID of the Cadence resource and is prefixed with `0x000000000000000000000002`. This address determines the location of the COA smart contract deployment and is the EVM address that is used to interact with the COA.
+
+A COA may instantiate transactions itself (where the COA's EVM address acts as `tx.origin`). This behaviour differs from other EVM environments, where only externally owned accounts (EOAs) may instantiate transactions.
+
+Because COAs are owned by Cadence resources, an EVM transaction is not required to trigger a transaction from a COA (e.g. a transaction to make a call to `execute` or EIP-4337's `validateUserOpMethod`). Instead, call transactions may be triggered directly from the Cadence resource that owns the COA. By invoking the `call` method on this resource, a transaction event will be emitted within the EVM environment.
+
+### More Information
+
+To learn how to create and interact with COAs in Cadence, see the guide for [Interacting with COAs from Cadence](../tutorials/cross-vm-apps/interacting-with-coa.md).
+
+For more information about Cadence Owned Accounts, see the [Flow EVM Support FLIP](https://github.com/onflow/flips/pull/225/files)
+
+
+=== evm/about.md ===
+---
+title: Why EVM on Flow
+sidebar_label: Why EVM on Flow
+sidebar_position: 1
+---
+
+# Why EVM on Flow
+
+Flow is an L1 that now supports EVM-equivalency. This means that all of Flow's protocol benefits, such as fast transactions, low costs, and mainstream scalability, are natively available without any additional code changes to solidity contracts. With EVM, solidity devs and builders can now easily tap into Flow's user base and unique IPs without any implementation risk.
+
+## Seamless Integration for Ethereum Developers
+
+Flow EVM is designed to work out-of-the-box with the Ethereum toolchain or other clients. Native EVM transactions also continue to be supported when using Metamask and other EVM-compatible clients.
+EVM-equivalency on Flow works behind-the-scenes by implementing a minimal transaction script in Cadence, Flow's smart contract language, to integrate Flow features with EVM. This is made possible because EVM transactions are composed and executed within Cadence transactions, enabling novel use-cases and patterns for integration.
+
+
+## Best-In-Class UX
+
+Flow allows for the creation of app on-boarding experiences that meet every type of user exactly where they are at, from web3 beginners to ecosystem veterans. This is possible through Account Linking, which utilizes the account abstraction model on Flow and enables users to immediately use an app without wallet authentication. On-chain accounts can be created as needed by the application which custodies their use for an anonymous user. At some later point these users may choose to link the custodied account to their self-custodial wallet taking full ownership of the account. EVM apps on Flow can also leverage Account Linking to handle creation of accounts and achieve a similarly smooth onboarding user experience.
+
+With Flow, builders can choose to expand EVM capabilities and transcend limitations using Cadence, which offers a powerful new account model, programmable resources, and hybrid ownership.
+
+## Instant Cross-VM Token Transfers
+
+EVM and Cadence environments both use FLOW as gas for transactions, sharing a singular token supply across both environments. Fungible and non-fungible tokens can also be seamlessly transferred between environments using the native VM token bridge, taking place instantly in a single atomic transaction.
+
+## Scalability, Performance and Low Gas Fees
+
+For sustainable user adoption, apps require the network they build on to be secure, efficient, affordable and fast. Gas fees are ultra-low cost on the network, but Flow goes a step further allowing for gasless experiences through sponsored transactions. Scalable performance is ensured with an innovative multi-node distributed consensus, flexible transaction model and horizontally scaled transaction linearization which solves proposer-builder separation, separation of compute, and settlement – all without sharding.
+
+Flow’s state space is extensible to the petabyte scale making it easy to store application data on-chain. This means contracts can maintain a full working dataset - including metadata - together with contract logic.
+
+Flow's transaction throughput peaked to 2M daily transactions during 2023 sustaining a similar average transaction volume as Ethereum. Unlike Ethereum, Flow has always operated well under its maximum throughput ceiling which is presently scalable to 5x more transactions with further performance optimizations to come when parallel execution is released. State scalability on Flow sets the foundations for further significant throughput optimization.
+
+
+## MEV Resilience
+
+The [MEV Resilient](../build/basics/mev-resistance.md) design on Flow offers DeFi builders improved market efficiency, fairness, trust and long-term viability for their apps. Since Flow EVM transactions are composed and executed within a Cadence transaction, block production is handled by Flow’s [multi-role architecture](https://flow.com/post/flow-blockchain-multi-node-architecture-advantages). This heterogeneity between node roles ensures that visibility into block proposal, assembly, asserting block validity and other correctness checks during the block production cycle exposes limited information to each node type on a need to know basis, observing the Principle of Least Privilege. These differences in node and consensus design results in strong economic disincentives for collusion because no individual node has full visibility into the state of block production for the chain. This robust MEV resilience is a significant difference from other EVM-compatible networks and results in reasonably priced, predictable gas fees. The impracticality of frontrunning or other attacks improves the user experience by eliminating failed transactions and invisible fees.
+
+
+## Join the Community
+
+Are you interested in launching an EVM project on Flow or partnering with us? Visit our weekly Flow [office hours](https://calendar.google.com/calendar/ical/c_47978f5cd9da636cadc6b8473102b5092c1a865dd010558393ecb7f9fd0c9ad0%40group.calendar.google.com/public/basic.ics) for discussions on project development and other opportunities for collaboration. You can also chat with us developers-chat in the Flow [Discord](https://discord.gg/flow).
+
+
+## Further Reading and Discussions
+
+- [Why EVM on Flow: Beyond Solidity](https://forum.flow.com/t/evm-on-flow-beyond-solidity/5260)
+- [Path to EVM Equivalence on Flow](https://forum.flow.com/t/evm-equivalence-on-flow-proposal-and-path-forward/5478)
+
+## Flow Improvement Proposals (FLIPs)
+
+Those wishing to understand the technical specifics of how Flow EVM works we recommend reviewing the following improvement proposals.
+
+- Understanding [EVM Support on Flow](https://github.com/onflow/flips/pull/225)
+- Exploring the [Flow VM Bridge](https://github.com/onflow/flips/pull/233/files/d5bc46c4b13f0b9b168a94f994c77a5a689f6b24..122e938b7acae7e774246b1b66aaf5979ca21444)
+- Insights into the [Flow EVM Gateway](https://github.com/onflow/flips/pull/235/files)
+- Integration of the [Cadence Interface](https://github.com/onflow/flips/blob/f646491ec895442dcccdb24d80080bab1c56188e/protocol/20231116-evm-support.md)
+
+
+=== evm/guides/web3-js.md ===
+---
+title: Web3.js on Flow Blockchain
+sidebar_label: Web3.js
+sidebar_position: 9
+---
+
+# Web3.js
+
+[Web3.js](https://web3js.org/) is a Javascript library for building on EVM-compatible networks.
+
+It allows developers to interact with smart contracts, send transactions, and retrieve data from the network.
+
+## Prerequisites
+
+:::info
+This guide assumes you have the latest version of [Node.js](https://nodejs.org/en) installed.
+:::
+
+To install `web3` in your project, run the following command:
+
+```sh
+npm install web3
+```
+
+## Initializing Web3 with Flow
+
+To use `web3` in your project, start by importing the module and initializing your `Web3` instance with a Flow RPC endpoint.
+
+```js
+const { Web3 } = require('web3');
+const web3 = new Web3('https://testnet.evm.nodes.onflow.org');
+```
+
+**Note:** If you want to connect to the Flow testnet, replace the above URL with `https://mainnet.evm.nodes.onflow.org`.
+
+## Querying The Blockchain
+
+`web3` provides a number of methods for querying the blockchain, such as getting the latest block number, querying account balances, and more.
+
+You can try using some of these methods to verify that your `web3` instance is working correctly.
+
+```js
+// Get the latest block number
+const blockNumber = await web3.eth.getBlockNumber();
+console.log(blockNumber); // Latest block number
+
+// Get the balance of an account
+const balance = await web3.eth.getBalance('0x1234'); // Replace with any address
+console.log(balance); // Balance in attoFlow
+
+// Get the chain ID
+const chainId = await web3.eth.getChainId();
+console.log(chainId);
+
+// Get the gas price
+const gasPrice = await web3.eth.getGasPrice();
+console.log(gasPrice); // Gas price in attoFlow
+```
+
+For more information about other queries you can make `web3`, please see the [official documentation](https://docs.web3js.org/).
+
+## Interacting with Smart Contracts
+
+The `web3` library allows developers to interact with smart contracts via the `web3.eth.Contract` API.
+
+For this example we will use the following `Storage` contract.
+
+We recommend deploying your own contract, which can be done using [Hardhat](../guides/hardhat.md) or [Remix](../guides/remix.md).
+
+```solidity
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+contract Storage {
+ uint256 public storedData;
+
+ function store(uint256 x) public {
+ storedData = x;
+ }
+
+ function retrieve() public view returns (uint256) {
+ return storedData;
+ }
+}
+```
+
+The ABI for this contract can be generated using the [`solc` compiler](https://docs.soliditylang.org/en/latest/installing-solidity.html), or another tool such as [Hardhat](../guides/hardhat.md) or [Remix](../guides/remix.md).
+
+Now that we have both the ABI and address of the contract, we can create a new `Contract` object for use in our application.
+
+```js
+// Replace with the ABI of the deployed contract
+const abi = [
+ {
+ inputs: [],
+ stateMutability: 'nonpayable',
+ type: 'constructor',
+ },
+ {
+ inputs: [
+ {
+ internalType: 'uint256',
+ name: 'x',
+ type: 'uint256',
+ },
+ ],
+ name: 'store',
+ outputs: [],
+ stateMutability: 'nonpayable',
+ type: 'function',
+ },
+ {
+ inputs: [],
+ name: 'retrieve',
+ outputs: [
+ {
+ internalType: 'uint256',
+ name: '',
+ type: 'uint256',
+ },
+ ],
+ stateMutability: 'view',
+ type: 'function',
+ },
+];
+
+// Replace with the address of the deployed contract
+const contractAddress = '0x4c7784ae96e7cfcf0224a95059573e96f03a4e70';
+
+// Create a new contract object with the ABI and address
+const contract = new web3.eth.Contract(abi, contractAddress);
+```
+
+We can now interact with the contract on the network by using the `contract` object.
+
+### Reading State
+
+State can be read from the contract by using the `call` function with one of the contract's methods. This will not change the state and will not send a transaction.
+
+```js
+// Retrieve the current value stored in the contract
+// (this is using the `retrieve` method from the contract with no arguments)
+const result = await contract.methods.retrieve().call();
+
+console.log(result); // Current value stored in the contract
+```
+
+### Changing State
+
+We can mutate the state of the contract by sending a transaction to the network.
+
+In order to send a transaction to the network, you will need an account with sufficient funds to pay for the transaction.
+
+:::info
+If you do not have an account yet, you can create one using the following command from your project's root directory:
+
+```sh
+node -e "console.log(require('web3').eth.accounts.create())"
+```
+
+Note that this is not a secure way to generate an account, and you should use a more secure method in a production environment.
+
+You can fund your account using the [Flow Faucet](https://faucet.flow.com/fund-account).
+:::
+
+We can use the `privateKeyToAccount` function to create an `Web3Account` object from our account's private key.
+
+```js
+// You must replace this with the private key of the account you wish to use
+const account = web3.eth.accounts.privateKeyToAccount('0x1234');
+```
+
+Then, we can sign a transaction using the user's account and send it to the network.
+
+```js
+const newValue = 1337; // Replace with any value you want to store
+
+// Sign a transaction that stores a new value in the contract
+// (this is using the `store` method from the contract with the new value as an argument)
+let signed = await account.signTransaction({
+ from: account.address,
+ to: contractAddress,
+ data: contract.methods.store(newValue).encodeABI(),
+ gas: 10000000n, // Replace with the gas limit you want to use
+ gasPrice: await web3.eth.getGasPrice(), // Replace with the gas price you want to use
+});
+
+// Send signed transaction to the network
+const result = await web3.eth.sendSignedTransaction(signed.rawTransaction);
+
+// { status: 1, transactionHash: '0x1234', ... }
+// status=1 means the transaction was successful
+console.log(result);
+```
+
+Now that the transaction has been sent, the contract's state should have been updated. We can verify this by querying the contract's state again:
+
+```js
+const result = await contract.methods.retrieve().call();
+console.log(result); // New value stored in the contract
+```
+
+For more information about using smart contracts in web3.js, see the [official documentation](https://docs.web3js.org/libdocs/Contract).
+
+
+=== evm/guides/wagmi.md ===
+---
+title: Viem & Wagmi
+description: 'Using Wagmi to interact with Solidity contract to Flow EVM.'
+sidebar_label: Viem & Wagmi
+sidebar_position: 4
+---
+
+:::info
+Make sure to use `viem` version `2.9.6` or greater. This version contains flow EVM networks
+:::
+
+# Using viem
+
+Flow networks have been added to viem chain definitions [viem networks](https://github.com/wevm/viem/tree/main/src/chains/definitions). This allows for convenient flow network configuration when using viem and wagmi.
+
+## Viem Flow Config
+
+The configuration below uses Flow Testnet. Since this configuration is already in viem various properties are already set, like block explorer and json-rpc endpoint. See how this configuration is used in a nextjs wagmi web application below.
+
+```javascript
+import { http, createConfig } from '@wagmi/core';
+import { flowTestnet } from '@wagmi/core/chains';
+import { injected } from '@wagmi/connectors';
+
+export const config = createConfig({
+ chains: [flowTestnet],
+ connectors: [injected()],
+ transports: {
+ [flowTestnet.id]: http(),
+ },
+});
+```
+
+# Using Next.js and Wagmi
+
+This tutorial will guide you through creating a simple web application, connect to an EVM capable wallet and interact with the "HelloWorld" smart contract to get and set greetings. We will not dive into managing transactions.
+
+## Prerequisites
+
+- Node.js installed on your machine
+- A code editor (e.g., Visual Studio Code)
+- Basic knowledge of React and Next.js
+
+## Step 1: Setting Up the Next.js Project
+
+This tutorial will be following [Wagmi getting-started manual tutorial](https://wagmi.sh/react/getting-started)
+First, let's create a Wagmi project named `flow-evm-wagmi`. We will use npm but you are welcome to use yarn or bun.
+
+```bash
+npm create wagmi@latest
+
+# project name flow-evm-wagmi
+# Select 'React' then 'next'
+
+```
+
+After Wagmi automatic installation procedure.
+
+```bash
+cd flow-evm-wagmi
+npm install
+```
+
+## Step 2: Configuring Wagmi and Connecting the Wallet
+
+Make sure you have Metamask installed and Flow network configured. [Metamask and Flow blockchain](/evm/using).
+Wagmi needs to know what networks to be aware of. Let's configure to use Flow Testnet by updating config.ts file with the following:
+
+```javascript
+import { http, createConfig } from '@wagmi/core';
+import { flowTestnet } from '@wagmi/core/chains';
+import { injected } from '@wagmi/connectors';
+
+export const config = createConfig({
+ chains: [flowTestnet],
+ connectors: [injected()],
+ transports: {
+ [flowTestnet.id]: http(),
+ },
+});
+```
+
+By default Wagmi configures many wallets, MetaMask, Coinbase Wallet, and WalletConnect as wallet providers. Above we simplify the code to only be interested in the Injected Provider, which we are interested in Metamask. Verify `page.tsx` code looks like the following.
+
+```javascript
+'use client'
+
+import { useAccount, useConnect, useDisconnect } from 'wagmi'
+
+function App() {
+ const account = useAccount()
+ const { connectors, connect, status, error } = useConnect()
+ const { disconnect } = useDisconnect()
+
+ return (
+ <>
+
+
Account
+
+
+ status: {account.status}
+
+ addresses: {JSON.stringify(account.addresses)}
+
+ chainId: {account.chainId}
+
+
+ {account.status === 'connected' && (
+
disconnect()}>
+ Disconnect
+
+ )}
+
+
+
+
Connect
+ {connectors.map((connector) => (
+
connect({ connector })}
+ type="button"
+ >
+ {connector.name}
+
+ ))}
+
{status}
+
{error?.message}
+
+ >
+}
+
+export default App
+
+```
+
+
+
+This step relies on an already deployed HelloWorld contract. See [Using Remix](./remix.md) to deploy a smart contract on flow evm blockchain.
+Create or edit the simple `page.tsx` file in the app directory to have better styles, that's beyond this tutorial. We will modify `page.txs` to add a new `HelloWorld.tsx`. Replace `YOUR_CONTRACT_ADDRESS` with your deployed address.
+
+## Step 3: Creating the Interface for HelloWorld Contract
+
+Now, let's create a component to interact with the HelloWorld contract. Assume your contract is already deployed, and you have its address and ABI.
+
+- Create a new file, HelloWorld.ts, in the components directory.
+- Use Wagmi's hooks to read from and write to the smart contract:
+
+```javascript
+import { useState } from 'react';
+import {
+ useContractRead,
+ useContractWrite,
+ useAccount,
+ useConnect,
+} from 'wagmi';
+import contractABI from './HelloWorldABI.json'; // Import your contract's ABI
+
+const contractAddress = 'YOUR_CONTRACT_ADDRESS';
+
+const HelloWorld = () => {
+ const [newGreeting, setNewGreeting] = useState('');
+ const { address, isConnected } = useAccount();
+ const { connect } = useConnect();
+
+ const { data: greeting } = useContractRead({
+ addressOrName: contractAddress,
+ contractInterface: contractABI,
+ functionName: 'hello',
+ });
+
+ const { write: changeGreeting } = useContractWrite({
+ addressOrName: contractAddress,
+ contractInterface: contractABI,
+ functionName: 'changeGreeting',
+ args: [newGreeting],
+ });
+
+ if (!isConnected) {
+ return connect()}>Connect Wallet ;
+ }
+
+ return (
+
+
Current Greeting: {greeting}
+
setNewGreeting(e.target.value)}
+ placeholder="New greeting"
+ />
+
changeGreeting()}>Update Greeting
+
+ );
+};
+
+export default HelloWorld;
+```
+
+Reminder: aReplace YOUR_CONTRACT_ADDRESS with the actual address of your deployed HelloWorld contract.
+
+Also notice you need the HelloWorld contract ABI, save this to a new file called `HelloWorld.json` in the app directory.
+
+```json
+{
+ "abi": [
+ {
+ "inputs": [],
+ "stateMutability": "nonpayable",
+ "type": "constructor"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "newGreeting",
+ "type": "string"
+ }
+ ],
+ "name": "changeGreeting",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "greeting",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "hello",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ }
+ ]
+}
+```
+
+## Step 4: Integrating the HelloWorld Component
+
+Finally, import and use the HelloWorld component in your `pages.tsx`, throw it at the bottom of the render section.
+
+```javascript
+import HelloWorld from './helloWorld'
+
+ // put at the bottom of the Connect section.
+
+
Connect
+ {connectors.map((connector) => (
+
connect({ connector })}
+ type="button"
+ >
+ {connector.name}
+
+ ))}
+
{status}
+
{error?.message}
+
+
+ // 👇👇👇👇👇👇👇👇👇👇👇
+
+
+
+
+```
+
+Now, you have a functional App that can connect to Metamask, display the current greeting from the "HelloWorld" smart contract, and update the greeting.
+
+Test it by updating the greeting, signing a transaction in your Metamask then wait a minute then refresh the website. Handling transactions are outside of this tutorial. We'll leave that as a future task. [Checkout Wagmi documentation](https://wagmi.sh/react/getting-started)
+
+
+
+
+=== evm/guides/vrf.md ===
+---
+title: VRF (Randomness) in Solidity
+sidebar_label: VRF (Randomness) in Solidity
+sidebar_position: 6
+---
+
+## **Introduction**
+
+Flow provides secure, native on-chain randomness that developers can leverage through Cadence Arch, a precompiled
+contract available on the Flow EVM environment. This guide will walk through how Solidity developers can use Cadence
+Arch to access Flow’s verifiable randomness using Solidity.
+
+### **What is Cadence Arch?**
+
+[Cadence Arch](https://github.com/onflow/flips/blob/main/protocol/20231116-evm-support.md#cadence-arch) is a precompiled
+smart contract that allows Solidity developers on Flow EVM to interact with Flow’s randomness and other network features
+like block height. This contract can be accessed using its specific address, and Solidity developers can make static
+calls to retrieve random values and other information.
+
+---
+
+## **Prerequisites**
+
+- Basic Solidity knowledge.
+- Installed Metamask extension.
+- Remix IDE for compilation and deployment.
+- Flow EVM Testnet setup in Metamask.
+
+## **Network Information for Flow EVM**
+
+| **Parameter** | **Value** |
+| ------------------- | ----------------------------------------------------------------------------- |
+| **Network Name** | Flow EVM Testnet |
+| **RPC Endpoint** | [https://testnet.evm.nodes.onflow.org](https://testnet.evm.nodes.onflow.org/) |
+| **Chain ID** | 545 |
+| **Currency Symbol** | FLOW |
+| **Block Explorer** | [https://evm-testnet.flowscan.io](https://evm-testnet.flowscan.io/) |
+
+## **Steps to Connect Flow EVM Testnet to Metamask**
+
+1. Open Metamask and click **Networks** -> **Add Network**.
+2. Enter the following details:
+ - **Network Name**: Flow EVM Testnet
+ - **RPC URL**: `https://testnet.evm.nodes.onflow.org`
+ - **Chain ID**: `545`
+ - **Currency Symbol**: `FLOW`
+ - **Block Explorer**: `https://evm-testnet.flowscan.io`
+3. Click **Save** and switch to the Flow EVM Testnet.
+
+
+
+## **Obtaining Testnet FLOW**
+
+You can fund your account with testnet FLOW using the [Flow Faucet](https://testnet-faucet.onflow.org/fund-account).
+Enter your Flow-EVM testnet address, and you’ll receive testnet FLOW tokens to interact with smart contracts.
+
+---
+
+## **Solidity Code Example: Retrieving Random Numbers**
+
+Below is a simple Solidity contract that interacts with the Cadence Arch contract to retrieve a pseudo-random number.
+
+```solidity
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity >=0.7.0 <0.9.0;
+
+contract CadenceArchCaller {
+ // Address of the Cadence Arch contract
+ address constant public cadenceArch = 0x0000000000000000000000010000000000000001;
+
+ // Function to fetch a pseudo-random value
+ function revertibleRandom() public view returns (uint64) {
+ // Static call to the Cadence Arch contract's revertibleRandom function
+ (bool ok, bytes memory data) = cadenceArch.staticcall(abi.encodeWithSignature("revertibleRandom()"));
+ require(ok, "Failed to fetch a random number through Cadence Arch");
+ uint64 output = abi.decode(data, (uint64));
+ // Return the random value
+ return output;
+ }
+}
+
+```
+
+### **Explanation of the Contract**
+
+1. **Cadence Arch Address**:
+
+ The `cadenceArch` variable stores the address of the Cadence Arch precompiled contract
+ (`0x0000000000000000000000010000000000000001`), which is constant across Flow EVM.
+
+2. **Revertible Random**:
+
+ The `revertibleRandom()` function makes a static call to the `revertibleRandom()` function to fetch a pseudo-random
+ number. If the call is successful, it decodes the result as a `uint64` random value.
+
+---
+
+## **Deploying and Testing the Contract**
+
+### Compile and Deploy the Contract
+
+1. Open Remix IDE.
+2. Create a new file and paste the Solidity code above.
+
+
+
+3. Compile the contract by selecting the appropriate Solidity compiler version (0.8.x).
+
+
+
+4. Connect Remix to your Metamask wallet (with Flow EVM testnet) by selecting **Injected Web3** as the environment.
+
+
+
+5. Deploy the contract.
+
+
+
+### Call revertibleRandom
+
+After deployment, you can interact with the contract to retrieve a random number.
+
+Call the `revertibleRandom()` function in the left sidebar on the deployed contract. This will fetch a pseudo-random
+number generated by Flow’s VRF.
+
+
+
+The result will be a `uint64` random number generated on Flow EVM.
+
+---
+
+## **Generating Random Numbers in a Range**
+
+For use-cases like games and lotteries, it’s useful to generate a random number within a specified range, the following
+example shows how to get a value between a min and max number.
+
+```solidity
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity >=0.7.0 <0.9.0;
+
+contract RandomInRange {
+ address constant public cadenceArch = 0x0000000000000000000000010000000000000001;
+
+ // Generate a random number between min and max
+ function getRandomInRange(uint64 min, uint64 max) public view returns (uint64) {
+ // Static call to the Cadence Arch contract's revertibleRandom function
+ (bool ok, bytes memory data) = cadenceArch.staticcall(abi.encodeWithSignature("revertibleRandom()"));
+ require(ok, "Failed to fetch a random number through Cadence Arch");
+ uint64 randomNumber = abi.decode(data, (uint64));
+
+ // Return the number in the specified range
+ return (randomNumber % (max + 1 - min)) + min;
+ }
+}
+```
+
+:::warning
+
+The above code is susceptible to the [modulo
+bias](https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/),
+particularly if the random number range is not a multiple of your desired range. To avoid this, you can use a more
+complex algorithm like rejection sampling, an example for which is provided in [this
+repository](https://github.com/onflow/random-coin-toss).
+
+:::
+
+## **Secure Randomness with Commit-Reveal Scheme in Solidity**
+
+The **`revertibleRandom()`** function can be directly used to generate a pseudo-random number. However, in certain
+situations, especially involving untrusted callers, this function exposes a vulnerability: the ability of a transaction
+to **revert after seeing the random result**.
+
+**The Issue with Using `revertibleRandom()` Directly:**
+
+- When an untrusted party calls a contract function that uses `revertibleRandom()`, they receive the random number
+ **during the transaction execution**.
+- **Post-selection** is the ability of the caller to abort the transaction if the random outcome is unfavorable. In this
+ case, the user could choose to revert the transaction (for example, if they lose a bet) and attempt to call the
+ function again in hopes of a better outcome.
+- This can lead to a form of **transaction reversion attack**, where the randomness can be exploited by repeatedly
+ attempting transactions until a favorable result is obtained.
+
+## Read More
+
+For further details on Flow’s randomness and secure development practices, check out the [Flow Randomness
+Documentation](https://developers.flow.com/build/advanced-concepts/randomness).
+
+You can also view an example in both Solidity and Cadence of a [random coin toss
+implentation](https://github.com/onflow/random-coin-toss) using the VRF.
+
+_This documentation was contributed by [Noah Naizir](https://x.com/noah_overflow), a community developer._
+
+
+=== evm/guides/remix.md ===
+---
+title: Flow Remix Guide
+description: 'Using Remix to deploy a solidity contract to Flow EVM.'
+sidebar_label: Remix
+sidebar_position: 3
+---
+
+# Using Remix
+
+Remix is an open-source, web-based development environment tailored for EVM smart contract development. It offers developers a comprehensive suite of tools for writing, deploying, and testing smart contracts in Solidity. For more information, visit [Remix](https://remix.ethereum.org/).
+
+## Add the Flow Network to MetaMask
+
+
+
+Navigate to the [Using EVM](../using.mdx) page to find the button to add the Flow network information to your metamask.
+
+## Fund Your Flow Account
+
+Navigate to the [Flow Testnet Faucet](https://faucet.flow.com/fund-account) to obtain FLOW tokens necessary for deploying a smart contract.
+
+## Deploying a Smart Contract Using Remix
+
+
+
+### HelloWorld Smart Contract
+
+```solidity
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+contract HelloWorld {
+ // Declare a public field of type string.
+ string public greeting;
+
+ // Constructor to initialize the greeting.
+ // In Solidity, the constructor is defined with the "constructor" keyword.
+ constructor() {
+ greeting = "Hello, World!";
+ }
+
+ // Public function to change the greeting.
+ // The "public" keyword makes the function accessible from outside the contract.
+ function changeGreeting(string memory newGreeting) public {
+ greeting = newGreeting;
+ }
+
+ // Public function that returns the greeting.
+ // In Solidity, explicit return types are declared.
+ function hello() public view returns (string memory) {
+ return greeting;
+ }
+}
+
+
+```
+
+### Steps to Deploy the HelloWorld Smart Contract
+
+1. Create a file named `HelloWorld.sol`.
+2. Select Solidity Compiler and compile `HelloWorld.sol`.
+3. Select Deploy & Run Transactions.
+4. Make sure to select `Injected Provider - Metamask` in Environment dropdown.
+5. Deploy the `HelloWorld` smart contract.
+
+## Calling the Deployed Smart Contract
+
+
+
+### Using Ethers.js to Call the HelloWorld Smart Contract
+
+1. Create a new `get-greeting.js` file under `scripts`.
+2. Paste in the JavaScript code below.
+3. Click on green play button to run.
+4. Verify the greeting is "Hello World!".
+
+```javascript
+// Import ethers from the ethers.js library
+const { ethers } = require('ethers');
+
+// Define the contract ABI
+const contractABI = ['function hello() public view returns (string memory)'];
+
+// Define the contract address
+const contractAddress = '0x8a120383e6057b1f3aef4fa9b89c2f1b0a695926';
+
+// Connect to the Ethereum network
+// This example uses the default provider from ethers.js, which connects to the Ethereum mainnet.
+// For a testnet or custom RPC, use ethers.getDefaultProvider('networkName') or new ethers.providers.JsonRpcProvider(url)
+const provider = new ethers.providers.Web3Provider(window?.ethereum);
+
+// Create a new contract instance
+const contract = new ethers.Contract(contractAddress, contractABI, provider);
+
+// Call the hello function of the contract
+async function getGreeting() {
+ const greeting = await contract.hello();
+ console.log(greeting);
+}
+
+// Execute the function
+getGreeting();
+```
+
+Follow the steps below to change the greeting and retrieve the new greeting.
+
+## Updating the Deployed Smart Contract
+
+
+
+1. Select the `HelloWorld.sol` file.
+2. Select the `Deploy and Run Transaction` page.
+3. Make sure to select `Injected Provider - Metamask` in Environment dropdown.
+4. Type a new greeting in the text input next to orange `changeGreeting` button.
+5. Click on the orange `changeGreeting` button.
+6. Sign the Metamask transaction.
+7. Verify the greeting has changed by re-running `get-greeting.js` script above.
+
+
+=== evm/guides/rainbowkit.md ===
+---
+title: Using Rainbowkit with Flow Wallet
+description: A step-by-step guide on adding Flow Wallet as a custom Wallet to RainbowKit.
+sidebar_position: 4
+sidebar_label: Rainbowkit
+---
+
+Integrating Flow Wallet with [RainbowKit][1] allows users to seamlessly connect their Flow accounts through one of the most popular wallet connection interfaces.
+
+This guide walks you through the process of defining Flow Wallet as a custom wallet in RainbowKit and testing the integration. You can follow along by setting up a new RainbowKit project or use the code in this guide to integrate these steps into your existing dApp.
+
+## Objectives
+
+After completing this guide, you'll be able to:
+- Create a custom Flow Wallet connector compatible with RainbowKit's interface
+- Configure your Wagmi setup to support Flow Wallet connections
+- Implement a complete wallet connection flow for Flow blockchain users
+- Test and verify the Flow Wallet integration in your dApp
+
+## Prerequisites
+
+### Next.js and Modern Frontend Development
+
+The RainbowKit starter is built on Next.js, so familiarity with React, hooks, and modern frontend development will help you follow along.
+
+## A Flow Wallet
+
+To use Flow Wallet with RainbowKit, install the Flow Wallet browser extension from the [Chrome Web Store][2].
+
+Once installed, set up your wallet by creating or importing an account. For quick access, pin the extension to your browser toolbar.
+
+## Setting Up Your Environment
+
+### Initial Setup
+
+The RainbowKit starter is built on Next.js, following its standard project structure and conventions. Create a new project or ensure your existing one has the necessary dependencies:
+
+```bash
+$ npm init @rainbow-me/rainbowkit@latest
+$ cd my-rainbowkit-app
+$ npm run dev
+```
+
+The [RainbowKit](https://www.rainbowkit.com/) components will be available throughout your application via the provided wrapper components.
+
+### Creating the Flow Wallet Connector
+The first major step is defining the Flow Wallet connector. Create a new file called `flowWallet.ts` in `src/flowWallet.ts` to house the wallet configuration:
+
+```tsx
+/* src/flowWallet.ts */
+import { Wallet, getWalletConnectConnector } from '@rainbow-me/rainbowkit';
+
+export interface MyWalletOptions {
+ projectId: string;
+}
+
+export const flowWallet = ({ projectId }: MyWalletOptions): Wallet => ({
+ id: 'flow-wallet',
+ name: 'Flow Wallet',
+ iconUrl: 'https://lilico.app/logo_mobile.png',
+ iconBackground: '#41CC5D',
+ downloadUrls: {
+ android: 'https://play.google.com/store/apps/details?id=com.flowfoundation.wallet',
+ ios: 'https://apps.apple.com/ca/app/flow-wallet-nfts-and-crypto/id6478996750',
+ chrome: 'https://chromewebstore.google.com/detail/flow-wallet/hpclkefagolihohboafpheddmmgdffjm',
+ qrCode: 'https://link.lilico.app',
+ },
+ mobile: {
+ getUri: (uri: string) => uri,
+ },
+ qrCode: {
+ getUri: (uri: string) => uri,
+ instructions: {
+ learnMoreUrl: 'https://wallet.flow.com',
+ steps: [
+ {
+ description: 'We recommend putting Flow Wallet on your home screen for faster access to your wallet.',
+ step: 'install',
+ title: 'Open the Flow Wallet app',
+ },
+ {
+ description: 'You can find the scan button on home page, a connection prompt will appear for you to connect your wallet.',
+ step: 'scan',
+ title: 'Tap the scan button',
+ },
+ ],
+ },
+ },
+ extension: {
+ instructions: {
+ learnMoreUrl: 'https://wallet.flow.com',
+ steps: [
+ {
+ description: 'We recommend pinning Flow Wallet to your taskbar for quicker access to your wallet.',
+ step: 'install',
+ title: 'Install the Flow Wallet extension',
+ },
+ {
+ description: 'Be sure to back up your wallet using a secure method. Never share your secret phrase with anyone.',
+ step: 'create',
+ title: 'Create or Import a Wallet',
+ },
+ {
+ description: 'Once you set up your wallet, click below to refresh the browser and load up the extension.',
+ step: 'refresh',
+ title: 'Refresh your browser',
+ },
+ ],
+ },
+ },
+ createConnector: getWalletConnectConnector({ projectId }),
+});
+```
+
+### Configuring Wagmi Integration
+
+Next, update your Wagmi configuration to include Flow Wallet support. Modify your `wagmi.ts` file:
+
+```tsx
+/* src/wagmi.ts */
+'use client';
+
+import { connectorsForWallets } from '@rainbow-me/rainbowkit';
+import { createConfig, http } from 'wagmi';
+import { mainnet, flowMainnet } from 'viem/chains';
+import { flowWallet } from './flowWallet';
+
+/*
+We can leave this as is for the tutorial but it should be
+replaced with your own project ID for production use.
+*/
+const projectId = 'YOUR_PROJECT_ID';
+
+const connectors = connectorsForWallets(
+ [
+ {
+ groupName: 'Recommended',
+ wallets: [flowWallet]
+ },
+ ],
+ {
+ appName: 'RainbowKit App',
+ projectId,
+ }
+);
+
+export const config = createConfig({
+ connectors,
+ chains: [flowMainnet, mainnet],
+ ssr: true,
+ transports: {
+ [flowMainnet.id]: http(),
+ [mainnet.id]: http(),
+ },
+});
+```
+
+:::info
+
+WalletConnect Project ID
+
+Every dApp that relies on WalletConnect now needs to obtain a projectId from [WalletConnect Cloud (now rebranded as reown)](https://cloud.reown.com/sign-in). This is absolutely free and only takes a few minutes.
+
+To get a Project ID, sign up at WalletConnect Cloud, create a new project, and copy the generated ID into the `projectId` variable in the `wagmi.ts` file.
+
+:::
+
+## Testing Your Integration
+
+After implementing the Flow Wallet connector and configuring Wagmi, follow these steps to verify that the integration works correctly in your dApp:
+
+1. **Click "Connect Wallet"** – Open your application and click the "Connect Wallet" button.
+2. **Check for Flow Wallet** – Ensure Flow Wallet appears as an option in the RainbowKit wallet selection modal.
+ - If you haven't installed the browser extension and set up your wallet yet, you can find install it via the [Chrome Web Store][2].
+3. **Connect the Wallet** – Click on Flow Wallet in the selection modal. If using the browser extension, open it and press "Connect."
+
+
+
+4. **Verify Connection** – Confirm that your Flow Wallet is now connected and visible in your dApp's UI.
+
+
+
+## Conclusion
+
+In this tutorial, you learned how to integrate Flow Wallet with [RainbowKit](https://www.rainbowkit.com/), creating a seamless wallet connection experience for your users. You should now be able to:
+- Create a custom Flow Wallet connector compatible with RainbowKit's interface
+- Configure your Wagmi setup to support Flow Wallet connections
+- Implement a complete wallet connection flow for Flow blockchain users
+- Test and verify the Flow Wallet integration in your dApp
+
+Now that you've completed this tutorial, you're ready to enhance your dApp with additional Flow blockchain features such as token transfers, NFT minting, and smart contract interactions.
+
+[1]: https://www.rainbowkit.com/
+[2]: https://chromewebstore.google.com/detail/flow-wallet/hpclkefagolihohboafpheddmmgdffjm?hl=en
+
+=== evm/guides/integrating-metamask.mdx ===
+---
+title: Integrating Metamask
+sidebar_position: 1
+---
+
+import BrowserOnly from '@docusaurus/BrowserOnly';
+import { AddNetworkButton } from '@site/src/components/addNetworkButton';
+
+# Wallets & Configurations
+
+This document shows how to integrate the Flow Network programmatically with your Dapp via MetaMask.
+
+If you want to add it to your wallet now, you can click the buttons below, or follow the [manual process].
+
+
+ {() => {
+ // ******* If Chain Id changes, update the Chain ID in the AddNetworkButton component *******
+ return ;
+ }}
+
+
+## Metamask
+
+Integrating additional networks into MetaMask can pose challenges for users who lack technical expertise and may lead to errors. Simplifying this process can greatly enhance user onboarding for your application. This guide demonstrates how to create a straightforward button within your frontend application to streamline the addition of the Flow network to MetaMask.
+
+### EIP-3035 & MetaMask
+
+[EIP-3035](https://eips.ethereum.org/EIPS/eip-3085) is an Ethereum Improvement Proposal that defines an RPC method for adding Ethereum-compatible chains to wallet applications. Since March 2021 MetaMask has implemented that EIP as part of their MetaMask [Custom Networks API](https://consensys.io/blog/connect-users-to-layer-2-networks-with-the-metamask-custom-networks-api).
+
+### Flow Network configuration
+
+To add the Flow Testnet network to Metamask, add the following network configuration:
+
+```js
+export const TESTNET_PARAMS = {
+ chainId: '0x221',
+ chainName: 'Flow',
+ rpcUrls: ['https://testnet.evm.nodes.onflow.org'],
+ nativeCurrency: {
+ name: 'Flow',
+ symbol: 'FLOW',
+ decimals: 18,
+ },
+ blockExplorerUrls: ['https://evm-testnet.flowscan.io/']
+};
+```
+
+### Adding Flow Network
+
+To add this configuration to MetaMask, call the `wallet_addEthereumChain` method which is exposed by the web3 provider.
+
+```js
+function addFlowTestnet() {
+ injected.getProvider().then((provider) => {
+ provider
+ .request({
+ method: 'wallet_addEthereumChain',
+ params: [TESTNET_PARAMS],
+ })
+ .catch((error: any) => {
+ console.log(error);
+ });
+ });
+}
+```
+
+The variable, `injected`, is initialized as a `web3-react/injected-connector` used to interface with MetaMask APIs. Usage for other popular web frameworks is similar.
+
+The typical usage would be to expose this button if you get errors when attempting to connect to MetaMask (i.e. `Wrong Network` or `Error Connecting`).
+
+### User Experience
+
+Users of your app will need to first approve a connection to Metamask. After doing this, if you don't detect a successful Web3 network connection, you may present a dialog asking them to add the Flow network to their wallet.
+
+
+
+After they approve, your app will be connected to the Flow network.
+
+By using this approach to add the Flow network to Metamask, you can avoid manual user data entry and ensure that users are ready to interact with your dApp!
+
+{/* Reference-style links, does not render on page */}
+
+[manual process]: ../using.mdx
+
+
+=== evm/guides/hardhat.md ===
+---
+title: Flow Hardhat Guide
+description: 'Using Hardhat to deploy a Solidity contract to Flow EVM.'
+sidebar_label: Hardhat
+sidebar_position: 2
+---
+
+# Flow Hardhat Guide
+
+Hardhat is an Ethereum development tool designed to facilitate the deployment, testing, and debugging of smart contracts. It provides a streamlined experience for developers working with Solidity contracts.
+
+## Prerequisites
+
+### Node
+
+Node v18 or higher, available for [download here](https://nodejs.org/en/download).
+
+For those new to Hardhat, we recommend exploring the [official documentation](https://hardhat.org/tutorial/creating-a-new-hardhat-project) to get acquainted. The following instructions utilize `npm` to initialize a project and install dependencies:
+
+### Wallet
+
+You'll also need a wallet that supports EVM. For this guide, a MetaMask account and its corresponding private key will work.
+
+```shell
+mkdir hardhat-example
+cd hardhat-example
+
+npm init
+
+npm install --save-dev hardhat
+
+npx hardhat init
+```
+
+> When prompted, select TypeScript and to use `@nomicfoundation/hardhat-toolbox` to follow along with this guide.
+
+### Fund Your Wallet
+
+To deploy smart contracts, ensure your wallet has **$FLOW**. Obtain funds by navigating to the Flow [Faucet](https://faucet.flow.com/fund-account) and entering your wallet address.
+
+## Deploying a Smart Contract with Hardhat
+
+This section guides you through the process of deploying smart contracts on the Flow network using Hardhat.
+
+### Configuration
+
+First, incorporate the Testnet network into your `hardhat.config.ts`:
+
+```javascript
+import { HardhatUserConfig } from 'hardhat/config';
+import '@nomicfoundation/hardhat-toolbox';
+
+const config: HardhatUserConfig = {
+ solidity: '0.8.24',
+ networks: {
+ testnet: {
+ url: 'https://testnet.evm.nodes.onflow.org',
+ accounts: [``], // In practice, this should come from an environment variable and not be commited
+ gas: 500000, // Example gas limit
+ },
+ },
+};
+
+export default config;
+```
+
+To keep this example straightforward, we've included the account's private key directly in `hardhat.config.ts`. However, it is crucial to avoid committing private keys to your Git repository for security reasons. Instead, opt for using environment variables for safer handling of sensitive information.
+
+### Deploying HelloWorld Smart Contract
+
+## HelloWorld Smart Contract
+
+```solidity
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+contract HelloWorld {
+ // Declare a public field of type string.
+ string public greeting;
+
+ // Constructor to initialize the greeting.
+ // In Solidity, the constructor is defined with the "constructor" keyword.
+ constructor() {
+ greeting = "Hello, World!";
+ }
+
+ // Public function to change the greeting.
+ // The "public" keyword makes the function accessible from outside the contract.
+ function changeGreeting(string memory newGreeting) public {
+ greeting = newGreeting;
+ }
+
+ // Public function that returns the greeting.
+ // In Solidity, explicit return types are declared.
+ function hello() public view returns (string memory) {
+ return greeting;
+ }
+}
+```
+
+Deploying:
+
+1. Create a file named `HelloWorld.sol` under `contracts` directory.
+2. Add above `HelloWorld.sol` contract code to new file.
+3. Create a `deploy.ts` file in `scripts` directory.
+4. Paste in the following TypeScript code.
+
+```javascript
+import { ethers } from 'hardhat';
+
+async function main() {
+ const [deployer] = await ethers.getSigners();
+
+ console.log('Deploying contracts with the account:', deployer.address);
+
+ const deployment = await ethers.deployContract('HelloWorld');
+
+ console.log('HelloWorld address:', await deployment.getAddress());
+}
+
+main()
+ .then(() => process.exit(0))
+ .catch((error) => {
+ console.error(error);
+ process.exit(1);
+ });
+```
+
+5. Run `npx hardhat run scripts/deploy.ts --network testnet` in the project root.
+6. Copy the deployed `HelloWorld` address. This address will be used in other scripts.
+
+Output should look like this (with the exception that your address will be different):
+
+```shell
+❯ npx hardhat run scripts/deploy.ts --network testnet
+Deploying contracts with the account: ...
+HelloWorld address: 0x3Fe94f43Fb5CdB8268A801f274521a07F7b99dfb
+```
+
+You can now search for your deployed contract on the [Flowscan block explorer](https://evm-testnet.flowscan.io/)!
+
+### Get HelloWorld Contract Greeting
+
+Now, we want to get the greeting from the deployed `HelloWorld` smart contract.
+
+```javascript
+import { ethers } from 'hardhat';
+import HelloWorldABI from '../artifacts/contracts/HelloWorld.sol/HelloWorld.json';
+
+async function main() {
+ // Replace with your contract's address
+ const contractAddress = '0x3Fe94f43Fb5CdB8268A801f274521a07F7b99dfb';
+ // Get hardhat provider
+ const provider = ethers.provider;
+ // Create a new contract instance
+ const helloWorldContract = new ethers.Contract(
+ contractAddress,
+ HelloWorldABI.abi,
+ provider,
+ );
+ // Call the greeting function
+ const greeting = await helloWorldContract.hello();
+ console.log('The greeting is:', greeting);
+}
+
+main().catch((error) => {
+ console.error(error);
+ process.exit(1);
+});
+```
+
+Steps:
+
+1. Create a `getGreeting.ts` file in the `scripts` directory.
+2. Paste contents of script above. Make sure to update the contract address with the one from deployment in earlier step.
+3. Call script to get the greeting, `npx hardhat run scripts/getGreeting.ts --network testnet`
+4. The output should be as follows:
+
+```shell
+❯ npx hardhat run scripts/getGreeting.ts --network testnet
+The greeting is: Hello, World!
+```
+
+### Update Greeting on HelloWorld Smart Contract
+
+Next, we'll add a script to update the greeting and log it.
+
+```javascript
+import { ethers } from 'hardhat';
+import HelloWorldABI from '../artifacts/contracts/HelloWorld.sol/HelloWorld.json';
+
+async function main() {
+ const contractAddress = '0x3Fe94f43Fb5CdB8268A801f274521a07F7b99dfb';
+
+ const newGreeting = process.env.NEW_GREETING;
+ if (!newGreeting) {
+ console.error('Please set the NEW_GREETING environment variable.');
+ process.exit(1);
+ }
+
+ // Signer to send the transaction (e.g., the first account from the hardhat node)
+ const [signer] = await ethers.getSigners();
+
+ // Contract instance with signer
+ const helloWorldContract = new ethers.Contract(
+ contractAddress,
+ HelloWorldABI.abi,
+ signer,
+ );
+
+ console.log('The greeting is:', await helloWorldContract.hello());
+
+ // Create and send the transaction
+ const tx = await helloWorldContract.changeGreeting(newGreeting);
+ console.log('Transaction hash:', tx.hash);
+
+ // Wait for the transaction to be mined
+ await tx.wait().catch((error: Error) => {});
+ console.log('Greeting updated successfully!');
+ console.log('The greeting is:', await helloWorldContract.hello());
+}
+
+main().catch((error) => {
+ console.error(error);
+ process.exit(1);
+});
+```
+
+Here are the steps to follow:
+
+1. Create an `updateGreeting.ts` script in the `scripts` directory.
+2. Paste in the TypeScript above, make sure to update the contract address with the one from deployment in earlier step.
+3. Call the new script, `NEW_GREETING='Howdy!' npx hardhat run ./scripts/updateGreeting.ts --network testnet`
+4. The output should be
+
+```shell
+❯ NEW_GREETING='Howdy!' npx hardhat run ./scripts/updateGreeting.ts --network testnet
+The greeting is: Hello, World!
+Transaction hash: 0x03136298875d405e0814f54308390e73246e4e8b4502022c657f04f3985e0906
+Greeting updated successfully!
+The greeting is: Howdy!
+```
+
+
+### Verifying Contract
+
+To verify your contract on [Flowscan](https://evm-testnet.flowscan.io/), you can update your Hardhat config file as such including the correct chainID, apiURL and browserURL:
+
+```javascript
+import { HardhatUserConfig } from 'hardhat/config';
+import '@nomicfoundation/hardhat-toolbox';
+import "@nomicfoundation/hardhat-verify";
+
+const PRIVATE_KEY = vars.get("EVM_PRIVATE_KEY");
+
+const config: HardhatUserConfig = {
+ solidity: '0.8.24',
+ networks: {
+ testnet: {
+ url: 'https://testnet.evm.nodes.onflow.org',
+ accounts: [PRIVATE_KEY], // In practice, this should come from an environment variable and not be commited
+ gas: 500000, // Example gas limit
+ },
+ },
+ etherscan: {
+ apiKey: {
+ // Is not required by blockscout. Can be any non-empty string
+ 'testnet': "abc"
+ },
+ customChains: [
+ {
+ network: "testnet",
+ chainId: 545,
+ urls: {
+ apiURL: "https://evm-testnet.flowscan.io/api",
+ browserURL: "https://evm-testnet.flowscan.io/",
+ }
+ }
+ ]
+ },
+ sourcify: {
+ enabled: false
+ }
+};
+
+export default config;
+```
+
+The [verify](https://docs.blockscout.com/developer-support/verifying-a-smart-contract/hardhat-verification-plugin) plugin requires you to include constructor arguments with the verify task and ensures that they correspond to expected ABI signature. However, Blockscout ignores those arguments, so you may specify any values that correspond to the ABI. Execute the following command to verify the contract:
+
+```shell
+npx hardhat verify --network testnet DEPLOYED_CONTRACT_ADDRESS "Constructor argument 1"
+```
+
+=== evm/guides/foundry.md ===
+---
+title: Using Foundry with Flow
+description: 'Using Foundry to deploy a Solidity contract to Flow EVM.'
+sidebar_label: Foundry
+sidebar_position: 5
+---
+
+# Using Foundry with Flow
+
+Foundry is a suite of development tools that simplifies the process of developing and deploying Solidity contracts to EVM networks. This guide will walk you through the process of deploying a Solidity contract to Flow EVM using the Foundry development toolchain. You can check out the official Foundry docs [here](https://book.getfoundry.sh/).
+
+In this guide, we'll deploy an ERC-20 token contract to Flow EVM using Foundry. We'll cover:
+
+- Developing and testing a basic ERC-20 contract
+- Deploying the contract to Flow EVM using Foundry tools
+- Querying Testnet state
+- Mutating Testnet state by sending transactions
+
+## Overview
+
+To use Flow across all Foundry tools you need to:
+
+1. Provide the Flow EVM RPC URL to the command you are using:
+
+ ```shell
+ --rpc-url https://testnet.evm.nodes.onflow.org
+ ```
+
+2. Use the `--legacy` flag to disable [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) style transactions. Flow will support EIP-1559 soon and this flag won't be needed.
+
+As an example, we'll show you how to deploy a fungible token contract to Flow EVM using Foundry. You will see how the above flags are used in practice.
+
+## Example: Deploying an ERC-20 Token Contract to Flow EVM
+
+ERC-20 tokens are the most common type of tokens on Ethereum. We'll use [OpenZeppelin](https://www.openzeppelin.com/) starter templates with Foundry on Flow Testnet to deploy our own token called `MyToken`.
+
+### Installation
+
+The best way to install Foundry, is to use the `foundryup` CLI tool. You can get it using the following command:
+
+```shell
+curl -L https://foundry.paradigm.xyz | bash
+```
+
+Install the tools:
+
+```shell
+foundryup
+```
+
+This will install the Foundry tool suite: `forge`, `cast`, `anvil`, and `chisel`.
+
+You may need to reload your shell after `foundryup` installation.
+
+Check out the official [Installation](https://book.getfoundry.sh/getting-started/installation) guide for more information about different platforms or installing specific versions.
+
+### Wallet Setup
+
+We first need to generate a key pair for our EVM account. We can do this using the `cast` tool:
+
+```shell
+cast wallet new
+```
+
+`cast` will print the private key and address of the new account. We can then paste the account address into the [Faucet](https://faucet.flow.com/fund-account) to fund it with some Testnet FLOW tokens.
+
+You can verify the balance of the account after funding. Replace `$YOUR_ADDRESS` with the address of the account you funded:
+
+```shell
+cast balance --ether --rpc-url https://testnet.evm.nodes.onflow.org $YOUR_ADDRESS
+```
+
+### Project Setup
+
+First, create a new directory for your project:
+
+```shell
+mkdir mytoken
+cd mytoken
+```
+
+We can use `init` to initialize a new project:
+
+```shell
+forge init
+```
+
+This will create a contract called `Counter` in the `contracts` directory with associated tests and deployment scripts. We can replace this with our own ERC-20 contract. To verify the initial setup, you can run the tests for `Counter`:
+
+```shell
+forge test
+```
+
+The tests should pass.
+
+### Writing the ERC-20 Token Contract
+
+We'll use the OpenZeppelin ERC-20 contract template. We can start by adding OpenZeppelin to our project:
+
+```shell
+forge install OpenZeppelin/openzeppelin-contracts
+```
+
+Rename `src/Counter.sol` to `src/MyToken.sol` and replace the contents with the following:
+
+```solidity
+pragma solidity ^0.8.20;
+
+import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
+
+contract MyToken is ERC20 {
+ constructor(uint256 initialMint_) ERC20("MyToken", "MyT") {
+ _mint(msg.sender, initialMint_);
+ }
+}
+```
+
+The above is a basic ERC-20 token with the name `MyToken` and symbol `MyT`. It also mints the specified amount of tokens to the contract deployer. The amount is passed as a constructor argument during deployment.
+
+Before compiling, we also need to update the test file.
+
+### Testing
+
+Rename `test/Counter.t.sol` to `test/MyToken.t.sol` and replace the contents with the following:
+
+```solidity
+pragma solidity ^0.8.20;
+
+import {Test, console2, stdError} from "forge-std/Test.sol";
+import {MyToken} from "../src/MyToken.sol";
+
+contract MyTokenTest is Test {
+ uint256 initialSupply = 420000;
+
+ MyToken public token;
+ address ownerAddress = makeAddr("owner");
+ address randomUserAddress = makeAddr("user");
+
+ function setUp() public {
+ vm.prank(ownerAddress);
+ token = new MyToken(initialSupply);
+ }
+
+ /*
+ Test general ERC-20 token properties
+ */
+ function test_tokenProps() public view {
+ assertEq(token.name(), "MyToken");
+ assertEq(token.symbol(), "MyT");
+ assertEq(token.decimals(), 18);
+ assertEq(token.totalSupply(), initialSupply);
+ assertEq(token.balanceOf(address(0)), 0);
+ assertEq(token.balanceOf(ownerAddress), initialSupply);
+ }
+
+ /*
+ Test Revert transfer to sender with insufficient balance
+ */
+ function test_transferRevertInsufficientBalance() public {
+ vm.prank(randomUserAddress);
+ vm.expectRevert(abi.encodeWithSignature("ERC20InsufficientBalance(address,uint256,uint256)", randomUserAddress, 0, 42));
+ token.transfer(ownerAddress, 42);
+ }
+
+ /*
+ Test transfer
+ */
+ function test_transfer() public {
+ vm.prank(ownerAddress);
+ assertEq(token.transfer(randomUserAddress, 42), true);
+ assertEq(token.balanceOf(randomUserAddress), 42);
+ assertEq(token.balanceOf(ownerAddress), initialSupply - 42);
+ }
+
+ /*
+ Test transferFrom with approval
+ */
+ function test_transferFrom() public {
+ vm.prank(ownerAddress);
+ token.approve(randomUserAddress, 69);
+
+ uint256 initialRandomUserBalance = token.balanceOf(randomUserAddress);
+ uint256 initialOwnerBalance = token.balanceOf(ownerAddress);
+
+ vm.prank(randomUserAddress);
+ assertEq(token.transferFrom(ownerAddress, randomUserAddress, 42), true);
+ assertEq(token.balanceOf(randomUserAddress), initialRandomUserBalance + 42);
+ assertEq(token.balanceOf(ownerAddress), initialOwnerBalance - 42);
+ assertEq(token.allowance(ownerAddress, randomUserAddress), 69 - 42);
+ }
+}
+```
+
+You can now make sure everything is okay by compiling the contracts:
+
+```shell
+forge compile
+```
+
+Run the tests:
+
+```shell
+forge test
+```
+
+They should all succeed.
+
+### Deploying to Flow Testnet
+
+We can now deploy `MyToken` using the `forge create` command. We need to provide the RPC URL, private key from a funded account using the faucet, and constructor arguments that is the initial mint amount in this case. We need to use the `--legacy` flag to disable EIP-1559 style transactions. Replace `$DEPLOYER_PRIVATE_KEY` with the private key of the account you created earlier:
+
+```shell
+forge create --rpc-url https://testnet.evm.nodes.onflow.org \
+ --private-key $DEPLOYER_PRIVATE_KEY \
+ --constructor-args 42000000 \
+ --legacy \
+ src/MyToken.sol:MyToken
+```
+
+The above will print the deployed contract address. We'll use it in the next section to interact with the contract.
+
+### Verifying a Smart Contract
+
+Once deployed, you can verify the contract so that others can see the source code and interact with it from Flow's block explorer. You can use the [`forge verify-contract`](https://book.getfoundry.sh/reference/forge/forge-verify-contract) command:
+
+```shell
+forge verify-contract --rpc-url https://testnet.evm.nodes.onflow.org/ \
+ --verifier blockscout \
+ --verifier-url https://evm-testnet.flowscan.io/api \
+ $DEPLOYED_MYTOKEN_ADDRESS \
+ src/MyToken.sol:MyToken
+````
+
+:::info
+
+When verifying a Mainnet contract, be sure to use the Mainnet [RPC](../../evm/networks.md) and block explorer URLs.
+
+:::
+
+### Querying Testnet State
+
+Based on the given constructor arguments, the deployer should own `42,000,000 MyT`. We can check the `MyToken` balance of the contract owner. Replace `$DEPLOYED_MYTOKEN_ADDRESS` with the address of the deployed contract and `$DEPLOYER_ADDRESS` with the address of the account you funded earlier:
+
+```shell
+cast balance \
+ --rpc-url https://testnet.evm.nodes.onflow.org \
+ --erc20 $DEPLOYED_MYTOKEN_ADDRESS \
+ $DEPLOYER_ADDRESS
+```
+
+This should return the amount specified during deployment. We can also call the associated function directly in the contract:
+
+```shell
+cast call $DEPLOYED_MYTOKEN_ADDRESS \
+ --rpc-url https://testnet.evm.nodes.onflow.org \
+ "balanceOf(address)(uint256)" \
+ $DEPLOYER_ADDRESS
+```
+
+We can query other data like the token symbol:
+
+```shell
+cast call $DEPLOYED_MYTOKEN_ADDRESS \
+ --rpc-url https://testnet.evm.nodes.onflow.org \
+ "symbol()(string)"
+```
+
+### Sending Transactions
+
+Let's create a second account and move some tokens using a transaction. You can use `cast wallet new` to create a new test account. You don't need to fund it to receive tokens. Replace `$NEW_ADDRESS` with the address of the new account:
+
+```shell
+cast send $DEPLOYED_MYTOKEN_ADDRESS \
+ --rpc-url https://testnet.evm.nodes.onflow.org \
+ --private-key $DEPLOYER_PRIVATE_KEY \
+ --legacy \
+ "transfer(address,uint256)(bool)" \
+ $NEW_ADDRESS 42
+```
+
+We can check the balance of the new account:
+
+```shell
+cast balance \
+ --rpc-url https://testnet.evm.nodes.onflow.org \
+ --erc20 $DEPLOYED_MYTOKEN_ADDRESS \
+ $NEW_ADDRESS
+```
+
+The deployer should also own less tokens now:
+
+```shell
+cast balance \
+ --rpc-url https://testnet.evm.nodes.onflow.org \
+ --erc20 $DEPLOYED_MYTOKEN_ADDRESS \
+ $DEPLOYER_ADDRESS
+```
+
+
+=== evm/guides/ethers.md ===
+---
+title: Ethers.js on Flow Blockchain
+sidebar_label: Ethers
+sidebar_position: 8
+---
+
+# Ethers.js
+
+[ethers.js](https://docs.ethers.org/v5/) is a powerful JavaScript library for interacting with Ethereum and other EVM-compatible blockchain networks.
+
+In this guide, we'll walk you through how to use ethers.js to interact with smart contracts on the Flow Blockchain.
+
+---
+
+## Installation
+
+To begin using ethers.js in your project, you'll need to install the package. You can do this by running the following command:
+
+```bash
+bashCopy code
+npm install --save ethers
+
+```
+
+## Setup
+
+After installing ethers.js, the next step is to import it into your project.
+
+You can do this by adding the following line of code at the beginning of your JavaScript file:
+
+```jsx
+const ethers = require('ethers');
+```
+
+## Connecting to Flow
+
+To connect to the Flow Blockchain using ethers.js, you need to create a new `JsonRpcProvider` instance with the appropriate RPC URL for Flow:
+
+```jsx
+const ethers = require('ethers');
+
+const url = 'https://testnet.evm.nodes.onflow.org/';
+const provider = new ethers.providers.JsonRpcProvider(url);
+```
+
+**Note:** If you want to connect to the Flow testnet, replace the above URL with `https://mainnet.evm.nodes.onflow.org`.
+
+## Reading Data from the Blockchain
+
+Once your provider is set up, you can start reading data from the Flow Blockchain. For instance, to retrieve the latest block number, you can use the `getBlockNumber` method:
+
+```jsx
+async function getLatestBlock() {
+ const latestBlock = await provider.getBlockNumber();
+ console.log(latestBlock);
+}
+```
+
+## Writing Data to the Blockchain
+
+To send transactions or write data to the Flow Blockchain, you need to create a `Signer`. This can be done by initializing a new `Wallet` object with your private key and the previously created `Provider`:
+
+```jsx
+const privateKey = 'YOUR_PRIVATE_KEY';
+const signer = new ethers.Wallet(privateKey, provider);
+```
+
+**Note:** Replace `'YOUR_PRIVATE_KEY'` with the actual private key of the wallet you want to use.
+
+## Interacting with Smart Contracts
+
+ethers.js also enables interaction with smart contracts on the Flow Blockchain. To do this, create a `Contract` object using the ABI (Application Binary Interface) and the address of the deployed contract:
+
+```jsx
+const abi = [
+ // ABI of deployed contract
+];
+
+const contractAddress = 'CONTRACT_ADDRESS';
+
+// read-only contract instance
+const contract = new ethers.Contract(contractAddress, abi, provider);
+```
+
+For contracts that require writing, you'll need to provide a `Signer` object instead of a `Provider`:
+
+```jsx
+// write-enabled contract instance
+const contract = new ethers.Contract(contractAddress, abi, signer);
+```
+
+**Note:** Replace `'CONTRACT_ADDRESS'` with the actual address of your deployed contract.
+
+After setting up your `Contract` object, you can call methods on the smart contract as needed:
+
+```jsx
+async function setValue(value) {
+ const tx = await contract.set(value);
+ console.log(tx.hash);
+}
+
+async function getValue() {
+ const value = await contract.get();
+ console.log(value.toString());
+}
+```
+
+
+=== ecosystem/wallets.md ===
+---
+sidebar_position: 2
+description: Store, manage, and interact securely with tokens and digital assets on Flow. Discover a range of wallets that offer convenient ways to handle and safeguard your cryptocurrency holdings, ensuring easy access and enhanced security for your transactions and assets.
+sidebar_custom_props:
+ icon: 🔑
+---
+
+# Wallets
+
+Store, manage, and interact securely with tokens and digital assets on Flow. Discover a range of wallets that offer convenient ways to handle and safeguard your cryptocurrency holdings, ensuring easy access and enhanced security for your transactions and assets.
+
+
+
+## Flow Wallet
+
+[Flow Wallet](https://wallet.flow.com/) is the most popular Flow-native wallet, it sponsors all gas fees for users and interacts seamlessly with both Cadence and EVM dApps in the ecosystem.
+
+## Metamask Wallet
+
+[Metamask](https://metamask.io/) is a secure and user-friendly crypto wallet for NFTs and digital tokens. Presently only supports Flow EVM and cannot access Cadence accounts.
+
+## Dapper Wallet
+
+[Dapper Wallet](https://www.meetdapper.com/) is a wallet exceptionally friendly for first time crypto collectors to buy and manage digital assets.
+
+## Ledger
+
+[Ledger](https://www.ledger.com/) is a hardware wallet to secure, buy, exchange, and grow your crypto assets.
+
+## Finoa
+
+[Finoa](https://www.finoa.io/) is a platform for institutional investors to safely store and stake their FLOW tokens.
+
+## Blocto
+
+[Blocto](https://www.blocto.io/) is a cross-chain mobile wallet for IOS and Android devices.
+
+
+
+## For Developers
+
+
+
+## Flow Dev Wallet
+
+[The Flow Dev Wallet](../tools/flow-dev-wallet/index.md) simulates the protocols used by [FCL](../tools/clients/fcl-js/index.md) to interact with the Flow blockchain on behalf of simulated user accounts.
+
+## Magic.link
+
+[Magic](https://magic.link/) is a developer SDK that integrates with your application to enable passwordless Web3 onboarding (no seed phrases) and authentication using magic links (similar to Slack and Medium).
+
+
+
+
+=== ecosystem/vcs-and-funds.md ===
+---
+title: VCs & Funds
+description: Connect with venture capital firms and investment funds supporting Flow projects
+sidebar_position: 8
+sidebar_custom_props:
+ icon: 💼
+---
+
+# VCs & Funds
+
+Building a successful Web3 project requires more than just great technology - having the right investors and partners can make all the difference. The Flow ecosystem is supported by some of the world's leading venture capital firms and crypto-native funds.
+
+Research shows that warm introductions can increase your chances of securing funding by up to 500% more liley compared to cold outreach. The Flow Foundation can help facilitate introductions to our network of trusted investors who have a deep understanding of the Flow ecosystem and web3. Reach out to your local dev-rel in [office hours](https://calendar.google.com/calendar/u/0/embed?src=c_47978f5cd9da636cadc6b8473102b5092c1a865dd010558393ecb7f9fd0c9ad0@group.calendar.google.com) or [discord](https://discord.gg/flow) to get a warm introduction.
+
+
+
+
+
+
+=== ecosystem/projects.mdx ===
+---
+title: Community Projects
+description: Explore the diverse projects and contributions within the Flow Blockchain community.
+sidebar_position: 7
+sidebar_custom_props:
+ icon: 🏟️
+---
+
+import DocCardList from '@theme/DocCardList';
+
+Explore an array of exciting, grassroots initiatives, and projects that thrive within the Flow Blockchain community, each contributing to the platform's growth and innovation.
+
+
+
+
+=== ecosystem/index.mdx ===
+---
+sidebar_position: 1
+title: Ecosystem
+description: Access essential tools, knowledge, and community connections for the Flow Blockchain ecosystem.
+---
+
+import DocCardList from '@theme/DocCardList';
+import { isSamePath } from '@docusaurus/theme-common/internal';
+import { useDocsSidebar } from '@docusaurus/plugin-content-docs/client';
+import { useLocation } from '@docusaurus/router';
+
+ !isSamePath(item.href, useLocation().pathname)),
+ {
+ type: 'link',
+ label: 'Flow Forum',
+ href: 'https://forum.onflow.org/',
+ description: 'Engage with the Flow community, discuss ideas, and seek support on the Flow Blockchain Forum.',
+ customProps: {
+ icon: "🏛️"
+ },
+ },
+ {
+ type: 'link',
+ label: 'FLIPs',
+ href: 'https://github.com/onflow/flips',
+ description: 'Flow Improvement Proposals (FLIPs) serve as a platform for engaging the Flow community in development, harnessing the collective ideas, insights, and expertise of contributors and experts while ensuring widespread communication of design changes.',
+ customProps: {
+ icon: "📜"
+ },
+ },
+ ]
+}/>
+
+
+=== ecosystem/hackathons.md ===
+---
+title: Hackathons
+description: Participate in Flow hackathons to build, learn, and win prizes
+sidebar_position: 11
+sidebar_custom_props:
+ icon: 🚀
+---
+
+# Flow World Tour Hackathons
+
+Some of the most groundbreaking blockchain projects began as hackathon ideas—CryptoKitties, the game that revolutionized NFTs, was first built at the ETHGlobal Waterloo hackathon. Your project could be next.
+
+## Flow World Tour
+
+We're bringing together builders, creators, and innovators through a series of global hackathons—both in-person and online. These events are more than just competitions; they’re an opportunity to experiment, collaborate, and turn bold ideas into reality.
+
+### Why Join?
+
+#### **Build & Learn**
+
+Get hands-on experience with Flow while accessing expert mentorship, technical workshops, and valuable resources to refine your skills on the cutting edge, from AI agents to next-gen DeFi.
+
+#### **Network & Connect**
+
+Meet like-minded builders, potential co-founders, and potential investors. These events are a gateway to becoming part of the global Flow community.
+
+#### **Win & Launch**
+
+With substantial prize pools, industry recognition, and the chance to launch your project, hackathons can be the stepping stone to your next big startup, side-project, or public good.
+
+## Find Your Flow State
+
+Stay ahead of upcoming hackathons and exclusive announcements. [Join Flow World Tour on Telegram](https://t.me/flow_world_tour).
+
+
+=== ecosystem/grants.md ===
+---
+title: Grants
+description: Discover grant opportunities and funding programs available for Flow developers
+sidebar_position: 10
+sidebar_custom_props:
+ icon: 🌱
+---
+
+# Flow Developer Grants
+
+The Flow Foundation provides grants to support developers and teams building tools and products that enhance the Flow ecosystem.
+
+## Focus Areas
+
+We are particularly interested in projects across these key areas:
+
+- **Telegram Miniapps**: Building integrations and applications for the Telegram ecosystem
+- **DeFi**: Innovative decentralized finance solutions
+- **AI Agents**: Artificial intelligence and autonomous systems
+- **Sports**: Applications and platforms in the sports and gaming sector
+
+## How to Apply
+
+1. Visit the [Flow Developer Grants Repository](https://github.com/onflow/developer-grants)
+2. Create a new issue using the "Grant Application" template
+3. Fill out all required details about your project
+
+
+=== ecosystem/faucets.md ===
+---
+sidebar_position: 9
+description: Get free Flow tokens for testing. Faucets are like taps for tokens, useful for trying Flow without buying tokens.
+sidebar_custom_props:
+ icon: 💧
+---
+
+# Faucets
+
+Network Faucets provide free Flow tokens for testing purposes, functioning like taps that dispense tokens. They are valuable tools for experimenting with Flow without the need to purchase tokens.
+
+
+
+## Flow Faucet
+
+[Flow Faucet](https://testnet-faucet.onflow.org/) is a dedicated tool that provides a seamless way to acquire small amounts of Flow tokens for testing and development purposes on the Flow blockchain's testnet environment.
+
+### Supported Networks
+
+- [Testnet](https://testnet-faucet.onflow.org/)
+
+## LearnWeb3 Flow Faucet
+
+[LearnWeb3 Flow Faucet](https://learnweb3.io/faucets/flow) is a community faucet tool that provides a seamless way to acquire small amounts of Flow tokens for testing and development purposes on the Flow blockchain's testnet environment.
+
+### Supported Networks
+
+- [Testnet](https://learnweb3.io/faucets/flow)
+
+
+
+## Using Flow Faucet
+
+### Funding Your Account
+
+If you already have a Flow account, you can fund it directly from the Faucet's landing page. Simply paste the address of the account you want to fund, complete the CAPTCHA, and click "Fund Your Account."
+
+
+
+After a few seconds, you'll see your account's FLOW balance as a confirmation. Note, the Faucet will automatically determine if the address you paste is a Flow or EVM address and will fund the account accordingly.
+
+### Creating a Flow Account
+
+#### Generate a Key Pair
+
+To create a Flow-native account, you'll need to generate a key pair. You can do this most easily [Flow CLI](../build/getting-started/flow-cli.md) with the [`keys generate` command](../tools/flow-cli/keys/generate-keys.md)
+
+```sh
+flow keys generate
+```
+
+You'll receive a private key and a public key pair with default `ECDSA_P256` signature and `SHA3_256` hash algorithms.
+
+```sh
+❯ flow keys generate
+
+🔴️ Store private key safely and don't share with anyone!
+Private Key
+Public Key
+Mnemonic
+Derivation Path m/44'/539'/0'/0/0
+Signature Algorithm ECDSA_P256
+```
+
+You can then use the public key to create a new Flow account on the Faucet. Copy the resulting public key for the next step.
+
+#### Create a Flow-Native Account
+
+From the Faucet's landing page, click on the "Create Account" button. You'll be prompted to enter your public key. Paste the public key you generated using the Flow CLI and click "Create Account."
+
+:::tip
+
+Know that there is a distinction between Flow native accounts and EVM accounts. Native accounts allow you to interact with the Cadence runtime, while EVM accounts are used for interacting with Flow's EVM. To create an EVM account, you can use EVM tooling to generate an Ethereum Owned Account (EOA) and simply fund the associated address. Alternatively, you can create an EVM account controlled by your Flow native account - known as a Cadence Owned Account (COA) - in which case you'll need a Flow native account and should continue with the steps below.
+
+For more information interacting with EVM via COAs, see the [Interacting With COAs documentation](../tutorials/cross-vm-apps/interacting-with-coa.md).
+
+:::
+
+
+
+You can then paste your public key into the input field, complete the CAPTCHA, and click "Create Account."
+
+
+
+You'll be met with a confirmation screen, showing your Flow account address and the funded balance.
+
+
+
+#### Using your Flow Account
+
+Once your account has been created, you can add the account to your `flow.json` configuration file under the `accounts` attribute, like so:
+
+```json
+{
+ "accounts": {
+ "testnet-dev-account": {
+ "address": "",
+ "key": ""
+ }
+ }
+}
+```
+
+:::warning
+
+If you plan on using your flow.json in a production environment, you'll want to look at alternative methods to manage your keys more securely, at minimum using environment variables instead of storing your account private keys in plain text. See [How to Securely Use CLI](../tools/flow-cli/flow.json/security.md) for more information on alternate key management strategies and how to configure them in your `flow.json` file.
+
+:::
+
+After adding your account to your `flow.json` file, you're ready to use your account in your project. You can now deploy contracts, run transactions, and interact with the Flow blockchain using your new account.
+
+
+=== ecosystem/developer-profile.md ===
+---
+title: Developer Profile
+sidebar_label: Developer Profile
+description: Learn about Developer Profile - Flow's upcoming developer recognition and learning platform. Create your builder profile. In the future, you'll be able to track your learning journey, showcase your projects, and connect with the Flow ecosystem.
+sidebar_position: 4
+sidebar_custom_props:
+ icon: ⭐
+keywords:
+ - Developer Profile program
+ - Flow developers
+ - builder profiles
+ - learning paths
+ - developer challenges
+ - Flow ecosystem
+ - developer recognition
+ - Flow community
+ - learning platform
+ - developer achievements
+ - Flow certification
+ - builder network
+ - developer tools
+ - Flow education
+ - developer onboarding
+---
+
+The Developer Profile is the beginning of Flow's developer recognition and learning platform where builders can create profiles, track their learning journey, complete challenges, and showcase their contributions to the Flow ecosystem.
+
+It's fully onchain!
+
+:::tip
+
+The Developer Profile is currently in alpha. Please let us know what you think!
+
+:::
+
+## What is the Developer Profile?
+
+The Developer Profile is a platform designed to help developers:
+
+- Create and manage their Flow builder profiles
+- Track their learning progress through structured paths
+- Complete challenges and earn recognition
+- Connect with other builders in the ecosystem
+- Showcase their projects and contributions
+
+Currently, the Developer Profile is in alpha. You can:
+
+- Create your profile
+- Share your GitHub handle
+- Add your deployed contract addresses
+- Complete the First Challenge
+
+## Getting Started
+
+The Developer Profile is accessed by logging in with your wallet. Click the "Connect Button" in the top right.
+
+
+
+:::tip
+
+The Developer Profile is on Flow Cadence. You'll need to use a wallet that supports Cadence transactions, such as the [Flow Wallet] or [Blocto].
+
+:::
+
+Once connected, you can see your progress by clicking `Progress` in the dropdown menu.
+
+
+
+
+
+### 1. Create Your Profile
+
+Click `Profile` in the dropdown menu.
+
+- Choose a unique handle
+- Add your Github handle
+- Add your deployed contract addresses
+- Share how you discovered Flow
+
+### 2. Complete the First Challenge
+
+**After** you've created your profile, you can complete the first challenge.
+
+Click `Progress` in the dropdown menu.
+
+Click the button at the bottom of the page.
+
+Complete the challenge!
+
+## Next Steps
+
+We'll be updating the Developer Profile with new features and challenges. Check back soon!
+
+
+
+[Flow Wallet]: https://wallet.flow.com/
+[Blocto]: https://blocto.app/
+
+
+=== ecosystem/data-indexers.md ===
+---
+title: Data Indexers
+sidebar_label: Data Indexers
+sidebar_position: 4
+---
+
+# Data Indexers
+
+When building applications that leverage Flow data, developers have multiple Data Indexers to choose from. These platforms offer flexible options, allowing you to index all data on Flow, including information from both the Cadence VM and EVM. Alternatively, if your application doesn't require Cadence, you can opt to index only EVM data. This flexibility ensures that you can tailor your data indexing strategy to fit the specific needs of your application.
+
+## EVM & Cadence
+
+### **SimpleHash**
+
+[SimpleHash](https://simplehash.com/) is a comprehensive multi-chain NFT data platform that provides developers with easy access to token data across 60+ blockchain networks. It offers a robust API for querying NFT metadata, media, collection details, sales, floor prices, listings, and bids, streamlining the process of building NFT-powered applications.
+
+**Getting Started with SimpleHash**
+
+Developers can begin using SimpleHash by [signing up for an API key](https://simplehash.com/) on their website. The platform provides comprehensive [documentation](https://docs.simplehash.com/reference/overview) to help developers integrate SimpleHash into their projects.
+
+## **EVM Only**
+
+### Moralis
+
+[Moralis](https://moralis.io/) provides a robust suite of data APIs designed to support a wide array of blockchain applications. These APIs deliver both indexed and real-time data across 16+ blockchain networks, including comprehensive details on portfolio and wallet balances, NFT data, token metrics, price feeds, candlestick charts, and net worth calculations. Moralis enhances this data with additional layers of metadata, parsed events, and address labels to provide deeper insights and context.
+
+**Getting Started with Moralis**
+
+To integrate Moralis into your project, begin by [creating an account](https://moralis.io/). Detailed API references and integration guides are available in the Moralis [documentation](https://docs.moralis.io/). For step-by-step tutorials and use cases, visit their [YouTube channel](https://www.youtube.com/c/MoralisWeb3).
+
+### **Alchemy**
+
+[Alchemy](https://www.alchemy.com/) is a powerful blockchain development platform that provides enhanced APIs and advanced analytics to streamline the process of creating and scaling Web3 applications.
+
+**Getting Started with Alchemy**
+
+To begin using Alchemy, developers can [sign up for an account](https://www.alchemy.com/) on the Alchemy website. The platform offers extensive [documentation](https://docs.alchemy.com/) including API references, tutorials, and guides to help developers integrate Alchemy into their projects.
+
+
+=== ecosystem/builder-perks.md ===
+---
+title: Builder Perks
+description: Exclusive perks and benefits for Flow builders
+sidebar_position: 8
+---
+
+import Modal from "@site/src/ui/design-system/src/lib/Components/Modal";
+import ActionCard from "@site/src/components/ActionCard";
+import React from "react";
+import { useCurrentUser } from "@site/src/hooks/use-current-user";
+import { useProgress } from "@site/src/hooks/use-progress";
+import { useProfile } from "@site/src/hooks/use-profile";
+import ProfileModal from "@site/src/components/ProfileModal";
+import ConnectButton from "@site/src/components/ConnectButton";
+import { Button } from "@site/src/ui/design-system/src/lib/Components/Button";
+
+export const BuilderPerks = () => {
+ const [activeModal, setActiveModal] = React.useState(null);
+ const [isProfileModalOpen, setIsProfileModalOpen] = React.useState(false);
+ const { user, logIn } = useCurrentUser();
+ const { profile } = useProfile(user?.addr);
+ const { getProgress } = useProgress();
+ const progress = user?.addr ? getProgress() : 0;
+ const isProfileComplete = progress === 1;
+
+ const handleCardClick = (modalId) => {
+ if (!user?.loggedIn || !isProfileComplete) {
+ setActiveModal('profile-check');
+ } else {
+ setActiveModal(modalId);
+ }
+ };
+
+ return (
+
+
+
+
handleCardClick('gas-subsidy')}
+ />
+
+ handleCardClick('alchemy')}
+ />
+
+ handleCardClick('quicknode')}
+ />
+
+ handleCardClick('thirdweb')}
+ />
+
+
+ handleCardClick('olympix')}
+ />
+
+
+
+ {/* Profile Check Modal */}
+
setActiveModal(null)}
+ title="Complete Your Profile"
+ >
+
+
+ {!user?.loggedIn
+ ? "Please connect your wallet to access Flow Builder Perks."
+ : "Complete your Flow Builder Profile to access exclusive perks."}
+
+
+ {user?.loggedIn && (
+
+
+ {Math.floor(progress * 100)}%
+
+
Profile completion status
+
+ )}
+
+ {!user?.loggedIn ? (
+
setActiveModal(null)} />
+ ) : (
+ {
+ setIsProfileModalOpen(true);
+ setActiveModal(null);
+ }}
+ >
+ Complete Profile
+
+ )}
+
+
+
+
setIsProfileModalOpen(false)}
+ />
+
+ {/* QuickNode Modal */}
+ setActiveModal(null)}
+ title="QuickNode"
+ >
+
+
+
+
+
+
Features
+
+
+
• Lightning-fast RPC endpoints
+
• Real-time WebSocket streams
+
• Historical data backfills
+
+
+
• Multi-chain support
+
• Advanced monitoring tools
+
• 24/7 developer support
+
+
+
+
+
+
How to Claim
+
+
+ 1. Visit QuickNode signup →
+
+
+
2. Enter promo code:
+
+ BUILDWITHFLOW
+ navigator.clipboard.writeText('BUILDWITHFLOW')}
+ className="text-blue-500 hover:text-blue-600 text-sm"
+ >
+ Copy
+
+
+
+
+
+
+
+
+
+ {/* Olympix Modal */}
+ setActiveModal(null)}
+ title="Olympix"
+ >
+
+
+
+
+
+
Features
+
+
+
Team Size
+
1-2 developers
+
+
+
Revenue Requirement
+
$5,000+ per year
+
+
+
+
+
+
How to Apply
+
+
+
Send email to:
+
sarah@olympix.ai
+
CC:builders@flow.com
+
+
+
Include:
+
• Subject: "Olympix Flow Perk"
+
• Your GitHub username
+
• Link to your project
+
+
+
+
+
+
+
+ {/* Gas Subsidy Modal */}
+ setActiveModal(null)}
+ title="Gas Subsidy"
+ >
+
+
+
+
+
+
Features
+
+
+
Transaction Coverage
+
Sponsor up to 10,000 user transactions
+
+
+
Usage Impact
+
Up to 4x more app engagement
+
+
+
Contract Deployment
+
Launch your contracts on Mainnet for FREE
+
+
+
+
+
+
How to Apply
+
+
+
Send email to:
+
builders@flow.com
+
+
+
Include:
+
• Subject: "Gas Subsidy Request"
+
• Your GitHub username
+
• Your deployer address
+
+
+
+
+
+
+
+ {/* Alchemy Modal */}
+ setActiveModal(null)}
+ title="Alchemy"
+ >
+
+
+
+
+
+
Features
+
+
+
• Free infrastructure credits
+
• Product discounts
+
• Technical support
+
+
+
• Partner network access
+
• Launch amplification
+
• Community perks
+
+
+
+
+
+
How to Apply
+
+
+ 1. Apply to Startup Program →
+
+
+
2. Send follow-up email:
+
To: zaib@alchemy.com
+
CC: builders@flow.com
+
Subject: "Flow Alchemy Perk"
+
Include your GitHub username and project link
+
+
+
+
+
+
+
+ {/* Thirdweb Modal */}
+ setActiveModal(null)}
+ title="Thirdweb"
+ >
+
+
+
+
+
+
Features
+
+
+
• Production-grade RPCs
+
• Custom branding options
+
• User analytics dashboard
+
+
+
• Transaction management
+
• Automatic retries
+
• Team access controls
+
+
+
+
+
+
+
+
How to Claim
+
+
+ 1. Visit Thirdweb Dashboard →
+
+
+
2. Apply coupon code:
+
+ 3WEBDEV-FLOW
+ navigator.clipboard.writeText('3WEBDEV-FLOW')}
+ className="text-blue-500 hover:text-blue-600 text-sm"
+ >
+ Copy
+
+
+
+
+ 3. Upgrade to Growth tier and deploy your Engine instance
+
+
+
+
+
+
+
+ );
+};
+
+
+
+
+=== ecosystem/bridges.md ===
+---
+sidebar_position: 6
+description: Mechanisms that connect different blockchain networks, allowing secure and decentralized transfer of assets and data across platforms.
+sidebar_custom_props:
+ icon: ⛓️
+---
+
+# Bridges
+
+Bridges are mechanisms that connect different blockchain networks, enabling secure and decentralized transfers of assets and data across various platforms.
+
+
+
+## Stargate Bridge
+
+[Stargate Bridge][1] is a cross-chain liquidity transfer protocol powered by LayerZero that enables seamless bridging of assets between Flow and major blockchain networks like Ethereum, BNB Chain, and Base. It uses LayerZero's omnichain messaging capabilities which allow Stargate to provide deep liquidity pools, low slippage, and cost-efficient transfers for stablecoins and cryptocurrencies such as USDC, USDT, USDF, and ETH.
+
+## Flow Bridge
+
+[Flow Bridge][2] is a user-friendly, decentralized bridge designed to facilitate secure transfers of stablecoins like USDC, USDT, and USDF to and from Flow blockchain. Powered by Superbridge, it leverages native bridge contracts for official Superchain rollups, ensuring users receive the canonical asset on Flow with minimal trust assumptions. Flow Bridge supports transfers from 24+ chains, with ultra-low transaction fees and fast settlement times.
+
+## LayerZero
+
+[LayerZero][3] is a decentralized omnichain interoperability protocol that enables direct cross-chain messaging and asset transfers. It uses a unique Ultra Light Node (ULN) architecture combined with decentralized verifiers to ensure secure message delivery across chains. LayerZero supports multiple EVM-compatible chains and provides developers with tools to build cross-chain applications through its EndpointV2 contracts.
+
+## Hyperlane
+
+[Hyperlane][4] is a modular interoperability framework that enables secure cross-chain communication. It allows developers to build applications that can seamlessly interact across different blockchain networks. Hyperlane's architecture emphasizes security and flexibility, providing customizable security models and permissionless interoperability between any blockchain networks.
+
+## Celer cBridge
+
+[Celer cBridge][5] is a decentralized and non-custodial asset bridge that supports more than 150 tokens across over 40 blockchains and layer-2 rollups. It is built on top of the [Celer][6] Inter-chain Message Framework. cBridge has facilitated over $13 billion in cross-chain asset transfer volume across 40+ blockchains for more than 350,000 unique users. It is rapidly growing and expanding to support more blockchains and layer-2 solutions.
+
+## Axelar
+
+[Axelar][7] is a decentralized cross-chain network connecting over 55 blockchains, facilitating asset transfers and smart contract programmability. It features a proof-of-stake consensus for security and supports cross-chain applications through General Message Passing (GMP). Integrations with platforms like [Squid][8] enable easy token swaps across networks like Ethereum and Polygon.
+
+## DeBridge
+
+[DeBridge][9] is a decentralized cross-chain network supporting hundreds of tokens over 75 blockchains. DeBridge runs on its generic messaging protocol and operates cross-chain validator infrastructure to achieve a high level cross-chain interoperability for quick, low-cost bridging. DeBridge's architecture emphasizes security and fault tolerance with robust handling of forks or blockchain outages to mitigate bridging issues.
+
+## Relay
+[Relay][10] is an intent-based bridge enabling high-speed bridging and connecting over 30 blockchains. Unlike consensus validator based decentralized bridges, Relay's permissioned relayer model stores outbound tokens on the origin chain and issues tokens on the destination chain allowing for low-cost, fast bridging of assets.
+
+
+
+[1]: https://stargate.finance/bridge
+[2]: https://bridge.flow.com/
+[3]: https://docs.layerzero.network/
+[4]: https://www.usenexus.org/
+[5]: https://cbridge.celer.network/
+[6]: https://celer.network/
+[7]: https://www.axelar.network/
+[8]: https://www.squidrouter.com/
+[9]: https://app.debridge.finance/
+[10]: https://relay.link/bridge
+
+=== ecosystem/block-explorers.md ===
+---
+sidebar_position: 3
+description: |
+ User-friendly online tools that provide visual representations of blockchain data, facilitating easy navigation through transactions, blocks, addresses, and smart contracts while ensuring real-time insights and transparency.
+sidebar_custom_props:
+ icon: 🔍
+---
+
+# Flow Block Explorers
+
+Block explorers are user-friendly online tools that visually present blockchain data, allowing users to easily navigate transactions, blocks, addresses, and smart contracts while providing real-time insights and transparency.
+
+
+
+## Flowscan
+
+[Flowscan](https://flowscan.io/) provides various tools to explore the blockchain, including:
+
+- Blocks
+- Transactions
+- Contracts
+- Network activity (transaction count)
+- Transaction cost (gas fee)
+- Validators information
+
+### Supported networks:
+
+- [Mainnet](https://flowscan.io/)
+- [Testnet](https://testnet.flowscan.io/)
+
+## Flowscan [EVM]
+
+[Flowscan](https://evm-testnet.flowscan.io/) is based off of the popular Blockscout and provides a user-friendly interface to search for specific EVM transactions, blocks, monitor network health, and track the status of various smart contracts and tokens on Flow EVM. Features include:
+
+- Real-Time Data: View live transaction data, blocks, and account activities.
+- Search Functionality: Search for specific transactions, blocks, and accounts.
+- Smart Contract Analysis: Examine smart contract statuses and interactions.
+- Token Tracking: Monitor the creation and transfer of various tokens on the Flow network.
+
+### Supported networks:
+
+- [Testnet](https://evm-testnet.flowscan.io/)
+- [Mainnet](https://evm.flowscan.io/)
+
+## Flow View
+
+[Flow View](https://www.flowview.app/) offers comprehensive tools to view accounts' information, including:
+
+- Address, balance, and storage
+- Public keys and their weights
+- Staking information
+- Tokens, collections, and listings
+- Deployed smart contracts
+
+### Supported networks:
+
+- [Mainnet](https://www.flowview.app/)
+- [Testnet](https://testnet.flowview.app/)
+- [Emulator (local)](https://emulator.flowview.app/)
+
+## Contract Browser
+
+[Contract Browser](https://contractbrowser.com/) provides tools for viewing deployed smart contracts, their dependencies, and dependents. Features include:
+
+- Search, view, and verify smart contract source code
+- Detailed smart contract information
+
+[Testnet Contract Browser](https://testnet.contractbrowser.com/) is also available for `Testnet Flow`.
+
+
+
+
+=== ecosystem/auditors.md ===
+---
+sidebar_position: 12
+description: |
+ Third-party auditors for Cadence contract auditing
+sidebar_custom_props:
+ icon: 🔎
+---
+
+# Auditors
+
+The following companies provide independent contract auditing services of Cadence smart contracts for the Flow ecosystem.
+
+
+
+## Nagra (Kudelski)
+
+[Nagra](https://www.nagra.com/) a multinational provider of security services including blockchain security and smart contract auditing of Cadence.
+
+## NCC Group
+
+[NCC Group](https://www.nccgroup.com/us/) a global provider of security services including blockchain security and smart contract auditing of Cadence.
+
+## QuantStamp Inc.
+
+[Quantstamp Inc.](https://quantstamp.com/) specializing in blockchain security and smart contract auditing including Cadence.
+
+## Halborn Inc.
+
+[Halborn Inc.](https://www.halborn.com/) specializing in blockchain security and smart contract auditing including Cadence.
+
+## Oak Security
+
+[Oak Security](https://www.oaksecurity.io/) a specialist in smart contract auditing security including Cadence.
+
+## Emerald City Academy
+
+[Emerald City Academy - Shield](https://docs.ecdao.org/auditing/shield) a Cadence-specialized, community-driven auditing service also offering development support and review for Cadence smart contracts.
+
+
+
+
+=== ecosystem/defi-liquidity/index.md ===
+---
+title: DeFi & Liquidity
+description: Mechanisms that connect different blockchain networks, allowing secure and decentralized transfer of assets and data across platforms.
+keywords:
+ - DeFi
+ - liquidity
+ - decentralized finance
+ - blockchain networks
+ - cross-chain transfer
+ - decentralized transfer
+ - Flow blockchain
+ - DEX
+ - lending platforms
+ - stablecoin protocols
+ - liquidity solutions
+sidebar_position: 5
+sidebar_custom_props:
+ icon: 💧
+---
+
+# DeFi & Liquidity on Flow
+
+**Fast, scalable, and capital-efficient DeFi.** Flow delivers a seamless DeFi experience without congestion, unlocking new possibilities for developers and users alike.
+
+Flow is designed for **next-generation DeFi**, enabling developers to build high-performance **DEXs, lending platforms, stablecoin protocols, and liquidity solutions**—all without the friction of high fees or complex scaling layers.
+
+## Why DeFi on Flow?
+
+**Ultra-low fees** – Cost-efficient swaps, lending, and staking
+**Fast finality** – Transactions are confirmed quickly with guaranteed execution
+**Capital-efficient execution** – No MEV, no congestion, seamless scaling
+**Composable DeFi** – Built-in interoperability between assets
+
+**Start integrating DeFi on Flow today.**
+
+**[DeFi Contracts](./defi-contracts.md)**
+**[Cross-chain swaps](./cross-chain-swaps.md)**
+**[Read the FAQ](./faq.md)**
+
+Explore the [FlowVerse DeFi ecosystem](https://www.flowverse.co/?categories=defi) page for more information.
+
+
+## Securing DeFi on Flow EVM
+
+Flow EVM supports secure multi-sig from Safe.Global (formerly Gnosis Safe) or Fireblocks. Both offer robust solutions for
+developers seeking to enhance the security and management of tokenized assets with a focus on institutional-grade practices and scalability.
+
+* [Safe.Global](https://safe.flow.com/)
+* [Fireblocks](https://www.fireblocks.com/)
+
+---
+
+
+=== ecosystem/defi-liquidity/faq.md ===
+---
+id: faq
+title: Stablecoins & Bridges on Flow FAQ
+description: Frequently asked questions about stablecoins, liquidity, and bridging on the Flow blockchain.
+keywords:
+ - stablecoins
+ - bridges
+ - Flow blockchain
+ - USDC
+ - USDT
+ - USDF
+ - decentralized exchanges
+ - DEX
+ - yield farming
+ - liquidity
+sidebar_position: 3
+sidebar_label: Stablecoins & Bridges FAQ
+---
+
+import Details from '@theme/Details';
+
+# DeFi & Liquidity FAQ
+
+Below are common questions regarding stablecoins, liquidity, and bridging on Flow. Click on each question to expand and view the answer.
+
+## Bridging and Gas
+
+
+No, Flow uses $FLOW as the gas token. [WETH](./defi-contracts#stablecoins--wrapped-assets) is supported on Flow EVM when [bridging](../bridges.md) from another chain. $WFLOW is used as an ERC20 in DeFi apps and not used for gas.
+
+
+
+When using Flow EVM for the first time, your EOA will automatically be credited 0.05 FLOW to cover gas costs when bridging into Flow.
+If further top-ups are required you can use [Gas.zip](https://www.gas.zip/). See [Fees](../../evm/fees) for information on gas pricing.
+
+Flow Wallet users do not pay for gas since the wallet subsidizes all transaction fees.
+
+
+## Stablecoins on Flow
+
+
+USDC (USD Coin) - Issued by Circle
+
+USDT (Tether USD) - Issued by Tether
+
+USDF (USD Flow) - Backed by PYUSD (PayPal USD) issued by PayPal
+
+
+
+
+
+You can find all the contract addresses for the stablecoins and bridges on Flow here:
+[DeFi Contracts on Flow][0]
+
+
+
+Stablecoins can be traded on major Flow-based decentralized exchanges (DEXs) like:
+
+- KittyPunch, PunchSwap - [https://swap.kittypunch.xyz/][1]
+- IncrementFi, IncrementSwap - [https://app.increment.fi/swap][2]
+
+
+
+You can earn yield through:
+
+- Lending Platforms - Supply stablecoins on [IncrementFi][3], [Sturdy Finance][19] & [MoreMarkets][4] to earn interest.
+- Liquidity Pools - Provide liquidity on [IncrementFi][5] or [KittyPunch][6] to earn trading fees and farm LP tokens.
+- Yield Aggregators (Coming soon) - Use [KittyPunch][7] to automate stablecoin yield strategies.
+
+
+
+Stablecoins on Flow are designed to be secure and efficient but as with any blockchain asset, there are risks to be aware of:
+
+- Depegging - While rare, some stablecoins have lost their peg in the past due to liquidity issues or market crashes. Flow stablecoins like USDC and USDF are backed by trusted issuers to maintain stability.
+- Smart Contract Risks - Bugs or exploits in DeFi platforms can lead to losses.
+- Centralization Risks - USDC and USDT are controlled by centralized issuers who can freeze assets.
+- Bridging Risks - Flow stablecoins (USDC, USDT, USDF) use LayerZero for bridging, a secure and widely adopted cross-chain solution. While all bridges carry some risk, LayerZero is built with advanced security measures to reduce vulnerabilities.
+
+
+
+You can bridge USDC, USDT, and USDF via [https://bridge.flow.com/][8] or [https://stargate.finance/bridge][9]
+
+### Step-by-step example USDC to Flow
+
+1. Go to any of the bridges (e.g. [https://stargate.finance/bridge][9])
+2. Connect your wallet that holds USDC
+3. Select the source chain (e.g. Ethereum, BNB Chain, Base)
+4. Choose Flow as the destination chain
+5. Enter the amount of USDC you want to bridge
+6. Approve and confirm the transaction
+7. Wait for the transfer to complete - It usually takes a few minutes
+
+
+
+Flow’s transaction fees are extremely low (typically less than $0.000179 per transaction), making stablecoin transfers and trading much cheaper than on any other chain.
+
+In many cases, Flow Wallet or Flow-based apps sponsor the gas fees, meaning users can transact stablecoins without paying any gas. This makes Flow an ideal chain for cost-efficient DeFi transactions.
+
+
+
+
+Stablecoins can be used for payments on Flow with services like:
+
+[Beezie][10], [Flowty][11], [Flowverse][12] and many other platforms.
+
+
+
+
+- DeFi integrations with RWAs (Real World Assets).
+- Stay tuned on [Flow X account][13] or via the community [Flowverse][14]
+
+
+## Stargate and LayerZero on Flow
+
+
+LayerZero is an omnichain interoperability protocol that enables seamless cross-chain communication between different blockchains. It allows assets, messages, and data to move securely between chains without relying on traditional bridges.
+
+
+
+Stargate is a liquidity transfer protocol built on LayerZero that allows users to bridge assets across multiple blockchains with minimal slippage and deep liquidity.
+
+
+
+With Stargate now supporting Flow, users can bridge assets to and from Flow blockchain via [Stargate Finance][9]. This enables Flow to interact with other major chains like Ethereum, Base, Arbitrum One, and BNB Chain, unlocking global onchain liquidity for Flow-based apps and DeFi protocols.
+
+
+
+Currently, Stargate supports bridging USDC, USDT, and ETH between Flow and other chains. Additional assets may be added in the future.
+
+
+
+- Total fees: You pay gas fees + relayer fees, typically less than $1.5 per bridge transaction.
+- Gas fees vary depending on network congestion and gas prices.
+- Bridging from Ethereum costs around 0.0003868 ETH (~$1.04) in gas fees, plus LayerZero relayer fees of 0.00003536 ETH ($0.095).
+- Flow’s transaction fees are extremely low (typically less than $0.000179 per transaction), making stablecoin transfers and trading significantly cheaper than other chains.
+- In many cases, Flow Wallet or Flow-based apps sponsor gas fees, allowing users to bridge and transact stablecoins with zero cost on Flow.
+
+
+
+- Most transactions settle within a few minutes (~3 mins).
+- Congestion on the source chain can cause delays.
+
+
+
+Stargate is built on LayerZero, a well-audited and widely used interoperability protocol.
+
+- Secure & Trusted – Used by top DeFi ecosystems with rigorous security audits.
+- Efficient & Cost-Effective – Fast transactions with low fees, especially on Flow.
+- Reliable Bridged Assets – USDC, USDT, and ETH bridged via Stargate are fully supported in Flow’s DeFi ecosystem.
+
+Tip: Always verify official links to ensure a safe bridging experience.
+
+
+
+
+- Direct USDC transfers between Flow and other blockchains.
+- Unlocks cross-chain DeFi use cases (e.g., lending, trading, staking).
+- Low fees and high-speed transactions on Flow.
+
+
+
+Currently, Stargate only supports stablecoins like USDC and USDT, but NFT and asset bridging may be possible in the future via LayerZero-based messaging.
+
+
+
+- **DeFi**: Seamless liquidity transfer between Flow and other ecosystems.
+- **Gaming**: Cross-chain in-game assets & currency settlements.
+- **Payments**: Fast and low-cost USDC/USDT/USDF transactions.
+- **NFTs**: Future potential for cross-chain NFT bridging.
+
+
+
+You can use any EVM wallet such as Metamask, Coinbase Wallet, and Flow Wallet.
+
+
+
+You can see a full list of stablecoins here:
+[DeFi Contracts on Flow][0]
+
+Trading pools for USDF and stgUSDC (USDC via Stargate) are already live and available for immediate use on Flow EVM and can be seamlessly transferred to any Flow Cadence address.
+
+
+
+
+Cadence applications can use USDC.e as the default, but they now also have the option to support USDF or stgUSDC based on their needs.
+
+If you have questions you can join [Flow Discord][15] to get free technical support.
+
+
+
+## Support and Additional Resources
+
+
+- Use [Stargate’s Explorer][9] to track your transfer.
+- You can also check Flow transactions on [evm.flowscan.io][16]
+- You can also visit [https://bridge.flow.com/][8] and connect your wallet to view activity.
+
+
+
+- **Stargate Discord**: [https://discord.com/invite/9sFqx9U][17]
+- **Flow Discord**: [https://discord.gg/flow][15]
+
+
+
+- **Flow Twitter/X:** [https://x.com/flow_blockchain][13]
+- **Flow Discord**: [https://discord.gg/flow][15]
+
+
+[0]: ./defi-contracts.md
+[1]: https://swap.kittypunch.xyz/
+[2]: https://app.increment.fi/swap?in=A.1654653399040a61.FlowToken&out=
+[3]: https://app.increment.fi/dashboard
+[4]: https://app.more.markets/
+[5]: https://app.increment.fi/liquidity
+[6]: https://www.kittypunch.xyz/
+[7]: https://app.kittypunch.xyz/
+[8]: https://bridge.flow.com/
+[9]: https://stargate.finance/bridge
+[10]: https://beezie.io/
+[11]: https://www.flowty.io/
+[12]: https://nft.flowverse.co/
+[13]: https://x.com/flow_blockchain
+[14]: https://x.com/flowverse_
+[15]: https://discord.gg/flow
+[16]: https://evm.flowscan.io
+[17]: https://discord.com/invite/9sFqx9U
+[19]: https://v2.sturdy.finance/overview
+[20]: https://www.flowverse.co/?categories=defi
+
+=== ecosystem/defi-liquidity/defi-contracts.md ===
+---
+id: defi-contracts
+title: DeFi Contracts on Flow
+description: A reference table of frequently used DeFi contracts on Flow, including their addresses for both Flow EVM and Flow Cadence.
+keywords:
+ - DeFi contracts
+ - Flow blockchain
+ - Flow EVM
+ - Flow Cadence
+ - stablecoins
+ - wrapped assets
+ - AMMs
+ - DEXs
+ - KittyPunch
+ - PunchSwap
+sidebar_position: 1
+sidebar_label: DeFi Contracts
+---
+
+import StablecoinsWrappedAssetsTable from '@site/src/components/defi-contracts/StablecoinsWrappedAssetsTable';
+
+Flow is a Layer 1 blockchain that supports EVM equivalency, offering two environments Flow EVM and Flow Cadence. Fungible and non-fungible tokens can seamlessly transfer between these environments via the native VM token bridge. As a result, many tokens have both a Flow EVM mainnet contract address and a Flow Cadence mainnet contract address, allowing developers to choose their preferred environment.
+
+Below is a list of commonly used DeFi contracts on Flow:
+
+## Stablecoins & Wrapped Assets
+
+#### Flow EVM Mainnet
+
+
+
+#### Flow Cadence Mainnet
+
+
+
+## AMMs & DEXs
+
+#### Flow EVM Mainnet
+
+| Contract Name | Flow EVM Mainnet Address |
+| -------------------------------------------- | -------------------------------------------- |
+| [StableKittyFactoryNG.sol (KittyPunch)][1] | `0x4412140D52C1F5834469a061927811Abb6026dB7` |
+| [TwoKittyFactory.sol (KittyPunch)][2] | `0xf0E48dC92f66E246244dd9F33b02f57b0E69fBa9` |
+| [TriKittyFactory.sol (KittyPunch)][3] | `0xebd098c60b1089f362AC9cfAd9134CBD29408226` |
+| [KittyRouterNgPoolsOnly.sol (KittyPunch)][4] | `0x87048a97526c4B66b71004927D24F61DEFcD6375` |
+| [PunchSwapV2Router02.sol (KittyPunch)][5] | `0xf45AFe28fd5519d5f8C1d4787a4D5f724C0eFa4d` |
+| [PunchSwapV2Factory.sol (KittyPunch)][6] | `0x29372c22459a4e373851798bFd6808e71EA34A71` |
+| [TrenchesTokensBuyer.sol (KittyPunch)][7] | `0x6D0e081Acc28eA9ee6b7fD293eC03F97147b026d` |
+
+#### Flow Cadence Mainnet
+
+| Contract Name | Flow Cadence Mainnet Address |
+| ----------------------------------- | ---------------------------- |
+| [SwapFactory.cdc (IncrementFi)][22] | `0xb063c16cac85dbd1` |
+| [SwapPair (IncrementFi)][23] | `0xecbda466e7f191c7` |
+| [SwapError (IncrementFi)][24] | `0xb78ef7afa52ff906` |
+| [SwapInterfaces (IncrementFi)][25] | `0xb78ef7afa52ff906` |
+| [SwapConfig (IncrementFi)][26] | `0xb78ef7afa52ff906` |
+| [SwapRouter (IncrementFi)][27] | `0xa6850776a94e6551` |
+
+## Bridges & Cross-Chain Messaging
+
+| Bridge / Protocol | Reference Docs |
+|----------------------------------------------|--------------------------|
+| Stargate Bridge ([stargate.finance][8]) | [Mainnet Contracts][9] |
+| Hyperlane Bridge ([trump.hyperlane.xyz][10]) | [Mainnet Contracts][11] |
+| Flow Bridge ([bridge.flow.com][12]) | [Superbridge Docs][13] |
+| Celer cBridge ([cbridge.celer.network][14]) | [Celer cBridge Docs][15] |
+| DeBridge ([app.debridge.finance][34]) | [DeBridge Contracts][35] |
+| Relay ([relay.link][36]) | [Relay Contracts][37] |
+| LayerZero | [Mainnet Contracts][16] |
+| Axelar | [Axelar Docs][17] |
+
+## Oracles
+
+#### Flow EVM Mainnet
+
+| Contract Name | Flow EVM Mainnet Address |
+|--------------------------------| -------------------------------------------- |
+| [ERC1967Proxy.sol (Pyth)][18] | `0x2880aB155794e7179c9eE2e38200202908C17B43` |
+| [ERC1967Proxy.sol (Stork)][28] | `0xacC0a0cF13571d30B4b8637996F5D6D774d4fd62` |
+
+
+#### Flow Cadence Testnet
+
+| Contract Name | Flow Cadence Testnet Address |
+|-------------------------------------------|------------------------------|
+| [PublicPriceOracle.cdc (IncrementFi)][31] | `0x8232ce4a3aff4e94` |
+| [BandOracle.cdc (Band)][32] | `0x2c71de7af78d1adf` |
+
+#### Flow Cadence Mainnet
+
+| Contract Name | Flow Cadence Mainnet Address |
+|-------------------------------------------| ---------------------------- |
+| [PublicPriceOracle.cdc (IncrementFi)][19] | `0xec67451f8a58216a` |
+| [BandOracle.cdc (Band) Protocol][33] | `0x6801a6222ebf784a` |
+
+## Ethereum Attestation Service
+
+More information can be found on the Credora docs site for [EAS on Flow](https://credora.gitbook.io/eas-for-flow).
+
+Testnet EAS Explorer: [https://flow-testnet.easscan.credora.io] (https://flow-testnet.easscan.credora.io)
+
+| Contract Name | Flow EVM Testnet Address |
+|---------------------------------------------------------|----------------------------------------------|
+| [SchemaRegistry.sol (Ethereum Attestation Service)][29] | `0x97900F59828Da4187607Cb8F84f49e3944199d18` |
+| [EAS.sol (Ethereum Attestation Service)][30] | `0xBCF2dA8f82fb032A2474c92Ec5b70C95A83fc0cc` |
+
+Mainnet EAS Explorer: [https://flow.easscan.credora.io] (https://flow.easscan.credora.io)
+
+| Contract Name | Flow EVM Mainnet Address |
+| ------------------------------------------------------- | -------------------------------------------- |
+| [SchemaRegistry.sol (Ethereum Attestation Service)][20] | `0xB0cF748a05AEA8D59e15834446CFC95bcFF510F0` |
+| [EAS.sol (Ethereum Attestation Service)][21] | `0xc6376222F6E009A705a34dbF1dF72fEf8efB3964` |
+
+
+[1]: https://evm.flowscan.io/address/0x4412140D52C1F5834469a061927811Abb6026dB7?tab=contract
+[2]: https://evm.flowscan.io/address/0xf0E48dC92f66E246244dd9F33b02f57b0E69fBa9?tab=contract
+[3]: https://evm.flowscan.io/address/0xebd098c60b1089f362AC9cfAd9134CBD29408226?tab=contract
+[4]: https://evm.flowscan.io/address/0x87048a97526c4B66b71004927D24F61DEFcD6375?tab=contract
+[5]: https://evm.flowscan.io/address/0xf45AFe28fd5519d5f8C1d4787a4D5f724C0eFa4d?tab=contract
+[6]: https://evm.flowscan.io/address/0x29372c22459a4e373851798bFd6808e71EA34A71?tab=contract
+[7]: https://evm.flowscan.io/address/0x6D0e081Acc28eA9ee6b7fD293eC03F97147b026d?tab=contract
+[8]: https://stargate.finance/bridge?srcChain=ethereum&srcToken=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48&dstChain=flow&dstToken=0xF1815bd50389c46847f0Bda824eC8da914045D14
+[9]: https://stargateprotocol.gitbook.io/stargate/v2-developer-docs/technical-reference/mainnet-contracts#flow
+[10]: https://trump.hyperlane.xyz/
+[11]: https://docs.hyperlane.xyz/docs/reference/addresses/mailbox-addresses
+[12]: https://bridge.flow.com/
+[13]: https://docs.superbridge.app/
+[14]: https://cbridge.celer.network/1/747/USDC-intermediary
+[15]: https://cbridge-docs.celer.network/tutorial/flow-cadence-bridging-guide
+[16]: https://docs.layerzero.network/v1/developers/evm/technical-reference/deployed-contracts?chains=flow
+[17]: https://docs.axelar.dev/validator/external-chains/flow/
+[18]: https://evm.flowscan.io/address/0x2880aB155794e7179c9eE2e38200202908C17B43?tab=contract
+[19]: https://contractbrowser.com/A.ec67451f8a58216a.PublicPriceOracle
+[20]: https://evm.flowscan.io/address/0xB0cF748a05AEA8D59e15834446CFC95bcFF510F0?tab=contract
+[21]: https://evm.flowscan.io/address/0xc6376222F6E009A705a34dbF1dF72fEf8efB3964?tab=contract
+[22]: https://contractbrowser.com/A.b063c16cac85dbd1.SwapFactory
+[23]: https://contractbrowser.com/A.ecbda466e7f191c7.SwapPair
+[24]: https://contractbrowser.com/A.b78ef7afa52ff906.SwapError
+[25]: https://contractbrowser.com/A.b78ef7afa52ff906.SwapInterfaces
+[26]: https://contractbrowser.com/A.b78ef7afa52ff906.SwapConfig
+[27]: https://contractbrowser.com/A.a6850776a94e6551.SwapRouter
+[28]: https://evm.flowscan.io/address/0xacC0a0cF13571d30B4b8637996F5D6D774d4fd62?tab=contract
+[29]: https://evm-testnet.flowscan.io/address/0x97900F59828Da4187607Cb8F84f49e3944199d18?tab=contract
+[30]: https://evm-testnet.flowscan.io/address/0xBCF2dA8f82fb032A2474c92Ec5b70C95A83fc0cc?tab=contract
+[31]: https://contractbrowser.com/A.8232ce4a3aff4e94.PublicPriceOracle
+[32]: https://contractbrowser.com/A.2c71de7af78d1adf.BandOracle
+[33]: https://contractbrowser.com/A.6801a6222ebf784a.BandOracle
+[34]: https://app.debridge.finance/
+[35]: https://docs.debridge.finance/dln-the-debridge-liquidity-network-protocol/deployed-contracts
+[36]: https://relay.link/bridge
+[37]: https://docs.relay.link/resources/contract-addresses
+
+
+=== ecosystem/defi-liquidity/cross-chain-swaps.md ===
+---
+id: cross-chain-swaps
+title: Cross-chain swaps on Flow EVM
+description: An overview of cross-chain options on Flow EVM
+keywords:
+ - cross-chain token swap
+ - cross-chain bridge
+ - intent based bridge
+ - liquidity based bridge
+ - bridges
+ - Flow blockchain
+ - Flow EVM
+ - EVM
+ - Relay.link
+ - DeBridge
+ - Stargate
+ - LayerZero
+ - Celer
+sidebar_position: 2
+sidebar_label: Cross-chain swaps on Flow EVM
+---
+
+import Details from '@theme/Details';
+
+The following bridges offer cross-chain swaps (token bridging including swap) to or from Flow EVM.
+
+## Liquidity Pool Based Cross-chain Swaps
+
+### Stargate
+
+[Stargate](https://stargate.finance) employs unified liquidity pools shared across multiple chains to enable native asset transfers and cross-chain swaps
+without wrapped tokens. It is built on LayerZero's cross-chain messaging protocol.
+
+### Celer
+
+[Celer](https://cbridge.celer.network) is a hybrid liquidity network bridge that combines multiple bridging models and is based on the Celer
+Inter-Chain Messaging Framework.
+
+## Intent Based Cross-chain Swaps
+
+Intent based bridges do not depend on pre-funded liquidity pools which can improve user experience, transaction speed and capital efficiency.
+
+### Relay
+
+[Relay.link](https://relay.link/bridge/base) allows users to specify desired cross-chain swap outcomes for orders.
+
+### DeBridge
+
+[DeBridge](https://app.debridge.finance/) achieves efficient cross-chain swaps with minimal slippage in a decentralized environment
+through a peer-to-peer transaction mechanism.
+
+
+
+
+=== ecosystem/defi-liquidity/add-token-to-metamask.md ===
+---
+title: How To Add Token To MetaMask
+description: How to import a Flow token in MetaMask
+sidebar_label: Add Token To MetaMask
+sidebar_position: 3
+keywords:
+ - add token to MetaMask
+ - MetaMask Flow EVM
+ - Flow EVM token
+ - import token MetaMask
+ - add custom token MetaMask
+ - Flow token contract address
+ - Flow EVM DeFi
+ - MetaMask Flow EVM network
+ - how to add token MetaMask
+ - Flow EVM block explorer
+ - Flow EVM Dexscreener
+ - Gecko Terminal Flow EVM
+ - Dexscreener Flow EVM
+ - evm.flowscan.io tokens
+ - wrapped Flow MetaMask
+ - Flow EVM liquidity
+ - Flow EVM DeFi tokens
+ - import Flow token
+ - Flow blockchain MetaMask
+---
+
+import MetaMaskImage from './add_custom_token_metamask.gif';
+import AddWrappedFlow from './add_wrapped_flow_to_metamask_2.png';
+
+:::info
+
+Want to add a token to MetaMask on Flow EVM?
+
+You can find a list of tokens on Flow at [evm.flowscan.io/tokens][1] or check the most popular DeFi token contract addresses [here][2]
+
+:::
+
+## Objectives
+
+After completing this guide, you'll be able to:
+
+- Add ERC20 tokens to MetaMask via [Flowscan][5].
+- Manually add a custom token to MetaMask using a contract address.
+- Locate Flow EVM token contract addresses on various platforms.
+
+## Add a Token to MetaMask via Flowscan
+
+1. Visit [https://evm.flowscan.io/tokens][1] to find the token you want to add to MetaMask.
+
+2. Hover over the token you want to import, and a MetaMask icon will appear. Click on it to add the token.
+
+:::note
+
+If you haven't yet added the Flow EVM network to your MetaMask, you will receive a prompt to add the network before adding the token.
+
+:::
+
+
+
+
+
+## Add a Custom Token in MetaMask Wallet
+
+If you have a token contract address, you can manually add it to MetaMask.
+
+### Steps to Add a Custom Token
+
+1. Open your MetaMask and go to the **Tokens** tab.
+
+2. Scroll down and click on **Import tokens**.
+
+3. Enter the token contract address.
+
+4. Click **Next**, then **Import** to add the token.
+
+
+
+## How to Find The Token Contract Address
+
+You can find token contract addresses on:
+
+- [Flowscan Token List][1]
+- The [DeFi Contracts][2] page
+- [Dexscreener Flow EVM][3]
+- [Gecko Terminal Flow EVM][4]
+
+If you're unsure, check the Flow EVM block explorer at [evm.flowscan.io][5]
+
+[1]: https://evm.flowscan.io/tokens
+[2]: /docs/ecosystem/defi-liquidity/defi-contracts.md
+[3]: https://dexscreener.com/flowevm
+[4]: https://www.geckoterminal.com/flow-evm/pools
+[5]: https://evm.flowscan.io
+
+
+=== build/flow.md ===
+---
+title: Why Flow
+sidebar_label: Why Flow
+sidebar_position: 1
+description: Learn why Flow blockchain is uniquely designed for consumer-scale decentralized applications. Understand Flow's multi-role architecture, native account abstraction, and EVM equivalence.
+keywords:
+ - Flow blockchain
+ - blockchain scaling
+ - multi-role architecture
+ - Cadence language
+ - EVM equivalence
+ - account abstraction
+ - blockchain security
+ - Flow features
+ - blockchain trilemma
+ - Flow EVM
+ - smart contracts
+ - Flow token
+ - blockchain architecture
+ - decentralization
+ - consumer apps
+ - MEV
+ - miner-extractable value
+ - maximum extractable value
+---
+
+
+# Why Flow
+
+
+Flow was built by consumer-facing, onchain app developers to solve the problem of building consumer-facing, onchain apps. Dieter Shirley, Chief Architect of Flow and co-author of the [ERC-721 NFT standard] calls it:
+
+>**A computer that anyone can use, everyone can trust, and no one can shut down.**
+
+Much of the protocol design is based on lessons learned from building web3 applications while working at [Dapper Labs], particularly [CryptoKitties] - the first onchain game to reach [widespread popularity]. The game went viral, then [struggled under its own success] when it caused so much traffic that Ethereum network itself was overwhelmed by the load.
+
+The design of Flow was guided by the need to alleviate this burden while creating the best experience possible for both developers and users. The blockchain network of the future must be able to handle millions of users while upholding the key pillars of decentralization:
+
+1. Verifiability
+1. Predictability/Reliability
+1. Equitable Access for All
+1. Permissionless Composability
+1. Interoperability
+1. Security
+
+Flow solves the [blockchain trilemma] and represents the next generation of blockchain technology. It's built to enable seamless consumer-scale apps without compromising decentralization or user experience and is the chosen blockchain network for [NBA Top Shot], [NFL All Day], [Mattel Creations], and [Disney Pinnacle].
+
+## What Makes Flow Unique
+
+Flow is a fast, decentralized, and developer-friendly blockchain designed to be the foundation for a new generation of games, apps, and the [digital assets] that power them. It is based on a unique [multi-role architecture], and designed to [scale without sharding], allowing for massive improvements in speed and throughput while preserving a developer-friendly, ACID-compliant environment. It natively allows development of smart contracts in the powerful [Cadence] language, and also supports full [Ethereum Virtual Machine (EVM)] equivalence with contracts written in Solidity.
+
+### Flow Blockchain
+
+- **Multi-role architecture:** The [multi-role architecture] of Flow allows the network to [scale without sharding] to serve billions of users without reducing the decentralization of consensus and verification.
+- **True Fast Finality**: For most other networks, it takes minutes, [a day], or even [a week] to reach hard finality - the point in which a transaction cannot be reversed. On Flow, the median time for finality is [under 10 seconds], without compromising security.
+- **Native VRF**: Flow provides [onchain randomness] at the protocol level. Instead of implementing a complex setup and [paying $10+ USD per number], simply call the built-in function.
+- **MEV Resistance**: Flow is designed to [ensure equitable access] by resisting MEV. Maximum Extractable Value, also know as Miner-Extractable Value (MEV), is a practice common in other blockchains in which the builder of a block can profit at your expense by manipulating where and how your transaction is included.
+- **Consumer Onboarding:** Flow was designed for mainstream consumers, with payment onramps catalyzing a safe and low-friction path from fiat to crypto.
+- **EVM Equivalence**: The [Cadence] Virtual Machine (VM) is powerful enough to allow other VMs to run inside of it, almost like a Docker Container. The first one integrated in this way is [EVM] and the EVM RPC API.
+- **Efficient Gas Costs**: The Flow blockchain is extremely efficient, allowing apps to do more computation at lower costs.
+
+### Flow Cadence
+
+- **Native Account Abstraction**: Flow has protocol-native [account abstraction]. All accounts are smart accounts, supporting scripting, multiple keys, multi-signature transactions, and walletless onboarding with social logins.
+- **Gasless Transactions**: Flow has multiple [signing roles] for each transaction. Most notably, the payer can be set independently of the authorizer. In other words, having one account sign a transaction and another pay for that transaction is a built-in feature.
+- **Security:** Smart contracts on Flow are natively written in [Cadence], an easier, safer, and more secure programming language for crypto assets and apps. It's the first high-level, [resource-oriented] programming language.
+- **Developer Ergonomics:** The Flow network is designed to maximize developer productivity. Examples range from upgradeable smart contracts to built-in logging support to the Flow Emulator.
+
+### Flow EVM
+
+- **Speed, Cost, and Compatibility**: Flow EVM can already run all of your audited Solidity contracts at an average of less than 1 cent per transaction ([usually way less!]). Unlike L2 solutions, Flow EVM reaches true finality in seconds - not in [a week]. 😳
+- **Bridge from Other EVM Networks**: You can [bridge] hundreds of assets from dozens of chains to Flow.
+- **VM Token Bridge**: Assets can be bridged between Flow Cadence and Flow EVM easily and atomically with the VM token bridge. Assets can even be bridged **and used** in a **single** transaction, allowing full composability between the EVM and Cadence environments.
+- **Access to Cadence**: Access Cadence features and contracts from Flow EVM to take advantage of native [VRF], higher computation for lower cost, and any asset on Cadence Flow. You can also build [cross-vm apps] on top of the wagmi/viem/RainbowKit stack, enabling batched transactions and more.
+- **EVM Equivalence:** Flow EVM is truly _EVM Equivalent_, not just _EVM Compatible_. It runs exactly the same as EVM mainnet, which means builders won't run into "minor" variances or endless "quirks" when they try to integrate. If it works on Ethereum Mainnet, it will work with Flow EVM.
+
+## Learning Shortcuts
+
+To get a complete picture on how to build on Flow, follow the 👈 sidebar top to bottom. This path will give you the most thorough onboarding experience.
+
+If you like to jump right into the deep end of the pool, take a look below for direct links to advanced topics!
+
+### Learn Cadence
+
+[Cadence] is a modern smart contract programming language designed to work with Flow. Learning a new language is an investment, but you'll find that Cadence is safer, more explicit, and less dangerous than other blockchain languages. Plus, it unlocks the full power of the Flow protocol!
+
+:::tip
+
+If you're already comfortable with Solidity, be sure to check out how [Cadence] works in our [Guide for Solidity Developers]!
+
+:::
+
+### Build with the EVM
+
+Not ready to take the plunge and learn [Cadence]? Try out "EVM++" by deploying existing [EVM] contracts to see that Flow EVM is faster and cheaper than nearly every other EVM solution without compromising on security.
+
+Deploying on Flow EVM also gives your Solidity contracts access to many Flow Cadence features, such as native [VRF].
+
+### Getting Started with App Development
+
+The [Getting Started] tutorial covers everything you need to know to build a Flow Cadence application:
+
+- Setting up your local development environment (it's fast and easy!)
+- Deploying and interacting with Flow Cadence contracts
+- Building a frontend that can interact with smart contracts written by you, or other developers
+
+### Core Contracts
+
+The Flow blockchain implements core functionality using its own smart contract language, [Cadence]. The core functionality is split into a set of contracts, called the [core contracts]:
+
+- **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.
+- **Flow Fees:** The FlowFees contract is where all the collected Flow fees are gathered.
+- **Service Account:** The FlowServiceAccount contract tracks transaction fees and deployment permissions and provides convenient methods for Flow Token operations.
+- **Staking Table:** The FlowIDTableStaking contract is the central table that manages staked nodes, delegation, and rewards.
+- **Epoch Contract:** The FlowEpoch contract is the state machine that manages Epoch phases and emits service events.
+
+
+### FLOW Token
+
+The [FLOW] (or $FLOW) token is the native currency for the Flow network. Developers and users can use FLOW to transact on the network. Developers can integrate FLOW directly into their apps for peer-to-peer payments, service charges, or consumer rewards. FLOW can be held, transferred, or transacted peer-to-peer.
+
+- To understand more about Flow Token Economics and the FLOW token, read the [Flow Token Economics] guide.
+- FLOW tokens are the native Fungible Token on Flow. To learn more about how to work with them in your applications, review the [FLOW] article.
+
+### Technical Background
+
+- The [Flow Technical Primer] is a great place to start to understand how Flow works.
+- The [Three technical whitepapers] cover the unique innovation behind the Flow blockchain network in-depth.
+
+
+
+
+[ERC-721 NFT standard]: https://github.com/ethereum/eips/issues/721
+[CryptoKitties]: https://www.cryptokitties.co/
+[Dapper Labs]: https://www.dapperlabs.com/
+[struggled under its own success]: https://spectrum.ieee.org/cryptokitties
+[blockchain trilemma]: https://coinmarketcap.com/academy/glossary/blockchain-trilemma
+[NBA Top Shot]: https://nbatopshot.com/
+[NFL All Day]: https://nflallday.com/
+[Mattel Creations]: https://creations.mattel.com/pages/virtual
+[Disney Pinnacle]: https://disneypinnacle.com/
+[digital assets]: https://www.onflow.org/post/flow-blockchain-cadence-programming-language-resources-assets
+[widespread popularity]: https://www.cnn.com/style/article/cryptokitty-blockchain/index.html
+[multi-role architecture]: https://www.onflow.org/primer
+[onchain randomness]: ./advanced-concepts/randomness.md
+[paying $10+ USD per number]: https://docs.chain.link/vrf/v2-5/billing
+[ensure equitable access]: ./basics/mev-resistance.md
+[scale without sharding]: https://www.onflow.org/post/flow-blockchain-multi-node-architecture-advantages
+[a day]: https://docs.zksync.io/zk-stack/concepts/finality#finality-on-zksync-era
+[a week]: https://docs.optimism.io/stack/rollup/overview#fault-proofs
+[usually way less!]: https://evm.flowscan.io/stats
+[under 10 seconds]: ./basics/transactions.md#flow
+[signing roles]: ./basics/transactions.md#signer-roles
+[Cadence]: https://cadence-lang.org/
+[resource-oriented]: https://flow.com/post/resources-programming-ownership
+[Ethereum Virtual Machine (EVM)]: https://flow.com/upgrade/crescendo/evm.md
+[EVM]: https://flow.com/upgrade/crescendo/evm.md
+[Guide for Solidity Developers]: https://cadence-lang.org/docs/solidity-to-cadence
+[account abstraction]: https://flow.com/account-abstraction
+[bridge]: ../ecosystem/bridges.md
+[cross-vm apps]: ../tutorials/cross-vm-apps/index.md
+[Getting Started]: ./getting-started/contract-interaction.md
+[core contracts]: ./core-contracts/index.md
+[FLOW]: ./core-contracts/03-flow-token.md
+[Flow Technical Primer]: https://www.onflow.org/primer
+[Three technical whitepapers]: https://www.onflow.org/technical-paper
+[Flow Token Economics]: https://www.onflow.org/flow-token-economics
+[VRF]: ../evm/guides/vrf.md
+
+
+
+
+=== build/explore-more.md ===
+---
+title: Explore More
+sidebar_label: Explore More
+description: Discover additional tutorials, guides, and resources for building on Flow blockchain. Learn about NFTs, fungible tokens, dApp development, and core blockchain concepts.
+sidebar_position: 999
+keywords:
+ - Flow tutorials
+ - dApp development
+ - NFT guide
+ - fungible tokens
+ - Flow CLI
+ - FCL quickstart
+ - web3 apps
+ - Flow basics
+ - blockchain tutorials
+ - Emerald Academy
+ - Flow guides
+ - smart contracts
+ - Flow development
+ - learning resources
+ - Flow ecosystem
+---
+
+import DocCardList from '@theme/DocCardList';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import { faWindowMaximize, faCoins, faGem, faBook, faLandmark } from '@fortawesome/free-solid-svg-icons'
+
+
+Below are some additional tutorials to help you get started with Flow:
+
+ ,
+ author: {
+ name: 'Flow Blockchain',
+ profileImage:
+ 'https://avatars.githubusercontent.com/u/62387156?s=200&v=4',
+ },
+ },
+ },
+ {
+ type: 'link',
+ label: 'Fungible Token Guide',
+ href: '/build/guides/fungible-token',
+ description: 'Steps to create, deploy, mint, and transfer fungible tokens on Flow',
+ customProps: {
+ icon: ,
+ author: {
+ name: 'Flow Blockchain',
+ profileImage:
+ 'https://avatars.githubusercontent.com/u/62387156?s=200&v=4',
+ },
+ },
+ },
+ {
+ type: 'link',
+ label: 'NFT Guide',
+ href: 'https://academy.ecdao.org/en/quickstarts/1-non-fungible-token-next',
+ description: 'A DApp that lets users create an empty collection, mint some pre-loaded NFTs, and transfer them to another account on Flow testnet.',
+ customProps: {
+ icon: ,
+ author: {
+ name: 'Emerald City DAO',
+ profileImage:
+ 'https://pbs.twimg.com/profile_images/1687225095557632005/tUCmv8_P_400x400.jpg',
+ },
+ },
+ },
+ {
+ type: 'link',
+ label: 'Walkthrough Guides',
+ href: '/build/getting-started/fcl-quickstart',
+ description: 'Longer form guides to help you get started with Flow',
+ customProps: {
+ icon: ,
+ author: {
+ name: 'Flow Blockchain',
+ profileImage:
+ 'https://avatars.githubusercontent.com/u/62387156?s=200&v=4',
+ },
+ },
+ },
+ {
+ type: 'link',
+ label: 'Emerald Academy',
+ href: 'https://academy.ecdao.org/en/quickstarts',
+ description: 'Quickstart Tutorials for Flow created by Emerald City Dao',
+ customProps: {
+ icon: '/images/logos/ea-logo.png',
+ author: {
+ name: 'Emerald City DAO',
+ profileImage:
+ 'https://pbs.twimg.com/profile_images/1687225095557632005/tUCmv8_P_400x400.jpg',
+ },
+ },
+ },
+ {
+ type: 'link',
+ label: 'Basic Concepts',
+ href: '/build/basics/blocks',
+ description: 'Basic Concepts of Flow Blockchain',
+ customProps: {
+ icon: ,
+ author: {
+ name: 'Flow Blockchain',
+ profileImage:
+ 'https://avatars.githubusercontent.com/u/62387156?s=200&v=4',
+ },
+ },
+ }
+]} />
+
+
+=== build/smart-contracts/testing.md ===
+---
+title: Testing Your Contracts
+sidebar_label: Testing Your Contracts
+description: Learn comprehensive testing strategies for Flow smart contracts. Master unit testing, integration testing, and code coverage using the Cadence Testing Framework and Flow CLI.
+sidebar_position: 4
+sidebar_custom_props:
+ icon: 📝
+keywords:
+ - smart contract testing
+ - Cadence testing
+ - test coverage
+ - unit tests
+ - integration tests
+ - Flow CLI
+ - test automation
+ - testing framework
+ - test suites
+ - code coverage
+ - test assertions
+ - test helpers
+ - automated testing
+ - contract verification
+ - testing best practices
+---
+
+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.
+
+## Install Flow CLI
+
+The [Flow CLI](../../tools/flow-cli/index.md) is the primary tool for developing, testing, and deploying 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](../../tools/flow-cli/install.md).
+
+## 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](../../tools/flow-cli/flow.json/configuration.md).
+
+```bash
+mkdir test-cadence
+cd test-cadence
+flow init
+```
+
+## Write a simple smart contract
+
+In your code editor, create a new file called `calculator.cdc` and add the following code:
+
+```cadence calculator.cdc
+access(all) contract Calculator {
+ access(all)
+ fun add(a: Int, b: Int): Int {
+ return a + b
+ }
+
+ access(all)
+ fun subtract(a: Int, b: Int): Int {
+ return a - b
+ }
+
+ access(all)
+ fun multiply(a: Int, b: Int): Int {
+ return a * b
+ }
+}
+```
+
+## Add the smart contract to the config
+
+Next up, we need to add our new contract in the `contracts` key in the `flow.json` config file. More specifically, we need to add the contract name, location and an address alias for the `testing` environment.
+
+```json
+{
+ "contracts": {
+ "Calculator": {
+ "source": "./calculator.cdc",
+ "aliases": {
+ "testing": "0x0000000000000007"
+ }
+ }
+ },
+ "networks": {...},
+ "accounts": {...},
+ "deployments": {...}
+}
+```
+
+For the time being, the address for the `testing` alias, can be one of:
+- `0x0000000000000005`
+- `0x0000000000000006`
+- `0x0000000000000007`
+- `0x0000000000000008`
+- `0x0000000000000009`
+- `0x000000000000000a`
+- `0x000000000000000b`
+- `0x000000000000000c`
+- `0x000000000000000d`
+- `0x000000000000000e`
+
+In the next release, there will be `20` addresses for contract deployment during testing.
+
+## Write unit tests
+
+In the same directory, create a new file called `calculator_test.cdc` and add the following code:
+
+```cadence calculator_test.cdc
+import Test
+import "Calculator" // contract name from the previous step
+
+access(all)
+fun setup() {
+ let err = Test.deployContract(
+ name: "Calculator",
+ path: "./calculator.cdc",
+ arguments: []
+ )
+ Test.expect(err, Test.beNil())
+}
+
+access(all)
+fun testAdd() {
+ Test.assertEqual(5, Calculator.add(a: 2, b: 3))
+}
+
+access(all)
+fun testSubtract() {
+ Test.assertEqual(2, Calculator.subtract(a: 5, b: 3))
+}
+```
+
+This code:
+- imports the `Calculator` contract from the `calculator.cdc` file (according to `flow.json`)
+- deploys the `Calculator` contract to the address specified in the `testing` alias
+- defines two test cases: `testAdd()` and `testSubtract()`
+- calls `add()` and `subtract()` methods with different input values respectively.
+
+## Running the test cases
+
+To run the test cases, use the following command in the terminal:
+
+```bash
+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:
+
+```bash
+Test results: "calculator_test.cdc"
+- PASS: testAdd
+- PASS: testSubtract
+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:
+
+```json
+{
+ "coverage": {
+ "A.0000000000000007.Calculator": {
+ "line_hits": {
+ "14": 0,
+ "4": 1,
+ "9": 1
+ },
+ "missed_lines": [
+ 14
+ ],
+ "statements": 3,
+ "percentage": "66.7%"
+ }
+ }
+}
+```
+
+Line 14 from the `Calculator` smart contract is marked as missed. This is the line:
+
+```cadence
+return a * b
+```
+which is the `multiply` method.
+
+By adding a test case for the above method:
+
+```cadence calculator_test.cdc
+...
+
+access(all)
+fun testMultiply() {
+ Test.assertEqual(10, Calculator.multiply(a: 2, b: 5))
+}
+```
+
+our code coverage percentage goes to `100%`:
+
+```bash
+flow test --cover --covercode="contracts" calculator_test.cdc
+
+Test results: "calculator_test.cdc"
+- PASS: testAdd
+- PASS: testSubtract
+- PASS: testMultiply
+Coverage: 100.0% of statements
+```
+
+## Advanced Testing Techniques
+
+The Cadence testing framework provides various features and techniques for writing 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.
+- **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.
+
+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.
+
+This is a basic example, and there are many more advanced features and techniques you can explore when working 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](../../tools/flow-cli/index.md).
+
+## Testing Requirements
+
+It is suggested to follow the following best practices:
+
+- Every publicly exposed feature of a contract and its resources should have unit tests that check both for success with correct input _and_ for failure with incorrect input.
+ These tests should be capable of being run locally with the Flow emulator, with no or minimal extra resources or configuration, and with a single command.
+- Each user story or workflow that uses the smart contracts should have an integration test that ensures that the series of steps required to complete it does so successfully with test data.
+
+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
+
+There are official SDKs/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.
+
+### 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](../../tools/flow-cli/index.md) tool, which includes a dedicated command for running 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.
+
+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.
+
+
+
+There is also a [repository](https://github.com/m-Peter/flow-code-coverage#readme) which contains some sample contracts and their tests.
+
+
+
+
+
+
+The Cadence testing framework utilizes the emulator under the hood.
+
+
+### Go Tests
+
+Tests in Go can be written using [flow-go-sdk](https://github.com/onflow/flow-go-sdk) and the go test command.
+
+You can find examples of Go tests in the following projects: [flow-core-contracts](https://github.com/onflow/flow-core-contracts/tree/master/lib/go/test), [flow-nft](https://github.com/onflow/flow-nft/tree/master/lib/go/test), [flow-ft](https://github.com/onflow/flow-ft/tree/master/lib/go/test).
+
+
+These tests are tied to the emulator but can be refactored to run on testnet
+
+
+## Testing Your Application
+
+### Automated Testing of Contract Code
+
+All contracts should include test coverage for _all contract functions_. Make sure you've accounted for success and failure cases appropriately.
+
+Tests should also be runnable in automated environments (CI). You can use the [Cadence testing utils](https://cadence-lang.org/docs/testing-framework) to create tests for your smart contract code.
+
+### Stress Testing Live Applications Before Mainnet
+
+Once you deployed your application to the testnet, you should record how your application handles non-trivial amounts of traffic to ensure there are no issues.
+
+
+Get familiar with the [Cadence anti-patterns](https://cadence-lang.org/docs/anti-patterns) to avoid avoid problematic or unintended behavior.
+
+
+
+## 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).
+
+
+=== build/smart-contracts/overview.md ===
+---
+title: Smart Contracts on Flow
+sidebar_label: Smart Contracts on Flow
+sidebar_position: 2
+sidebar_custom_props:
+ icon: 🛠️
+description: Learn about smart contract development on Flow blockchain. Understand data storage, standards implementation, and best practices for building decentralized applications using Cadence.
+keywords:
+ - smart contracts
+ - Flow blockchain
+ - Cadence
+ - dApp development
+ - NFT standards
+ - fungible tokens
+ - contract storage
+ - IPFS storage
+ - blockchain data
+ - Flow standards
+ - contract interfaces
+ - development tools
+ - Flow CLI
+ - Flow emulator
+ - 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 "on-chain" 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
+
+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.
+
+### 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.
+
+### 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](../../tools/flow-cli/index.md): A utility to directly interact with the chain and manage accounts and contracts.
+- [Flow Emulator](../../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](../../tools/vscode-extension/index.md): An IDE integration for developing smart contracts.
+
+## Storing 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.
+
+### 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
+
+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.
+
+### 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.
+
+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.
+
+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).
+
+## Using Existing Standards
+
+The Flow blockchain has existing smart contract standards for both fungible and non-fungible tokens that you should implement when building your contracts.
+
+### Non-Fungible Tokens (NFTs)
+
+All NFTs on the Flow blockchain implement the [NonFungibleToken](../../build/core-contracts/08-non-fungible-token.md) interface, allowing them to be compatible with wallets, marketplaces and other cross-app experiences.
+
+See the [NFT Guide](../guides/nft.md) for a guide on how to create a basic NFT contract
+that conforms to the standard.
+
+- [Non-Fungible Token (NFT) contract interface](../../build/core-contracts/08-non-fungible-token.md)
+
+### 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)
+
+### Fungible Tokens
+
+Fungible tokens (i.e. coins, currencies) on the Flow blockchain, including the default cryptocurrency token FLOW, implement the [FungibleToken](../../build/core-contracts/02-fungible-token.md) interface.
+
+See the [FT Guide](../guides/fungible-token.md) for a guide on how to create a basic fungible token
+contract that conforms to the standard.
+
+- [Fungible Token contract interface](../../build/core-contracts/02-fungible-token.md)
+
+
+=== build/smart-contracts/learn-cadence.md ===
+---
+sidebar_position: 1
+slug: /build/learn-cadence
+title: Learn Cadence ↗️
+---
+
+
+
+ ;
+
+=== build/smart-contracts/deploying.md ===
+---
+title: Deploying Contracts
+sidebar_label: Deploying Contracts
+description: Learn how to deploy and update smart contracts on Flow Mainnet and Testnet. Understand account creation, key management, deployment best practices, and network sporks.
+sidebar_position: 3
+sidebar_custom_props:
+ icon: 🥇
+keywords:
+ - contract deployment
+ - Flow mainnet
+ - Flow testnet
+ - account creation
+ - key management
+ - Flow CLI
+ - smart contracts
+ - deployment guide
+ - contract updates
+ - sporks
+ - network migration
+ - testnet faucet
+ - deployment security
+ - contract addresses
+ - Flow deployment
+---
+
+In order to deploy your smart contracts to the mainnet, you need a funded account. If you want to get started on Testnet, look below for information on how to get started.
+
+
+Make sure you handle your mainnet account keys appropriately. Using a Key Management Service is the best practice.
+
+
+### Creating an Account
+
+There are two simple methods of creating an account on testnet. **Interactive** and **Manual**, both use the Flow CLI. On mainnet you will have to fund your newly created account, there is no faucet.
+Make sure to install the Flow CLI. [Flow CLI](../../tools/flow-cli/accounts/create-accounts.md) has a interactive mode for generating keys.
+
+
+Anyone can deploy and update contracts on mainnet. Audits are encouraged but not mandatory to deploying contracts to mainnet. Take every precauction to reduce issues and protect users.
+
+
+### Create and deploy a mainnet project
+The tool of choice is Flow CLI, there are quickstarts and guides that use Flow CLI, [Getting Started](../getting-started/flow-cli)
+- It is highly encouraged to test your contracts, transactions and scripts on Testnet, have strong smart contract test coverage and follow any additional guidelines set out here: [Smart Contract Testing Guidelines](./testing.md).
+- Follow the Flow CLI instructions to [Create a Project](../../tools/flow-cli/index.md). You have the Flow CLI installed and ran `flow init` in your project folder and generating a `flow.json` file
+- Mainnet account: You completed the mainnet account setup, (see above) and have your key pair and mainnet address ready.
+- [Deploy your project](../../tools/flow-cli/deployment/deploy-project-contracts.md), notice that your account now has contracts deployed on mainnet.
+- [Deploy a contract](../../tools/flow-cli/accounts/account-add-contract.md) to mainnet. You can deploy contracts individually using the `account-add-contract` command.
+
+
+All your contract deployment addresses are stored in `flow.json`. Mainnet, Testnet and local (emulator) are stored as well.
+
+
+### Deploy updated contracts on mainnet
+
+Contracts can be updated and retain the contract address. You can use the [Flow CLI contract update command](../../tools/flow-cli/accounts/account-update-contract.md) to re-deploy an updated version of your contract:
+
+
+If you see `Error Code: 1103`, your new account does not have enough funds to complete the transaction. Make sure you have enough FLOW and your account is set up correctly, check [Flowdiver](https://flowdiver.io/) to verify.
+
+
+Once all your contracts are deployed, you can visit [flow-view-source](https://flow-view-source.com/) or run the [Flow CLI get account command](../../tools/flow-cli/accounts/get-accounts.md) to confirm the deployment.
+
+### Sporks
+
+Currently, **historical event data is not migrated between sporks,** so you'll need to design your application with this in mind. We recognize the usefulness of historical event data and plan on adding a means of accessing it in the near future. Past spork transactional data is available, [See Previous Spork Access Node Info](../../networks/node-ops/node-operation/past-upgrades)
+
+More Information on [Sporks](../../networks/node-ops/node-operation/spork)
+
+
+### Testnet
+
+
+The Flow test network, known as Flow Testnet, exists to help developers test their software and smart contracts against a live network. It's also used as a means of releasing and testing new protocol and smart contract features before they are integrated into Flow's main network (Mainnet).
+
+When the Flow protocol is updated or a new version of Cadence is released, those updates will always be made available on the [Flow Emulator](../../tools/emulator) _before_ they're integrated into Flow Testnet or Flow Mainnet.
+
+## Getting Started on Testnet
+
+If you need to create a flow.json file to store information about accounts and contracts use the `flow init` command to create a project
+
+To create accounts and generate keys, make sure to install [Flow CLI](../../tools/flow-cli/install). Flow CLI provides convenient functions to simplifies interacting with the blockchain.
+
+
+
+### Creating an Account
+
+There is a simple Flow CLI command to run to create an account. `flow accounts create` command will create a new account and generate a key pair then add the account to your flow.json. The command will try and You can also use the [Testnet Faucet](https://testnet-faucet-v2.onflow.org/) to create and fund an account.
+
+More information about [Flow CLI](../../tools/flow-cli/accounts/create-accounts) and creating accounts.
+
+### Creating and deploying a Project
+
+Flow CLI can be used to create a Cadence project and stay organized, [Flow CLI: Create a project](../../tools/flow-cli). This will make deployment much easiler and help with the iterative development process.
+
+After you have a project created and want to deploy your Cadence; contracts, transactions and scripts.
+`flow accounts add-contract --signer --network testnet` will deploy your contract to testnet.
+More information on how to use Flow CLI to [deploy](../../tools/flow-cli/deployment/deploy-project-contracts.md).
+
+Make sure Flow project was initialized in the previous step and the `flow.json` is present.
+
+
+### Making Use of Core Contracts
+
+Flow Testnet comes with some useful contracts already deployed, called **core contracts.** More information and import addresses for the [core contracts](../../build/core-contracts/index.md).
+
+Once your accounts are set up and you're ready to develop, you can look over [some code examples from the Flow Go SDK](https://github.com/onflow/flow-go-sdk/tree/master/examples).
+
+
+### Breaking Changes
+
+The Flow blockchain is improved continuously and thus version updates to Cadence, Flow node software, and the Flow SDKs will contain important updates as well as breaking changes.
+
+You should anticipate future updates and join the community ([Forum](https://forum.onflow.org/) or [Discord](https://discord.com/invite/J6fFnh2xx6)) to stay tuned on important announcements. Notices and guidelines for changes will be provided as early as possible.
+
+
+### Testnet Sporking
+
+"Sporking" (soft forking) is the process of upgrading the Flow network node software and migrating the chain state from one version to another.
+
+Currently, **historical event data is not migrated between sporks.** You'll need to design your application with this in mind. We recognize the usefulness of historical event data and plan on adding a means of accessing it in the near future. Only one previous spork data is available through old Access Node.
+
+
+
+Flow Testnet is explicitly for experimentation and testing and should not be used to exchange "real value" (e.g. developing a fiat money on/off-ramp for your testnet application).
+
+
+
+
+
+
+=== build/smart-contracts/best-practices/security-best-practices.md ===
+---
+title: Cadence Security Best Practices
+sidebar_label: Security Best Practices
+sidebar_position: 3
+description: Learn essential security practices for writing secure Cadence smart contracts. Understand how to handle references, account storage, capabilities, transactions, and access control safely.
+keywords:
+ - security practices
+ - Cadence security
+ - smart contract security
+ - secure coding
+ - reference safety
+ - account storage
+ - capabilities
+ - access control
+ - transaction security
+ - type safety
+ - authorization
+ - secure development
+ - Flow security
+ - best practices
+ - security guidelines
+---
+
+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.
+
+## 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 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.
+
+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.
+
+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.
+
+## 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.
+
+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.
+
+## 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.
+
+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.
+
+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.
+
+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.
+
+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.
+
+## 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.
+
+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.
+
+Do not blindly sign a transaction. The transaction could for example change deployed contracts by upgrading them with malicious statements, revoking or adding keys, transferring resources from storage, etc.
+
+## 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.
+
+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.
+
+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.
+
+
+=== build/smart-contracts/best-practices/project-development-tips.md ===
+---
+title: Flow Smart Contract Project Development Standards
+sidebar_label: Development Standards
+sidebar_position: 5
+description: Learn best practices for organizing and managing Cadence smart contract projects. Understand key aspects of design, development, testing, deployment, and community engagement.
+keywords:
+ - development standards
+ - smart contracts
+ - project management
+ - best practices
+ - Cadence development
+ - testing standards
+ - documentation
+ - deployment process
+ - project organization
+ - code review
+ - security practices
+ - community engagement
+ - open source
+ - technical leadership
+ - Flow development
+---
+
+# 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](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 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](https://cadence-lang.org/docs/).
+
+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 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.
+
+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.
+ - 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.
+
+## Development Process Recommendations
+
+### 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.
+
+### Comments and field/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.
+
+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
+
+
+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 (`//`)
+
+## Testing Recommendations
+
+Summarized below is a list of testing related recommendations
+which are noteworthy to mention for a typical smart contract project.
+
+Popular testing frameworks to use for cadence are listed here:
+- Cadence: [Cadence Testing Framework](../../smart-contracts/testing.md)
+- Go: [Overflow](https://github.com/bjartek/overflow)
+
+The same person who writes the code should also write the tests.
+They have the clearest understanding of the code paths and edge cases.
+
+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.
+
+
+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 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.
+
+Integration tests should also be written to ensure that your app and/or backend can interact
+properly with the smart contracts.
+
+## Managing 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
+
+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.
+
+### 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 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.
+
+- 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.
+ - 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.
+
+### 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.
+
+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
+
+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.
+
+### 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.
+
+- Keep issues open in the repo.
+- The owner should turn on email notifications for new issue creation in the repo.
+- Respond to issues quickly and clean up unimportant ones.
+- Consider blog posts to share more details on technical aspects of the project and upcoming changes.
+
+### 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:
+
+- [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)
+
+Composability and extensibility should also be priorities while designing, developing,
+and documenting their projects. (Documentation for these topics coming soon)
+
+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.
+
+
+=== build/smart-contracts/best-practices/contract-upgrades.md ===
+---
+title: Contract Upgrades with Incompatible Changes
+sidebar_position: 4
+description: Learn best practices for handling incompatible contract upgrades on Flow. Understand the risks and recommended approaches for upgrading smart contracts while maintaining data integrity.
+keywords:
+ - contract upgrades
+ - smart contracts
+ - incompatible changes
+ - contract migration
+ - upgrade strategy
+ - contract deployment
+ - Flow blockchain
+ - contract versioning
+ - data migration
+ - contract paths
+ - resource management
+ - upgrade transactions
+ - contract compatibility
+ - best practices
+ - contract security
+---
+
+### 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](https://cadence-lang.org/docs/language/contract-updatability) 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!
+
+
+=== build/guides/nft.md ===
+---
+title: Creating an NFT Contract
+description: Learn how to create and deploy a non-fungible token (NFT) contract on Flow using Cadence. Follow this guide to implement the Flow NFT standard, manage collections, and handle token minting and transfers.
+sidebar_position: 5
+keywords:
+ - NFT
+ - non-fungible token
+ - Flow NFT
+ - NFT standard
+ - smart contract
+ - Cadence
+ - token minting
+ - NFT collection
+ - Flow CLI
+ - token deployment
+ - NFT transfer
+ - digital assets
+ - Flow development
+ - NFT contract
+ - blockchain NFTs
+---
+
+:::info
+
+This guide is an in-depth tutorial on launching NFT contracts from scratch.
+To launch in 2 minutes using a tool check out [Touchstone](https://www.touchstone.city/)
+
+:::
+
+## What are NFTs
+
+NFTs, or Non-Fungible Tokens, represent a unique digital asset verified
+using blockchain technology. Unlike cryptocurrencies such as Bitcoin,
+which are fungible and can be exchanged on a one-for-one basis,
+NFTs are distinct and cannot be exchanged on a like-for-like basis.
+This uniqueness and indivisibility make them ideal for representing
+rare and valuable items like art, collectibles, tickets and even real estate.
+Their blockchain-backed nature ensures the authenticity and ownership of these digital assets.
+
+## Setting Up a Project
+
+To start creating an NFT on the Flow blockchain, you'll first need some tools and configurations in place.
+
+### Installing Flow CLI
+
+The **Flow CLI** (Command Line Interface) provides a suite of tools
+that allow developers to interact seamlessly with the Flow blockchain.
+
+If you haven't installed the Flow CLI yet and have [Homebrew](https://brew.sh/) installed,
+you can run `brew install flow-cli`. If you don't have Homebrew,
+please follow [the installation guide here](../../tools/flow-cli/install.md).
+
+### Initializing a New Project
+
+> 💡 Note: Here is [a link to the completed code](https://github.com/chasefleming/foobar-nft) if you want to skip ahead or reference as you follow along.
+
+Once you have the Flow CLI installed, you can set up a new project using the `flow init` command. This command initializes the necessary directory structure and a `flow.json` configuration file (a way to configure your project for contract sources, deployments, accounts, and more):
+
+```bash
+flow init foobar-nft
+```
+
+> Note: Select "No" when it asks you to install core contracts for the purposes of this tutorial.
+
+Upon execution, the command will generate the following directory structure:
+
+```
+/cadence
+ /contracts
+ /scripts
+ /transactions
+ /tests
+flow.json
+```
+
+Now, navigate into the project directory:
+
+```bash
+cd foobar-nft
+```
+
+To begin, let's create a contract file named `FooBar` for the `FooBar` token,
+which will be the focus of this tutorial. To do this, we can use the boilerplate `generate` command from the Flow CLI:
+
+```bash
+flow generate contract FooBar
+```
+
+This will create a new file at `cadence/contracts/FooBar.cdc` with the following contents:
+
+```cadence
+access(all) contract FooBar {
+ init() {}
+}
+```
+
+Now, add these contracts to your `flow.json`.
+These are important contracts that your contract will import that
+are pre-deployed to the emulator.
+
+```json
+"contracts": {
+ "NonFungibleToken": {
+ "aliases": {
+ "emulator": "f8d6e0586b0a20c7"
+ }
+ },
+ "ViewResolver": {
+ "aliases": {
+ "emulator": "0xf8d6e0586b0a20c7"
+ }
+ },
+ "MetadataViews": {
+ "aliases": {
+ "emulator": "0xf8d6e0586b0a20c7"
+ }
+ }
+}
+```
+
+## Setting Up Our NFT on the Contract
+
+### Understanding Resources
+
+On the Flow blockchain, "[Resources](https://cadence-lang.org/docs/tutorial/resources-compose)"
+are a key feature of the Cadence programming language.
+They represent unique, non-duplicable assets, ensuring that they can only exist
+in one place at a time. This concept is crucial for representing NFTs on Flow,
+as it guarantees their uniqueness.
+
+To begin, let's define a basic `NFT` resource.
+This resource requires an `init` method, which is invoked when the resource is instantiated:
+
+```cadence
+access(all) contract FooBar {
+
+ access(all) resource NFT {
+ init() {}
+ }
+
+ init() {}
+}
+```
+
+Every resource in Cadence has a unique identifier assigned to it.
+We can use it to set an ID for our NFT. Here's how you can do that:
+
+```cadence
+access(all) contract FooBar {
+
+ access(all) resource NFT {
+ access(all) let id: UInt64
+
+ init() {
+ self.id = self.uuid
+ }
+ }
+
+ init() {}
+}
+```
+
+To control the creation of NFTs, it's essential to have a mechanism
+that restricts their minting. This ensures that not just anyone can create an NFT and inflate its supply.
+To achieve this, you can introduce an `NFTMinter` resource that contains a `createNFT` function:
+
+```cadence
+access(all) contract FooBar {
+
+ // ...[previous code]...
+
+ access(all) resource NFTMinter {
+ access(all) fun createNFT(): @NFT {
+ return <-create NFT()
+ }
+
+ init() {}
+ }
+
+ init() {}
+}
+```
+
+In this example, the `NFTMinter` resource will be stored on the contract account's storage.
+This means that only the contract account will have the ability to mint new NFTs.
+To set this up, add the following line to the contract's `init` function:
+
+```cadence
+access(all) contract FooBar {
+
+ // ...[previous code]...
+
+ init() {
+ self.account.storage.save(<- create NFTMinter(), to: /storage/fooBarNFTMinter)
+ }
+}
+```
+
+### Setting Up an NFT Collection
+
+Storing individual NFTs directly in an account's storage can cause issues,
+especially if you want to store multiple NFTs.
+Instead, it's required to create a collection that can hold multiple NFTs.
+This collection can then be stored in the account's storage.
+
+Start by creating a new resource named `Collection`.
+This resource will act as a container for your NFTs, storing them in a dictionary indexed by their IDs.
+
+```cadence
+access(all) contract FooBar {
+
+ // ...[NFT resource code]...
+
+ access(all) resource Collection {
+
+ access(all) var ownedNFTs: @{UInt64: NFT}
+
+ init() {
+ self.ownedNFTs <- {}
+ }
+
+ }
+
+ // ...[NFTMinter code]...
+}
+```
+
+## Fitting the Flow NFT Standard
+
+To ensure compatibility and interoperability within the Flow ecosystem,
+it's crucial that your NFT contract adheres to the [Flow NFT standard](https://github.com/onflow/flow-nft).
+This standard defines the events, functions, resources, metadata and other elements that a contract should have.
+By following this standard, your NFTs will be compatible with various marketplaces, apps, and other services within the Flow ecosystem.
+
+### Applying the Standard
+
+To start, you need to inform the Flow blockchain that your contract will implement the `NonFungibleToken` standard.
+Since it's a standard, there's no need for deployment.
+It's already available on the Emulator, Testnet, and Mainnet for the community's benefit.
+
+Begin by importing the token standard into your contract
+and adding the correct interface conformances to FooBar, NFT, and Collection:
+
+```cadence
+import "NonFungibleToken"
+
+access(all) contract FooBar: NonFungibleToken {
+
+ /// Standard Paths
+ access(all) let CollectionStoragePath: StoragePath
+ access(all) let CollectionPublicPath: PublicPath
+
+ /// Path where the minter should be stored
+ /// The standard paths for the collection are stored in the collection resource type
+ access(all) let MinterStoragePath: StoragePath
+
+ // ...contract code
+
+ access(all) resource NFT: NonFungibleToken.NFT {
+ // ...NFT code
+ }
+
+ access(all) resource Collection: NonFungibleToken.Collection {
+
+ // Make sure to update this field!
+ access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}}
+
+ // ...Collection Code
+ }
+
+ // ...rest of the contract code
+
+ init() {
+ // Set the named paths
+ self.CollectionStoragePath = /storage/fooBarNFTCollection
+ self.CollectionPublicPath = /public/fooBarNFTCollection
+ self.MinterStoragePath = /storage/fooBarNFTMinter
+ self.account.storage.save(<- create NFTMinter(), to: self.MinterStoragePath)
+ }
+}
+```
+
+As you can see, we also added standard paths for the Collection and Minter
+
+These interface conformances for [NFT](https://github.com/onflow/flow-nft/blob/master/contracts/NonFungibleToken.cdc#L98)
+and [Collection](https://github.com/onflow/flow-nft/blob/master/contracts/NonFungibleToken.cdc#L190)
+inherit from other interfaces that provide important functionality and restrictions
+for your NFT and Collection types.
+
+To allow accounts to create their own collections, add a function
+in the main contract that creates a new `Collection` and returns it.
+This function takes a `nftType: Type` argument that allows the caller
+to specify which type of `Collection` they want to create.
+Contracts that implement multiple `NFT` and/or `Collection` types can use this argument,
+but since your contract is only implementing one `NFT` and `Collection` type,
+it can ignore the argument.
+You'll also want to add a simpler one directly
+to the `NFT` and `Collection` definitions
+so users can directly create a collection from an existing collection:
+
+```cadence
+access(all) contract FooBar: NonFungibleToken {
+
+ // ...other FooBar contract code
+
+ access(all) resource NFT: NonFungibleToken.NFT {
+ // ...NFT code
+
+ access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
+ return <-FooBar.createEmptyCollection(nftType: Type<@FooBar.NFT>())
+ }
+ }
+
+
+ access(all) resource Collection: NonFungibleToken.Collection {
+
+ // ...other Collection code
+
+ /// createEmptyCollection creates an empty Collection of the same type
+ /// and returns it to the caller
+ /// @return A an empty collection of the same type
+ access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
+ return <-FooBar.createEmptyCollection(nftType: Type<@FooBar.NFT>())
+ }
+ }
+
+ // ...other FooBar contract code
+
+ /// createEmptyCollection creates an empty Collection for the specified NFT type
+ /// and returns it to the caller so that they can own NFTs
+ access(all) fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection} {
+ return <- create Collection()
+ }
+
+ // ...FooBar minter and init code
+}
+```
+
+To manage the NFTs within a collection, you'll need functions to deposit and withdraw NFTs. Here's how you can add a `deposit` function:
+
+```cadence
+access(all) resource Collection: NonFungibleToken.Collection {
+
+ access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}}
+
+ /// deposit takes a NFT and adds it to the collections dictionary
+ /// and adds the ID to the id array
+ access(all) fun deposit(token: @{NonFungibleToken.NFT}) {
+ let token <- token as! @FooBar.NFT
+ let id = token.id
+
+ // add the new token to the dictionary which removes the old one
+ let oldToken <- self.ownedNFTs[token.id] <- token
+
+ destroy oldToken
+ }
+
+ // ...[following code]...
+}
+```
+
+Similarly, you can add a `withdraw` function to remove an NFT from the collection:
+
+```cadence
+access(all) resource Collection: NonFungibleToken.Collection {
+ // ...[deposit code]...
+
+ /// withdraw removes an NFT from the collection and moves it to the caller
+ access(NonFungibleToken.Withdraw) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} {
+ let token <- self.ownedNFTs.remove(key: withdrawID)
+ ?? panic("FooBar.Collection.withdraw: Could not withdraw an NFT with ID "
+ .concat(withdrawID.toString())
+ .concat(". Check the submitted ID to make sure it is one that this collection owns."))
+
+ return <-token
+ }
+
+ // ...[createEmptyCollection code]...
+}
+```
+
+As you can see, this function has an `access(NonFungibleToken.Withdraw)` access modifier.
+This is an example of entitlements in Cadence.
+[Entitlements](https://cadence-lang.org/docs/language/access-control#entitlements)
+are a way for developers to restrict access to privileged fields and functions
+in a composite type like a resource when a reference is created for it.
+In this example, the `withdraw()` function is always accessible to code that
+controls the full `Collection` object, but if a reference is created for it,
+the `withdraw()` function can only be called if the reference
+is authorized by the owner with `NonFungibleToken.Withdraw`,
+which is [a standard entitlement](https://github.com/onflow/flow-nft/blob/master/contracts/NonFungibleToken.cdc#L58)
+defined by the `NonFungibleToken` contract:
+
+```cadence
+// Example of an authorized entitled reference to a NonFungibleToken.Collection
+
+```
+
+Entitlements are important to understand because they are what protects
+privileged functionality in your resource objects from being accessed by third-parties.
+It is recommended to read the [entitlements documentation](https://cadence-lang.org/docs/language/access-control#entitlements)
+to understand how to use the feature properly.
+
+[References](https://cadence-lang.org/docs/language/references) can be freely up-casted and down-casted in Cadence, so it is important
+for privileged functionality to be protected by an entitlement so that it can
+only be accessed if it is authorized.
+
+### Standard NFT Events
+
+Many projects rely on events the signal when withdrawals or deposits happen.
+Luckily, the `NonFungibleToken` standard handles the definition and emission
+of events for projects, so there is no need for you to add any events
+to your implementation for withdraw and deposit.
+
+Here are the `FungibleToken` event definitions:
+
+```cadence
+ /// Event that is emitted when a token is withdrawn,
+ /// indicating the type, id, uuid, the owner of the collection that it was withdrawn from,
+ /// and the UUID of the resource it was withdrawn from, usually a collection.
+ ///
+ /// If the collection is not in an account's storage, `from` will be `nil`.
+ ///
+ access(all) event Withdrawn(type: String, id: UInt64, uuid: UInt64, from: Address?, providerUUID: UInt64)
+
+ /// Event that emitted when a token is deposited to a collection.
+ /// Indicates the type, id, uuid, the owner of the collection that it was deposited to,
+ /// and the UUID of the collection it was deposited to
+ ///
+ /// If the collection is not in an account's storage, `from`, will be `nil`.
+ ///
+ access(all) event Deposited(type: String, id: UInt64, uuid: UInt64, to: Address?, collectionUUID: UInt64)
+
+```
+
+These events are [emitted by the `Collection` interface](https://github.com/onflow/flow-nft/blob/master/contracts/NonFungibleToken.cdc#L202)
+in the `NonFungibleToken` contract whenever the relevant function is called on any implementation.
+
+There is also a `NonFungibleToken.NFT.ResourceDestroyed` event that is emitted every time an NFT is destroyed:
+```cadence
+ /// Event that is emitted automatically every time a resource is destroyed
+ /// The type information is included in the metadata event so it is not needed as an argument
+ access(all) event ResourceDestroyed(id: UInt64 = self.id, uuid: UInt64 = self.uuid)
+```
+`ResourceDestroyed` events are standard events that can be added to any resource definition
+to be emitted when the resource is destroyed. Learn more about them [in the Cadence docs](https://cadence-lang.org/docs/language/resources#destroy-events).
+
+Additionally, check out the optional [`Burner` contract](../core-contracts/14-burner.md),
+which is the standard that all projects should use for handling the destruction of any resource.
+
+Lastly, there is a [standard `NonFungibleToken.Updated` event](https://github.com/onflow/flow-nft/blob/master/contracts/NonFungibleToken.cdc#L63-L77)
+that your contract can emit if the NFT is updated in any way.
+This is optional though, so no need to include support for it in your implementation.
+
+To facilitate querying, you'll also want a function to retrieve
+important information from the collection, like what types it supports
+and all the NFT IDs within a collection:
+
+```cadence
+access(all) resource Collection: NonFungibleToken.Collection {
+ // ...[withdraw code]...
+
+ /// getIDs returns an array of the IDs that are in the collection
+ access(all) view fun getIDs(): [UInt64] {
+ return self.ownedNFTs.keys
+ }
+
+ /// getSupportedNFTTypes returns a list of NFT types that this receiver accepts
+ access(all) view fun getSupportedNFTTypes(): {Type: Bool} {
+ let supportedTypes: {Type: Bool} = {}
+ supportedTypes[Type<@FooBar.NFT>()] = true
+ return supportedTypes
+ }
+
+ /// Returns whether or not the given type is accepted by the collection
+ /// A collection that can accept any type should just return true by default
+ access(all) view fun isSupportedNFTType(type: Type): Bool {
+ return type == Type<@FooBar.NFT>()
+ }
+
+ // ...[createEmptyCollection code]...
+}
+```
+
+### Supporting NFT Metadata
+
+The Non-Fungible Token standard also enforces that implementations
+provide functionality to return a set of standard views about the tokens
+via the [ViewResolver](https://github.com/onflow/flow-nft/blob/master/contracts/ViewResolver.cdc)
+and [MetadataViews](https://github.com/onflow/flow-nft/blob/master/contracts/MetadataViews.cdc) definitions.
+(You will need to add these imports to your contract)
+These provide developers with standard ways of representing metadata
+about a given token such as token symbols, images, royalties, editions,
+website links, and standard account paths and types that third-parties can access in a standard way.
+You can see the [metadata views documentation](../advanced-concepts/metadata-views.md)
+for a more thorough guide using a NFT contract as an example.
+
+For now, you can add this code to your contract to support the important metadata:
+
+```cadence
+// Add this import!
+import "MetadataViews"
+
+access(all) contract FooBar: NonFungibleToken {
+
+ // ...other FooBar contract code
+
+ access(all) resource NFT: NonFungibleToken.NFT {
+
+ // ...other NFT code
+
+ /// Gets a list of views specific to the individual NFT
+ access(all) view fun getViews(): [Type] {
+ return [
+ Type(),
+ Type(),
+ Type(),
+ Type(),
+ Type()
+ ]
+ }
+
+ /// Resolves a view for this specific NFT
+ access(all) fun resolveView(_ view: Type): AnyStruct? {
+ switch view {
+ case Type():
+ return MetadataViews.Display(
+ name: "FooBar Example Token",
+ description: "An Example NFT Contract from the Flow NFT Guide",
+ thumbnail: MetadataViews.HTTPFile(
+ url: "Fill this in with a URL to a thumbnail of the NFT"
+ )
+ )
+ case Type():
+ // There is no max number of NFTs that can be minted from this contract
+ // so the max edition field value is set to nil
+ let editionInfo = MetadataViews.Edition(name: "FooBar Edition", number: self.id, max: nil)
+ let editionList: [MetadataViews.Edition] = [editionInfo]
+ return MetadataViews.Editions(
+ editionList
+ )
+ case Type():
+ return MetadataViews.Serial(
+ self.id
+ )
+ case Type():
+ return FooBar.resolveContractView(resourceType: Type<@FooBar.NFT>(), viewType: Type())
+ case Type():
+ return FooBar.resolveContractView(resourceType: Type<@FooBar.NFT>(), viewType: Type())
+ }
+ return nil
+ }
+ }
+
+ access(all) resource Collection: NonFungibleToken.Vault {
+
+ // ...[getIDs code]...
+
+ /// Allows a caller to borrow a reference to a specific NFT
+ /// so that they can get the metadata views for the specific NFT
+ access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? {
+ return &self.ownedNFTs[id]
+ }
+
+ // ...[rest of code]...
+ }
+
+ /// Gets a list of views for all the NFTs defined by this contract
+ access(all) view fun getContractViews(resourceType: Type?): [Type] {
+ return [
+ Type(),
+ Type()
+ ]
+ }
+
+ /// Resolves a view that applies to all the NFTs defined by this contract
+ access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
+ switch viewType {
+ case Type():
+ let collectionData = MetadataViews.NFTCollectionData(
+ storagePath: self.CollectionStoragePath,
+ publicPath: self.CollectionPublicPath,
+ publicCollection: Type<&FooBar.Collection>(),
+ publicLinkedType: Type<&FooBar.Collection>(),
+ createEmptyCollectionFunction: (fun(): @{NonFungibleToken.Collection} {
+ return <-FooBar.createEmptyCollection(nftType: Type<@FooBar.NFT>())
+ })
+ )
+ return collectionData
+ case Type():
+ let media = MetadataViews.Media(
+ file: MetadataViews.HTTPFile(
+ url: "Add your own SVG+XML link here"
+ ),
+ mediaType: "image/svg+xml"
+ )
+ return MetadataViews.NFTCollectionDisplay(
+ name: "The FooBar Example Collection",
+ description: "This collection is used as an example to help you develop your next Flow NFT.",
+ externalURL: MetadataViews.ExternalURL("Add your own link here"),
+ squareImage: media,
+ bannerImage: media,
+ socials: {
+ "twitter": MetadataViews.ExternalURL("Add a link to your project's twitter")
+ }
+ )
+ }
+ return nil
+ }
+}
+```
+
+If you ever plan on making your NFTs more complex, you should look into
+adding views for `Edition`, `EVMBridgedMetadata`, `Traits`, and `Royalties`.
+These views make it much easier for third-party sites like marketplaces
+and NFT information aggregators to clearly display information
+about your projects on their apps and websites and are critical
+for every project to include if we want to have a vibrant and interoperable
+ecosystem.
+
+## Deploying the Contract
+
+With your contract ready, it's time to deploy it.
+First, add the `FooBar` contract to the `flow.json` configuration file:
+
+```bash
+flow config add contract
+```
+
+When prompted, enter the following name and location (press `Enter` to skip alias questions):
+
+```
+Enter name: FooBar
+Enter contract file location: cadence/contracts/FooBar.cdc
+```
+
+Next, configure the deployment settings by running the following command:
+
+```bash
+flow config add deployment
+```
+
+Choose the `emulator` for the network and `emulator-account`
+for the account to deploy to.
+Then, select the `FooBar` contract (you may need to scroll down).
+This will update your `flow.json` configuration.
+After that, you can select `No` when asked to deploy another contract.
+
+To start the Flow emulator, run (you may need to approve a prompt to allow connection the first time):
+
+```bash
+flow emulator start
+```
+
+In a separate terminal or command prompt, deploy the contract:
+
+```bash
+flow project deploy
+```
+
+You'll then see a message that says `All contracts deployed successfully`.
+
+## Creating an NFTCollection
+
+To manage multiple NFTs, you'll need an NFT collection.
+Start by creating a transaction file for this purpose (we can use the `generate` command again):
+
+```bash
+flow generate transaction setup_foobar_collection
+```
+
+This creates a transaction file at `cadence/transactions/setup_foobar_collection.cdc`.
+
+Transactions, on the other hand, are pieces of Cadence code
+that can mutate the state of the blockchain.
+Transactions need to be signed by one or more accounts,
+and they can have multiple phases, represented by different blocks of code.
+
+In this file, import the necessary contracts and define a transaction
+to create a new collection, storing it in the account's storage.
+Additionally, the transaction creates a capability that allows others
+to get a public reference to the collection to read from its methods.
+
+This capability ensures secure, restricted access to specific functionalities or information within a resource.
+
+```cadence
+import "FooBar"
+import "NonFungibleToken"
+
+transaction {
+
+ prepare(signer: auth(BorrowValue, IssueStorageCapabilityController, PublishCapability, SaveValue, UnpublishCapability) &Account) {
+
+ // Return early if the account already has a collection
+ if signer.storage.borrow<&FooBar.Collection>(from: FooBar.CollectionStoragePath) != nil {
+ return
+ }
+
+ // Create a new empty collection
+ let collection <- FooBar.createEmptyCollection(nftType: Type<@FooBar.NFT>())
+
+ // save it to the account
+ signer.storage.save(<-collection, to: FooBar.CollectionStoragePath)
+
+ let collectionCap = signer.capabilities.storage.issue<&FooBar.Collection>(FooBar.CollectionStoragePath)
+ signer.capabilities.publish(collectionCap, at: FooBar.CollectionPublicPath)
+ }
+}
+```
+
+There are also examples of [generic transactions](https://github.com/onflow/flow-nft/blob/master/transactions/setup_account_from_address.cdc)
+that you can use to setup an account for ANY non-fungible token using metadata views!
+You should check those out and try to use generic transactions whenever it is possible.
+
+To store this new NFT collection, create a new account:
+
+```bash
+flow accounts create
+```
+
+Name it `test-acct` and select `emulator` as the network. Then, using the Flow CLI, run the transaction:
+
+```bash
+flow transactions send cadence/transactions/setup_foobar_collection.cdc --signer test-acct --network emulator
+```
+
+Congratulations! You've successfully created an NFT collection for the `test-acct`.
+
+## Get an Account's NFTs
+
+To retrieve the NFTs associated with an account, you'll need a script.
+Scripts are read-only operations that allow you to query the blockchain.
+They don't modify the blockchain's state, and therefore,
+they don't require gas fees or signatures (read more about scripts here).
+
+Start by creating a script file using the `generate` command again:
+
+```bash
+flow generate script get_foobar_ids
+```
+
+In this script, import the necessary contracts and define a function that retrieves the NFT IDs associated with a given account:
+
+```cadence
+import "NonFungibleToken"
+import "FooBar"
+
+access(all) fun main(address: Address): [UInt64] {
+ let account = getAccount(address)
+
+ let collectionRef = account.capabilities.borrow<&{NonFungibleToken.Collection}>(
+ FooBar.CollectionPublicPath
+ ) ?? panic("The account ".concat(address.toString()).concat(" does not have a NonFungibleToken Collection at ")
+ .concat(FooBar.CollectionPublicPath.toString())
+ .concat(". The account must initialize their account with this collection first!"))
+
+ return collectionRef.getIDs()
+}
+```
+
+To check the NFTs associated with the `test-acct`, run the script (note: replace `0x123` with the address for `test-acct` from `flow.json`):
+
+```bash
+flow scripts execute cadence/scripts/get_foobar_ids.cdc 0x123
+```
+
+Since you haven't added any NFTs to the collection yet, the result will be an empty array.
+
+## Minting and Depositing an NFT to a Collection
+
+To mint and deposit an NFT into a collection, create a new transaction file:
+
+```bash
+flow generate transaction mint_foobar_nft
+```
+
+In this file, define a transaction that takes a recipient's address as an argument.
+This transaction will borrow the minting capability from the contract account,
+borrow the recipient's collection capability, create a new NFT using the minter,
+and deposit it into the recipient's collection:
+
+```cadence
+import "NonFungibleToken"
+import "FooBar"
+
+transaction(
+ recipient: Address
+) {
+
+ /// local variable for storing the minter reference
+ let minter: &FooBar.NFTMinter
+
+ /// Reference to the receiver's collection
+ let recipientCollectionRef: &{NonFungibleToken.Receiver}
+
+ prepare(signer: auth(BorrowValue) &Account) {
+
+ // borrow a reference to the NFTMinter resource in storage
+ self.minter = signer.storage.borrow<&FooBar.NFTMinter>(from: FooBar.MinterStoragePath)
+ ?? panic("The signer does not store a FooBar Collection object at the path "
+ .concat(FooBar.CollectionStoragePath.toString())
+ .concat("The signer must initialize their account with this collection first!"))
+
+ // Borrow the recipient's public NFT collection reference
+ self.recipientCollectionRef = getAccount(recipient).capabilities.borrow<&{NonFungibleToken.Receiver}>(
+ FooBar.CollectionPublicPath
+ ) ?? panic("The account ".concat(recipient.toString()).concat(" does not have a NonFungibleToken Receiver at ")
+ .concat(FooBar.CollectionPublicPath.toString())
+ .concat(". The account must initialize their account with this collection first!"))
+ }
+
+ execute {
+ // Mint the NFT and deposit it to the recipient's collection
+ let mintedNFT <- self.minter.createNFT()
+ self.recipientCollectionRef.deposit(token: <-mintedNFT)
+ }
+}
+```
+
+To run this transaction, use the Flow CLI. Remember, the contract account
+(which has the minting resource) should be the one signing the transaction.
+Pass the test account's address (from the `flow.json` file) as the recipient argument
+(note: replace `0x123` with the address for `test-acct` from `flow.json`):
+
+```bash
+flow transactions send cadence/transactions/mint_foobar_nft.cdc 0x123 --signer emulator-account --network emulator
+```
+
+After executing the transaction, you can run the earlier script to verify
+that the NFT was added to the `test-acct`'s collection (remember to replace `0x123`):
+
+```bash
+flow scripts execute cadence/scripts/get_foobar_ids.cdc 0x123
+```
+
+You should now see a value in the `test-acct`'s collection array!
+
+## Transferring an NFT to Another Account
+
+To transfer an NFT to another account, create a new transaction file using `generate`:
+
+```bash
+flow generate transaction transfer_foobar_nft
+```
+
+In this file, define a transaction that takes a recipient's address and the ID
+of the NFT you want to transfer as arguments.
+This transaction will borrow the sender's collection, get the recipient's capability,
+withdraw the NFT from the sender's collection, and deposit it into the recipient's collection:
+
+```cadence
+import "FooBar"
+import "NonFungibleToken"
+
+transaction(recipient: Address, withdrawID: UInt64) {
+
+ /// Reference to the withdrawer's collection
+ let withdrawRef: auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Collection}
+
+ /// Reference of the collection to deposit the NFT to
+ let receiverRef: &{NonFungibleToken.Receiver}
+
+ prepare(signer: auth(BorrowValue) &Account) {
+
+ // borrow a reference to the signer's NFT collection
+ self.withdrawRef = signer.storage.borrow(
+ from: FooBar.CollectionStoragePath
+ ) ?? panic("The signer does not store a FooBar Collection object at the path "
+ .concat(FooBar.CollectionStoragePath.toString())
+ .concat("The signer must initialize their account with this collection first!"))
+
+ // get the recipients public account object
+ let recipient = getAccount(recipient)
+
+ // borrow a public reference to the receivers collection
+ let receiverCap = recipient.capabilities.get<&{NonFungibleToken.Receiver}>(FooBar.CollectionPublicPath)
+
+ self.receiverRef = receiverCap.borrow()
+ ?? panic("The account ".concat(recipient.toString()).concat(" does not have a NonFungibleToken Receiver at ")
+ .concat(FooBar.CollectionPublicPath.toString())
+ .concat(". The account must initialize their account with this collection first!"))
+ }
+
+ execute {
+ let nft <- self.withdrawRef.withdraw(withdrawID: withdrawID)
+ self.receiverRef.deposit(token: <-nft)
+ }
+}
+```
+
+To transfer the NFT, first create a new account:
+
+```bash
+flow accounts create
+```
+
+Name it `test-acct-2` and select `Emulator` as the network. Next, create a collection for this new account:
+
+```bash
+flow transactions send cadence/transactions/setup_foobar_collection.cdc --signer test-acct-2 --network emulator
+```
+
+Now, run the transaction to transfer the NFT from `test-acct` to `test-acct-2`
+using the addresses from the `flow.json` file (replace `0x124` with `test-acct-2`'s address.
+Also note that `0` is the `id` of the `NFT` we'll be transferring):
+
+```bash
+flow transactions send cadence/transactions/transfer_foobar_nft.cdc 0x124 0 --signer test-acct --network emulator
+```
+
+To verify the transfer, you can run the earlier script for `test-acct-2` (replace `0x124`):
+
+```bash
+flow scripts execute cadence/scripts/get_foobar_ids.cdc 0x123
+```
+
+The transfer transaction also has a [generic version](https://github.com/onflow/flow-nft/blob/master/transactions/generic_transfer_with_address.cdc)
+that developers are encouraged to use!
+
+Congrats, you did it! You're now ready to launch the next fun NFT project on Flow.
+
+## More
+
+- Explore [an example NFT repository](https://github.com/nvdtf/flow-nft-scaffold/blob/main/cadence/contracts/exampleNFT/ExampleNFT.cdc)
+- Dive into the details of [the NFT Standard](https://github.com/onflow/flow-nft)
+- Check out the [`Burner` contract](../core-contracts/14-burner.md), which is the standard
+that all projects should use for handling the destruction of any resource.
+- For a deeper dive into `MetadataViews`, consult the [introduction guide](../advanced-concepts/metadata-views.md) or [the FLIP that introduced this feature](https://github.com/onflow/flips/blob/main/application/20210916-nft-metadata.md).
+- Use a [no code tool for creating NFT projects on Flow](https://www.touchstone.city/)
+
+
+=== build/guides/more-guides.mdx ===
+---
+title: More Guides
+description: Various guides for Flow
+sidebar_position: 5
+sidebar_custom_props:
+ icon: 🏟️
+---
+
+import DocCardList from '@theme/DocCardList';
+
+Explore an array of exciting, grassroots initiatives, and projects that thrive within the Flow Blockchain community, each contributing to the platform's growth and innovation.
+
+
+
+=== build/guides/fungible-token.md ===
+---
+title: Creating a Fungible Token
+description: Learn how to create and deploy a fungible token on Flow using Cadence. Follow this guide to implement the Flow Fungible Token standard, manage token minting, transfers, and vault management.
+sidebar_position: 6
+keywords:
+ - fungible token
+ - Flow token
+ - token standard
+ - smart contract
+ - Cadence
+ - token minting
+ - token transfers
+ - vault management
+ - Flow CLI
+ - token deployment
+ - FT standard
+ - token balance
+ - Flow development
+ - token contract
+ - blockchain tokens
+---
+
+:::info
+
+This guide is an in-depth tutorial on launching a Fungible Token contract from scratch. To launch in 2 minutes using a tool check out [Toucans](https://toucans.ecdao.org/)
+
+:::
+
+## What are Fungible Tokens?
+
+Fungible tokens are digital assets that are interchangeable and indistinguishable with other tokens of the same type. This means that each token is identical in specification to every other token in circulation. Think of them like traditional money; every dollar bill has the same value as every other dollar bill. Fungible tokens play a crucial role in web3 ecosystems, serving as both a means of payment and an incentive for network participation. They can take on various roles including currencies, structured financial instruments, shares of index funds, and even voting rights in decentralized autonomous organizations.
+
+## Vaults on Flow
+
+On the Flow blockchain and in the Cadence programming language,
+fungible tokens are stored in structures called resources.
+Resources are objects in Cadence that store data,
+but have special restrictions about how they can be stored and transferred,
+making them perfect for representing digital objects with real value.
+
+You can learn more about resources in the Cadence [documentation](https://cadence-lang.org/docs/language/resources)
+and [tutorials](https://cadence-lang.org/docs/tutorial/resources).
+
+For fungible tokens specifically, tokens are represented by a resource type called a `Vault`:
+
+```cadence
+access(all) resource interface Vault {
+
+ /// Field that tracks the balance of a vault
+ access(all) var balance: UFix64
+
+}
+```
+
+Think of a `Vault` as a digital piggy bank.
+Users who own fungible tokens store vault objects that track their balances
+directly in their account storage. This is opposed to languages
+that track user balances in a central ledger smart contract.
+
+When you transfer tokens from one vault to another:
+
+1. The transferor's vault creates a temporary vault holding the transfer amount.
+2. The original vault's balance decreases by the transfer amount.
+3. The recipient's vault receives the tokens from the temporary vault
+ and adds the temporary vault's balance to the its own balance.
+4. The temporary vault is then destroyed.
+
+This process ensures secure and accurate token transfers on the Flow blockchain.
+
+## Fungible Token Standard
+
+The [Fungible Token Standard](https://github.com/onflow/flow-ft) defines how a fungible token should behave on Flow.
+Wallets and other platforms need to recognize these tokens,
+so they adhere to a specific interface, which defines fields like balance,
+totalSupply, withdraw functionality, and more.
+This interface ensures that all fungible tokens on Flow have a consistent structure and behavior.
+Clink the link to the fungible token standard to see the full standard
+and learn about specific features and requirements.
+
+[Learn more about interfaces here](https://developers.flow.com/cadence/language/interfaces).
+
+## Setting Up a Project
+
+To start creating a Fungible Token on the Flow blockchain, you'll first need some tools and configurations in place.
+
+### Installing Flow CLI
+
+The **Flow CLI** (Command Line Interface) provides a suite of tools that allow developers to interact seamlessly with the Flow blockchain.
+
+If you haven't installed the Flow CLI yet and have [Homebrew](https://brew.sh/) installed,
+you can run `brew install flow-cli`. If you don't have Homebrew,
+please follow [the installation guide here](https://developers.flow.com/tools/flow-cli/install).
+
+### Initializing a New Project
+
+> 💡 Note: Here is [a link to the completed code](https://github.com/chasefleming/FooToken) if you want to skip ahead or reference as you follow along.
+
+Once you have the Flow CLI installed, you can set up a new project using the `flow init` command. This command initializes the necessary directory structure and a `flow.json` configuration file (a way to configure your project for contract sources, deployments, accounts, and more):
+
+```bash
+flow init FooToken
+```
+
+> Note: Select "No" when it asks you to install core contracts for the purposes of this tutorial.
+
+Upon execution, the command will generate the following directory structure:
+
+```
+/cadence
+ /contracts
+ /scripts
+ /transactions
+ /tests
+flow.json
+```
+
+Now, navigate into the project directory:
+
+```bash
+cd FooToken
+```
+
+In our configuration file, called `flow.json`, for the network we want to use,
+we are going to state the address the `FungibleToken` contract is deployed
+to via `aliases` in a new `contracts` section. Since it is a standard contract,
+it has already been deployed to the emulator, a tool that runs and emulates
+a local development version of the Flow Blockchain, for us.
+You can find addresses for other networks, like Testnet and Mainnet, on the [Fungible Token Standard repo](https://github.com/onflow/flow-ft).
+
+We'll also need to add the addresses for `ViewResolver`, `MetadataViews`,
+and `FungibleTokenMetadataViews`, which are other important contracts to use.
+These contracts are deployed to the Flow emulator by default,
+so there is not need to copy their code into your repo.
+The addresses below are the addresses in the emulator that your contract
+will import them from.
+
+```json
+"contracts": {
+ "FungibleToken": {
+ "aliases": {
+ "emulator": "0xee82856bf20e2aa6"
+ }
+ },
+ "FungibleTokenMetadataViews": {
+ "aliases": {
+ "emulator": "0xee82856bf20e2aa6"
+ }
+ },
+ "ViewResolver": {
+ "aliases": {
+ "emulator": "0xf8d6e0586b0a20c7"
+ }
+ },
+ "MetadataViews": {
+ "aliases": {
+ "emulator": "0xf8d6e0586b0a20c7"
+ }
+ }
+}
+```
+
+## Writing Our Token Contract
+
+Next let's create a `FooToken` contract at `cadence/contract/FooToken.cdc` using the boilerplate `generate` command from the Flow CLI:
+
+```bash
+flow generate contract FooToken
+```
+
+This will create a new file called `FooToken.cdc` in the `contracts` directory. Let's open it up and add some code.
+
+In this contract file, we want to import our `FungibleToken` contract that we've defined in `flow.json`.
+
+```cadence
+import "FungibleToken"
+```
+
+In this same file, let's create our contract which implements the `FungibleToken` contract interface (it does so by setting it following the `FooToken:`).
+We'll also include fields for standard storage and public paths
+for our resource definitions.
+In our `init` — which runs on the contract's first deployment and is used to set initial values — let's set an starting total supply of 1,000 tokens for this example.
+
+```cadence
+// ...previous code
+
+access(all) contract FooToken: FungibleToken {
+ access(all) var totalSupply: UFix64
+
+ access(all) let VaultStoragePath: StoragePath
+ access(all) let VaultPublicPath: PublicPath
+ access(all) let MinterStoragePath: StoragePath
+
+ init() {
+ self.totalSupply = 1000.0
+ self.VaultStoragePath = /storage/fooTokenVault
+ self.VaultPublicPath = /public/fooTokenVault
+ self.MinterStoragePath = /storage/fooTokenMinter
+ }
+}
+```
+
+### Creating a Vault
+
+Inside of this contract, we'll need to create a resource for a `Vault`.
+The `FungibleToken` standard requires that your vault implements the `FungibleToken.Vault` interface.
+This interface inherits from [many other interfaces](https://github.com/onflow/flow-ft/blob/master/contracts/FungibleToken.cdc#L140)
+which enforce different functionality that you can learn about in the standard.
+
+```cadence
+import "FungibleToken"
+
+access(all) contract FooToken: FungibleToken {
+ // ...totalSupply and path code
+
+ access(all) resource Vault: FungibleToken.Vault {
+
+ access(all) var balance: UFix64
+
+ init(balance: UFix64) {
+ self.balance = balance
+ }
+ }
+
+ // ...init code
+}
+```
+
+In order to give an account a vault, we need to create a function
+that creates a vault of our FooToken type and returns it to the account.
+This function takes a `vaultType: Type` argument that allows the caller
+to specify which type of `Vault` they want to create.
+Contracts that implement multiple `Vault` types can use this argument,
+but since your contract is only implementing one `Vault` type,
+it can ignore the argument.
+
+A simpler version of this function with no parameter
+should also be added to your `Vault` implementation.
+
+```cadence
+import "FungibleToken"
+
+access(all) contract FooToken: FungibleToken {
+ // ...other code
+
+ access(all) resource Vault: FungibleToken.Vault {
+
+ // ...other vault code
+
+ access(all) fun createEmptyVault(): @FooToken.Vault {
+ return <-create Vault(balance: 0.0)
+ }
+
+ // ...vault init code
+ }
+
+ // ...other code
+
+ access(all) fun createEmptyVault(vaultType: Type): @FooToken.Vault {
+ return <- create Vault(balance: 0.0)
+ }
+
+ // ...FooToken.init() code
+}
+```
+
+Inside our `Vault` resource, we also need a way to withdraw balances.
+To do that, we need to add a `withdraw()` function that returns a new vault
+with the transfer amount and decrements the existing balance.
+
+```cadence
+import "FungibleToken"
+
+access(all) contract FooToken: FungibleToken {
+
+ // ...previous code
+
+ access(all) resource Vault: FungibleToken.Vault {
+
+ // ...other vault code
+
+ access(FungibleToken.Withdraw) fun withdraw(amount: UFix64): @FooToken.Vault {
+ self.balance = self.balance - amount
+ return <-create Vault(balance: amount)
+ }
+
+ // ...vault init code
+ }
+
+ // ...additional code
+}
+```
+
+As you can see, this function has an `access(FungibleToken.Withdraw)` access modifier.
+This is an example of entitlements in Cadence.
+[Entitlements](https://cadence-lang.org/docs/language/access-control#entitlements)
+are a way for developers to restrict access to privileged fields and functions
+in a composite type like a resource when a reference is created for it.
+In this example, the `withdraw()` function is always accessible to code that
+controls the full `Vault` object, but if a reference is created for it,
+the `withdraw()` function can only be called if the reference
+is authorized by the owner with `FungibleToken.Withdraw`,
+which is [a standard entitlement](https://github.com/onflow/flow-ft/blob/master/contracts/FungibleToken.cdc#L53)
+defined by the FungibleToken contract:
+
+```cadence
+// Example of an authorized entitled reference to a FungibleToken.Vault
+
+```
+
+Entitlements are important to understand because they are what protects
+privileged functionality in your resource objects from being accessed by third-parties.
+It is recommended to read the [entitlements documentation](https://cadence-lang.org/docs/language/access-control#entitlements)
+to understand how to use the feature properly.
+
+[References](https://cadence-lang.org/docs/language/references) can be freely up-casted and down-casted in Cadence, so it is important
+for privileged functionality to be protected by an entitlement so that it can
+only be accessed if it is authorized.
+
+In addition to withdrawing, the vault also needs a way to deposit.
+We'll [typecast](https://cadence-lang.org/docs/language/operators#casting-operators)
+to make sure we are dealing with the correct token, update the vault balance,
+and destroy the vault. Add this code to your resource:
+
+```cadence
+import "FungibleToken"
+
+access(all) contract FooToken: FungibleToken {
+
+ // ...previous code
+
+ access(all) resource Vault: FungibleToken.Vault {
+
+ // ...other vault code
+
+ access(all) fun deposit(from: @{FungibleToken.Vault}) {
+ let vault <- from as! @FooToken.Vault
+ self.balance = self.balance + vault.balance
+ destroy vault
+ }
+
+ // ...vault init
+
+ }
+
+ // ...additional code
+}
+```
+
+Many projects rely on events the signal when withdrawals, deposits, or burns happen.
+Luckily, the `FungibleToken` standard handles the definition and emission
+of events for projects, so there is no need for you to add any events
+to your implementation for withdraw, deposit, and burn.
+
+Here are the `FungibleToken` event definitions:
+
+```cadence
+/// The event that is emitted when tokens are withdrawn from a Vault
+access(all) event Withdrawn(type: String, amount: UFix64, from: Address?, fromUUID: UInt64, withdrawnUUID: UInt64, balanceAfter: UFix64)
+
+/// The event that is emitted when tokens are deposited to a Vault
+access(all) event Deposited(type: String, amount: UFix64, to: Address?, toUUID: UInt64, depositedUUID: UInt64, balanceAfter: UFix64)
+
+/// Event that is emitted when the global burn method is called with a non-zero balance
+access(all) event Burned(type: String, amount: UFix64, fromUUID: UInt64)
+```
+
+These events are [emitted by the `Vault` interface](https://github.com/onflow/flow-ft/blob/master/contracts/FungibleToken.cdc#L198)
+in the `FungibleToken` contract whenever the relevant function is called on any implementation.
+
+One important piece to understand about the `Burned` event in particular
+is that in order for it to be emitted when a `Vault` is burned, it needs to
+be burnt via [the `Burner` contract's `burn()` method](https://github.com/onflow/flow-ft/blob/master/contracts/utility/Burner.cdc#L23).
+
+The [`Burner` contract](../core-contracts/14-burner.md) defines a standard
+that all projects should use for handling the destruction of any resource.
+It allows projects to define custom logic that can be executed when a resource is destroyed,
+like emitting events, or updating a field in the contract to show that the resource was destroyed.
+
+This will call the resource's `burnCallback()` function, which emits the event.
+You'll need to also add this function to your token contract now:
+
+```cadence
+import "FungibleToken"
+
+access(all) contract FooToken: FungibleToken {
+
+ // ...previous code
+
+ access(all) resource Vault: FungibleToken.Vault {
+
+ // ...other vault code
+
+ /// Called when a fungible token is burned via the `Burner.burn()` method
+ access(contract) fun burnCallback() {
+ if self.balance > 0.0 {
+ FooToken.totalSupply = FooToken.totalSupply - self.balance
+ }
+ self.balance = 0.0
+ }
+
+ // ...vault init
+
+ }
+
+ // ...additional code
+}
+```
+
+If you ever need to destroy a `Vault` with a non-zero balance,
+you should destroy it via the `Burner.burn` method so this important function can be called.
+
+There are three other utility methods that need to be added to your `Vault`
+to get various information:
+
+```cadence
+import "FungibleToken"
+
+access(all) contract FooToken: FungibleToken {
+
+ // ...previous code
+
+ access(all) resource Vault: FungibleToken.Vault {
+
+ // ...other vault code
+
+ /// getSupportedVaultTypes optionally returns a list of vault types that this receiver accepts
+ access(all) view fun getSupportedVaultTypes(): {Type: Bool} {
+ let supportedTypes: {Type: Bool} = {}
+ supportedTypes[self.getType()] = true
+ return supportedTypes
+ }
+
+ /// Says if the Vault can receive the provided type in the deposit method
+ access(all) view fun isSupportedVaultType(type: Type): Bool {
+ return self.getSupportedVaultTypes()[type] ?? false
+ }
+
+ /// Asks if the amount can be withdrawn from this vault
+ access(all) view fun isAvailableToWithdraw(amount: UFix64): Bool {
+ return amount <= self.balance
+ }
+
+ // ...vault init
+
+ }
+
+ // ...additional code
+}
+```
+
+### Adding Support for Metadata Views
+
+The Fungible Token standard also enforces that implementations
+provide functionality to return a set of standard views about the tokens
+via the [ViewResolver](https://github.com/onflow/flow-nft/blob/master/contracts/ViewResolver.cdc)
+and [FungibleTokenMetadataViews](https://github.com/onflow/flow-ft/blob/master/contracts/FungibleTokenMetadataViews.cdc) definitions.
+(You will need to add these imports to your contract now)
+These provide developers with standard ways of representing metadata
+about a given token such as supply, token symbols, website links, and standard
+account paths and types that third-parties can access in a standard way.
+You can see the [metadata views documentation](../advanced-concepts/metadata-views.md)
+for a more thorough guide using a NFT contract as an example.
+
+For now, you can add this code to your contract to support the important metadata views:
+
+```cadence
+import "FungibleToken"
+
+// Add these imports
+import "MetadataViews"
+import "FungibleTokenMetadataViews"
+
+access(all) contract FooToken: FungibleToken {
+ // ...other code
+
+ access(all) view fun getContractViews(resourceType: Type?): [Type] {
+ return [
+ Type(),
+ Type(),
+ Type(),
+ Type()
+ ]
+ }
+
+ access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
+ switch viewType {
+ case Type():
+ return FungibleTokenMetadataViews.FTView(
+ ftDisplay: self.resolveContractView(resourceType: nil, viewType: Type()) as! FungibleTokenMetadataViews.FTDisplay?,
+ ftVaultData: self.resolveContractView(resourceType: nil, viewType: Type()) as! FungibleTokenMetadataViews.FTVaultData?
+ )
+ case Type():
+ let media = MetadataViews.Media(
+ file: MetadataViews.HTTPFile(
+ // Change this to your own SVG image
+ url: "https://assets.website-files.com/5f6294c0c7a8cdd643b1c820/5f6294c0c7a8cda55cb1c936_Flow_Wordmark.svg"
+ ),
+ mediaType: "image/svg+xml"
+ )
+ let medias = MetadataViews.Medias([media])
+ return FungibleTokenMetadataViews.FTDisplay(
+ // Change these to represent your own token
+ name: "Example Foo Token",
+ symbol: "EFT",
+ description: "This fungible token is used as an example to help you develop your next FT #onFlow.",
+ externalURL: MetadataViews.ExternalURL("https://developers.flow.com/build/guides/fungible-token"),
+ logos: medias,
+ socials: {
+ "twitter": MetadataViews.ExternalURL("https://twitter.com/flow_blockchain")
+ }
+ )
+ case Type():
+ return FungibleTokenMetadataViews.FTVaultData(
+ storagePath: self.VaultStoragePath,
+ receiverPath: self.VaultPublicPath,
+ metadataPath: self.VaultPublicPath,
+ receiverLinkedType: Type<&FooToken.Vault>(),
+ metadataLinkedType: Type<&FooToken.Vault>(),
+ createEmptyVaultFunction: (fun(): @{FungibleToken.Vault} {
+ return <-FooToken.createEmptyVault(vaultType: Type<@FooToken.Vault>())
+ })
+ )
+ case Type():
+ return FungibleTokenMetadataViews.TotalSupply(
+ totalSupply: FooToken.totalSupply
+ )
+ }
+ return nil
+ }
+
+ // ...other code
+
+ access(all) resource Vault: FungibleToken.Vault {
+
+ // ...other vault code
+
+ access(all) view fun getViews(): [Type] {
+ return FooToken.getContractViews(resourceType: nil)
+ }
+
+ access(all) fun resolveView(_ view: Type): AnyStruct? {
+ return FooToken.resolveContractView(resourceType: nil, viewType: view)
+ }
+
+ // ...other vault code
+ }
+
+ // ...other FooToken code
+}
+```
+
+### Creating a Minter
+
+Let's create a minter resource which is used to mint vaults that have tokens in them. We can keep track of tokens we are minting with totalSupply
+
+If we want the ability to create new tokens, we'll need a way to mint them. To do that, let's create another resource on the `FooToken` contract. This will have a `mintToken`function which can increase the total supply of the token.
+
+```cadence
+import "FungibleToken"
+import "MetadataViews"
+import "FungibleTokenMetadataViews"
+
+access(all) contract FooToken: FungibleToken {
+
+ // ...additional contract code
+
+ // Add this event
+ access(all) event TokensMinted(amount: UFix64, type: String)
+
+ /// Minter
+ ///
+ /// Resource object that token admin accounts can hold to mint new tokens.
+ ///
+ access(all) resource Minter {
+ /// mintTokens
+ ///
+ /// Function that mints new tokens, adds them to the total supply,
+ /// and returns them to the calling context.
+ ///
+ access(all) fun mintTokens(amount: UFix64): @FooToken.Vault {
+ FooToken.totalSupply = FooToken.totalSupply + amount
+ let vault <-create Vault(balance: amount)
+ emit TokensMinted(amount: amount, type: vault.getType().identifier)
+ return <-vault
+ }
+ }
+
+ // ...additional contract code
+}
+```
+
+We also want to decide which account/s we want to give this ability to.
+In our example, we'll give it to the account where the contract is deployed.
+We can set this in the contract init function below the setting of total supply
+so that when the contract is created the minter is stored on the same account.
+
+```cadence
+import "FungibleToken"
+import "MetadataViews"
+import "FungibleTokenMetadataViews"
+
+access(all) contract FooToken: FungibleToken {
+
+ // ...additional contract code
+
+ init() {
+ self.totalSupply = 1000.0 // existed before
+ self.account.save(<- create Minter(), to: self.MinterStoragePath)
+ }
+}
+```
+
+After each of these steps, your `FooToken.cdc` contract file should now look like this:
+
+```cadence
+import "FungibleToken"
+import "MetadataViews"
+import "FungibleTokenMetadataViews"
+
+access(all) contract FooToken: FungibleToken {
+
+ /// The event that is emitted when new tokens are minted
+ access(all) event TokensMinted(amount: UFix64, type: String)
+
+ /// Total supply of FooTokens in existence
+ access(all) var totalSupply: UFix64
+
+ /// Storage and Public Paths
+ access(all) let VaultStoragePath: StoragePath
+ access(all) let VaultPublicPath: PublicPath
+ access(all) let ReceiverPublicPath: PublicPath
+ access(all) let MinterStoragePath: StoragePath
+
+ access(all) view fun getContractViews(resourceType: Type?): [Type] {
+ return [
+ Type(),
+ Type(),
+ Type(),
+ Type()
+ ]
+ }
+
+ access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
+ switch viewType {
+ case Type():
+ return FungibleTokenMetadataViews.FTView(
+ ftDisplay: self.resolveContractView(resourceType: nil, viewType: Type()) as! FungibleTokenMetadataViews.FTDisplay?,
+ ftVaultData: self.resolveContractView(resourceType: nil, viewType: Type()) as! FungibleTokenMetadataViews.FTVaultData?
+ )
+ case Type():
+ let media = MetadataViews.Media(
+ file: MetadataViews.HTTPFile(
+ // Change this to your own SVG image
+ url: "https://assets.website-files.com/5f6294c0c7a8cdd643b1c820/5f6294c0c7a8cda55cb1c936_Flow_Wordmark.svg"
+ ),
+ mediaType: "image/svg+xml"
+ )
+ let medias = MetadataViews.Medias([media])
+ return FungibleTokenMetadataViews.FTDisplay(
+ // Change these to represent your own token
+ name: "Example Foo Token",
+ symbol: "EFT",
+ description: "This fungible token is used as an example to help you develop your next FT #onFlow.",
+ externalURL: MetadataViews.ExternalURL("https://developers.flow.com/build/guides/fungible-token"),
+ logos: medias,
+ socials: {
+ "twitter": MetadataViews.ExternalURL("https://twitter.com/flow_blockchain")
+ }
+ )
+ case Type():
+ return FungibleTokenMetadataViews.FTVaultData(
+ storagePath: self.VaultStoragePath,
+ receiverPath: self.VaultPublicPath,
+ metadataPath: self.VaultPublicPath,
+ receiverLinkedType: Type<&FooToken.Vault>(),
+ metadataLinkedType: Type<&FooToken.Vault>(),
+ createEmptyVaultFunction: (fun(): @{FungibleToken.Vault} {
+ return <-FooToken.createEmptyVault(vaultType: Type<@FooToken.Vault>())
+ })
+ )
+ case Type():
+ return FungibleTokenMetadataViews.TotalSupply(
+ totalSupply: FooToken.totalSupply
+ )
+ }
+ return nil
+ }
+
+ access(all) resource Vault: FungibleToken.Vault {
+
+ /// The total balance of this vault
+ access(all) var balance: UFix64
+
+ // initialize the balance at resource creation time
+ init(balance: UFix64) {
+ self.balance = balance
+ }
+
+ /// Called when a fungible token is burned via the `Burner.burn()` method
+ access(contract) fun burnCallback() {
+ if self.balance > 0.0 {
+ FooToken.totalSupply = FooToken.totalSupply - self.balance
+ }
+ self.balance = 0.0
+ }
+
+ access(all) view fun getViews(): [Type] {
+ return FooToken.getContractViews(resourceType: nil)
+ }
+
+ access(all) fun resolveView(_ view: Type): AnyStruct? {
+ return FooToken.resolveContractView(resourceType: nil, viewType: view)
+ }
+
+ access(all) view fun getSupportedVaultTypes(): {Type: Bool} {
+ let supportedTypes: {Type: Bool} = {}
+ supportedTypes[self.getType()] = true
+ return supportedTypes
+ }
+
+ access(all) view fun isSupportedVaultType(type: Type): Bool {
+ return self.getSupportedVaultTypes()[type] ?? false
+ }
+
+ access(all) view fun isAvailableToWithdraw(amount: UFix64): Bool {
+ return amount <= self.balance
+ }
+
+ access(FungibleToken.Withdraw) fun withdraw(amount: UFix64): @FooToken.Vault {
+ self.balance = self.balance - amount
+ return <-create Vault(balance: amount)
+ }
+
+ access(all) fun deposit(from: @{FungibleToken.Vault}) {
+ let vault <- from as! @FooToken.Vault
+ self.balance = self.balance + vault.balance
+ vault.balance = 0.0
+ destroy vault
+ }
+
+ access(all) fun createEmptyVault(): @FooToken.Vault {
+ return <-create Vault(balance: 0.0)
+ }
+ }
+
+ access(all) resource Minter {
+ /// mintTokens
+ ///
+ /// Function that mints new tokens, adds them to the total supply,
+ /// and returns them to the calling context.
+ ///
+ access(all) fun mintTokens(amount: UFix64): @FooToken.Vault {
+ FooToken.totalSupply = FooToken.totalSupply + amount
+ let vault <-create Vault(balance: amount)
+ emit TokensMinted(amount: amount, type: vault.getType().identifier)
+ return <-vault
+ }
+ }
+
+ access(all) fun createEmptyVault(vaultType: Type): @FooToken.Vault {
+ return <- create Vault(balance: 0.0)
+ }
+
+ init() {
+ self.totalSupply = 1000.0
+
+ self.VaultStoragePath = /storage/fooTokenVault
+ self.VaultPublicPath = /public/fooTokenVault
+ self.MinterStoragePath = /storage/fooTokenMinter
+
+ // Create the Vault with the total supply of tokens and save it in storage
+ //
+ let vault <- create Vault(balance: self.totalSupply)
+ emit TokensMinted(amount: vault.balance, type: vault.getType().identifier)
+ self.account.storage.save(<-vault, to: self.VaultStoragePath)
+
+ // Create a public capability to the stored Vault that exposes
+ // the `deposit` method and getAcceptedTypes method through the `Receiver` interface
+ // and the `balance` method through the `Balance` interface
+ //
+ let fooTokenCap = self.account.capabilities.storage.issue<&FooToken.Vault>(self.VaultStoragePath)
+ self.account.capabilities.publish(fooTokenCap, at: self.VaultPublicPath)
+
+ let minter <- create Minter()
+ self.account.storage.save(<-minter, to: self.MinterStoragePath)
+ }
+}
+```
+
+## Deploying the Contract
+
+In order to use the contract, we need to deploy it to the network we want to use it on.
+In our case we are going to deploy it to emulator while developing.
+
+Back in our `flow.json`, let's add our `FooToken` to the `contracts` after `FungibleToken` with the path of the source code:
+
+```json
+"FooToken": "cadence/contracts/FooToken.cdc"
+```
+
+Let's also add a new `deployments` section to `flow.json` with the network
+we want to deploy it to, `emulator`, the account we want it deployed to `emulator-account`,
+and the list of contracts we want deployed in the array.
+
+```json
+"deployments": {
+ "emulator": {
+ "emulator-account": ["FooToken"]
+ }
+}
+```
+
+Next, using the Flow CLI, we will start the emulator. As mentioned,
+this will give us a local development environment for the Flow Blockchain.
+
+```bash
+flow emulator start
+```
+
+Open a new terminal and run the following to deploy your project:
+
+```bash
+flow project deploy
+```
+
+Congrats, you've deployed your contract to the Flow Blockchain emulator.
+To read more about deploying your project to other environments,
+see the [CLI docs](https://developers.flow.com/tools/flow-cli/deployment/deploy-project-contracts).
+
+## Reading the Token's Total Supply
+
+Let's now check that our total supply was initialized with 1,000 FooTokens. Go ahead and create a script called `get_total_supply.cdc` using the `generate` command.
+
+```bash
+flow generate script get_total_supply
+```
+
+In `cadence/scripts/get_total_supply.cdc` (which was just created), let's add this code which will log the `totalSupply` value from the `FooToken` contract:
+
+```cadence
+import "FooToken"
+
+access(all) fun main(): UFix64 {
+ return FooToken.totalSupply
+}
+```
+
+To run this using the CLI, enter this in your terminal:
+
+```bash
+flow scripts execute cadence/scripts/get_total_supply.cdc
+```
+
+In the terminal where you started the emulator, you should see `Result: 1000.0`
+
+To learn more about running scripts using Flow CLI, [see the docs](https://developers.flow.com/tools/flow-cli/scripts/execute-scripts).
+
+## Giving Accounts the Ability to Receive Tokens
+
+On Flow, newly created accounts cannot receive arbitrary assets.
+They need to be initialized to receive resources.
+In our case, we want to give accounts tokens and we'll need to create
+a `Vault` (which acts as a receiver) on each account that we want
+to have the ability to receive tokens. To do this, we'll need to run a transaction
+which will create the vault and set it in their storage
+using the `createEmptyVault()` function we created earlier on the contract.
+
+Let's first create the file at `cadence/transactions/setup_ft_account.cdc` using the `generate` command:
+
+```bash
+flow generate transaction setup_ft_account
+```
+
+Then add this code to it.
+This will call the `createEmptyVault` function, save it in storage,
+and create a capability for the vault which will later allow us to read from it
+(To learn more about capabilities, see [the Cadence docs here](https://developers.flow.com/cadence/language/capabilities)).
+
+```cadence
+import "FungibleToken"
+import "FooToken"
+
+transaction () {
+
+ prepare(signer: auth(BorrowValue, IssueStorageCapabilityController, PublishCapability, SaveValue) &Account) {
+
+ // Return early if the account already stores a FooToken Vault
+ if signer.storage.borrow<&FooToken.Vault>(from: FooToken.VaultStoragePath) != nil {
+ return
+ }
+
+ let vault <- FooToken.createEmptyVault(vaultType: Type<@FooToken.Vault>())
+
+ // Create a new FooToken Vault and put it in storage
+ signer.storage.save(<-vault, to: FooToken.VaultStoragePath)
+
+ // Create a public capability to the Vault that exposes the Vault interfaces
+ let vaultCap = signer.capabilities.storage.issue<&FooToken.Vault>(
+ FooToken.VaultStoragePath
+ )
+ signer.capabilities.publish(vaultCap, at: FooToken.VaultPublicPath)
+ }
+}
+```
+
+There are also examples of [generic transactions](https://github.com/onflow/flow-ft/blob/master/transactions/metadata/setup_account_from_address.cdc)
+that you can use to setup an account for ANY fungible token using metadata views!
+You should check those out and try to use generic transactions whenever it is possible.
+
+Next let's create a new emulator account using the CLI. We'll use this account to create a new vault and mint tokens into it. Run:
+
+```bash
+flow accounts create
+```
+
+Let's call it `test-acct` and select "Emulator" for the network:
+
+```bash
+test-acct
+```
+
+This will have added a new account, called `test-acct` to your `flow.json`.
+
+To call our setup account transaction from the CLI, we'll run the following:
+
+```bash
+flow transactions send ./cadence/transactions/setup_ft_account.cdc --signer test-acct --network emulator
+```
+
+To learn more about running transactions using CLI, [see the docs](https://developers.flow.com/tools/flow-cli/transactions/send-transactions).
+
+## Reading a Vault's Balance
+
+Let's now read the balance of the newly created account (`test-acct`) to check it's zero.
+
+Create this new script file `cadence/scripts/get_footoken_balance.cdc`:
+
+```bash
+flow generate script get_footoken_balance
+```
+
+Add this code which attempts to borrow the capability from the account requested and logs the vault balance if permitted:
+
+```cadence
+import "FungibleToken"
+import "FooToken"
+import "FungibleTokenMetadataViews"
+
+access(all) fun main(address: Address): UFix64 {
+ let vaultData = FooToken.resolveContractView(resourceType: nil, viewType: Type()) as! FungibleTokenMetadataViews.FTVaultData?
+ ?? panic("Could not get FTVaultData view for the FooToken contract")
+
+ return getAccount(address).capabilities.borrow<&{FungibleToken.Balance}>(
+ vaultData.metadataPath
+ )?.balance
+ ?? panic("Could not borrow a reference to the FooToken Vault in account "
+ .concat(address.toString()).concat(" at path ").concat(vaultData.metadataPath.toString())
+ .concat(". Make sure you are querying an address that has an FooToken Vault set up properly."))
+}
+```
+
+To run this script using the CLI, enter the following in your terminal.
+Note: you'll need to replace `123` with the address created by CLI
+in your `flow.json` for the `test-acct` address.
+
+```bash
+flow scripts execute cadence/scripts/get_footoken_balance.cdc 123 // change "123" to test-acct address
+```
+
+You should see a balance of zero logged.
+
+## Minting More Tokens
+
+Now that we have an account with a vault, let's mint some tokens into it
+using the Minter we created on the contract account.
+
+To do this, let's create a new transaction file `cadence/transactions/mint_footoken.cdc`:
+
+```bash
+flow generate transaction mint_footoken
+```
+
+Next, let's add the following code to the `mint_footoken.cdc` file.
+This code will attempt to borrow the minting capability
+and mint 20 new tokens into the receivers account.
+
+```cadence
+import "FungibleToken"
+import "FooToken"
+
+transaction(recipient: Address, amount: UFix64) {
+
+ /// Reference to the Example Token Minter Resource object
+ let tokenMinter: &FooToken.Minter
+
+ /// Reference to the Fungible Token Receiver of the recipient
+ let tokenReceiver: &{FungibleToken.Receiver}
+
+ prepare(signer: auth(BorrowValue) &Account) {
+
+ // Borrow a reference to the admin object
+ self.tokenMinter = signer.storage.borrow<&FooToken.Minter>(from: FooToken.MinterStoragePath)
+ ?? panic("Cannot mint: Signer does not store the FooToken Minter in their account!")
+
+ self.tokenReceiver = getAccount(recipient).capabilities.borrow<&{FungibleToken.Receiver}>(FooToken.VaultPublicPath)
+ ?? panic("Could not borrow a Receiver reference to the FungibleToken Vault in account "
+ .concat(recipient.toString()).concat(" at path ").concat(FooToken.VaultPublicPath.toString())
+ .concat(". Make sure you are sending to an address that has ")
+ .concat("a FungibleToken Vault set up properly at the specified path."))
+ }
+
+ execute {
+
+ // Create mint tokens
+ let mintedVault <- self.tokenMinter.mintTokens(amount: amount)
+
+ // Deposit them to the receiever
+ self.tokenReceiver.deposit(from: <-mintedVault)
+ }
+}
+```
+
+To run this transaction, enter this in your terminal.
+Note: `123` should be replaced with address of `test-acct` found in your `flow.json`.
+This command also states to sign with our `emulator-account` on the Emulator network.
+
+```bash
+flow transactions send ./cadence/transactions/mint_footoken.cdc 123 20.0 --signer emulator-account --network emulator
+```
+
+Let's go ahead and read the vault again. Remember to replace `123` with the correct address.
+
+```bash
+flow scripts execute cadence/scripts/get_footoken_balance.cdc 123
+```
+
+It should now say 20 tokens are in the vault.
+
+## Transferring Tokens Between Accounts
+
+The final functionality we'll add is the ability to transfer tokens from one account to another.
+
+To do that, create a new `cadence/transactions/transfer_footoken.cdc` transaction file:
+
+```bash
+flow generate transaction transfer_footoken
+```
+
+Let's add the code which states that the signer of the transaction
+will withdraw from their vault and put it into the receiver's vault
+which will be passed as a transaction argument.
+
+```cadence
+import "FungibleToken"
+import "FooToken"
+
+transaction(to: Address, amount: UFix64) {
+
+ // The Vault resource that holds the tokens that are being transferred
+ let sentVault: @{FungibleToken.Vault}
+
+ prepare(signer: auth(BorrowValue) &Account) {
+
+ // Get a reference to the signer's stored vault
+ let vaultRef = signer.storage.borrow(from: FooToken.VaultStoragePath)
+ ?? panic("The signer does not store an FooToken.Vault object at the path "
+ .concat(FooToken.VaultStoragePath.toString())
+ .concat(". The signer must initialize their account with this vault first!"))
+
+ // Withdraw tokens from the signer's stored vault
+ self.sentVault <- vaultRef.withdraw(amount: amount)
+ }
+
+ execute {
+
+ // Get the recipient's public account object
+ let recipient = getAccount(to)
+
+ // Get a reference to the recipient's Receiver
+ let receiverRef = recipient.capabilities.borrow<&{FungibleToken.Receiver}>(FooToken.VaultPublicPath)
+ ?? panic("Could not borrow a Receiver reference to the FooToken Vault in account "
+ .concat(recipient.toString()).concat(" at path ").concat(FooToken.VaultPublicPath.toString())
+ .concat(". Make sure you are sending to an address that has ")
+ .concat("a FooToken Vault set up properly at the specified path."))
+
+ // Deposit the withdrawn tokens in the recipient's receiver
+ receiverRef.deposit(from: <-self.sentVault)
+ }
+}
+```
+
+To send our tokens, we'll need to create a new account to send them to. Let's make one more account on emulator. Run:
+
+```bash
+flow accounts create
+```
+
+And pick the name:
+
+```bash
+test-acct-2
+```
+
+Make sure to select Emulator as the network.
+
+Don't forget the new account will need a vault added, so let's run the following transaction to add one:
+
+```bash
+flow transactions send ./cadence/transactions/setup_ft_account.cdc --signer test-acct-2 --network emulator
+```
+
+Now, let's send 1 token from our earlier account to the new account. Remember to replace `123` with account address of `test-acct-2`.
+
+```bash
+flow transactions send ./cadence/transactions/transfer_footoken.cdc 123 1.0 --signer test-acct --network emulator
+```
+
+After that, read the balance of `test-acct-2` (replace the address `123`).
+
+```bash
+flow scripts execute cadence/scripts/get_footoken_balance.cdc 123
+```
+
+You should now see 1 token in `test-acct-2` account!
+
+The transfer transaction also has a [generic version](https://github.com/onflow/flow-ft/blob/master/transactions/generic_transfer_with_address.cdc) that developers are encouraged to use!
+
+## More
+
+- [View a repo of this example code](https://github.com/chasefleming/FooToken)
+- [Review an `ExampleToken` contract implementing all of the remaining FungibleToken interface](https://github.com/onflow/flow-ft/blob/master/contracts/ExampleToken.cdc)
+- [View the Flow Token Standard](https://github.com/onflow/flow-ft/blob/master/contracts/FungibleToken.cdc)
+
+
+=== build/guides/account-linking-with-dapper.md ===
+---
+title: Account Linking With NBA Top Shot
+description: Use Account Linking between the Dapper Wallet and Flow Wallet to effortlessly use NBA Top Shot Moments in your app.
+sidebar_position: 5
+sidebar_custom_props:
+ icon: ⛓️
+keywords:
+ - NBA Top Shot
+ - Dapper Wallet
+ - account linking
+ - Flow wallet
+ - NFT integration
+ - Moments NFTs
+ - wallet connection
+ - Flow dApp
+ - blockchain integration
+ - smart contracts
+ - wallet management
+ - NFT display
+ - Flow development
+ - wallet interoperability
+ - asset management
+---
+
+# Account Linking With NBA Top Shot
+
+[Account Linking] is a powerful Flow feature that allows users to connect their wallets, enabling linked wallets to view and manage assets in one wallet with another. This feature helps reduce or even eliminate the challenges posed by other account abstraction solutions, which often lead to multiple isolated wallets and fragmented assets.
+
+In this tutorial, you'll build a [simple onchain app] that allows users to sign into your app with their Flow wallet and view [NBA Top Shot] Moments that reside in their [Dapper Wallet] - without those users needing to sign in with Dapper.
+
+## Objectives
+
+After completing this guide, you'll be able to:
+
+* Pull your users' NBA Top Shot Moments into your Flow app without needing to transfer them out of their Dapper wallet
+* Retrieve and list all NFT collections in any child wallet linked to a given Flow address
+* Write a [Cadence] script to iterate through the storage of a Flow wallet to find NFT collections
+* Run Cadence Scripts from the frontend
+
+## Prerequisites
+
+### Next.js and Modern Frontend Development
+
+This tutorial uses [Next.js]. You don't need to be an expert, but it's helpful to be comfortable with development using a current React framework. You'll be on your own to select and use a package manager, manage Node versions, and other frontend environment tasks. If you don't have your own preference, you can just follow along with us and use [Yarn].
+
+### Flow Wallet
+
+You'll need a [Flow Wallet], but you don't need to deposit any funds.
+
+## Moments NFTs
+
+You'll need a [Dapper Wallet] containing some Moments NFTs, such as [NBA Top Shot] Moments.
+
+## Getting Started
+
+This tutorial will use a [Next.js] project as the foundation of the frontend. Create a new project with:
+
+```zsh
+npx create-next-app@latest
+```
+
+We will be using TypeScript and the App Router, in this tutorial.
+
+Open your new project in the editor of your choice, install dependencies, and run the project.
+
+```zsh
+yarn install
+yarn run dev
+```
+
+If everything is working properly, you'll be able to navigate to `localhost:3000` and see the default [Next.js] page.
+
+## Flow Cadence Setup
+
+You'll need a few more dependencies to efficiently work with Cadence inside of your app.
+
+### Flow CLI and Types
+
+The [Flow CLI] contains a number of command-line tools for interacting with the Flow ecosystem. If you don't already have it installed, you can add it with Brew (or using [other installation methods]):
+
+```zsh
+brew install flow-cli
+```
+
+Once it's installed, you'll need to initialize Flow in your Next.js project. From the root, run:
+
+```zsh
+flow init --config-only
+```
+
+The `--config-only` flag [initializes a project] with the just the config file. This allows the Flow CLI to interact with your project without adding any unnecessary files.
+
+Next, you'll need to do a little bit of config work so that your project knows how to read Cadence files. Install the Flow Cadence Plugin:
+
+```zsh
+yarn add flow-cadence-plugin --dev
+```
+
+Finally, open `next.config.ts` and update it to use the plugin with Raw Loader:
+
+```tsx
+// next.config.ts
+import type { NextConfig } from "next";
+import FlowCadencePlugin from "flow-cadence-plugin";
+
+const nextConfig: NextConfig = {
+ webpack: (config) => {
+ config.plugins.push(new FlowCadencePlugin())
+
+ return config;
+ },
+};
+
+export default nextConfig;
+```
+
+## Frontend Setup
+
+We'll use the Flow Client Library [FCL] to manage blockchain interaction from the frontend. It's similar to viem, ethers, or web3.js, but works with the Flow blockchain and transactions and scripts written in Cadence.
+
+```zsh
+yarn add @onflow/fcl
+```
+
+Go ahead and install `dotenv` as well:
+
+```
+yarn add dotenv
+```
+
+### Provider Setup
+
+A fair amount of boilerplate code is needed to set up your provider. We'll provide it, but since it's not the purpose of this tutorial, we'll be brief on explanations. For more details, check out the [App Quickstart Guide].
+
+Add `app/providers/AuthProvider.tsx`:
+
+```tsx
+'use client';
+/* eslint-disable @typescript-eslint/no-explicit-any */
+
+import { createContext, useContext, ReactNode } from 'react';
+import useCurrentUser from '../hooks/use-current-user.hook';
+
+interface State {
+ user: any;
+ loggedIn: any;
+ logIn: any;
+ logOut: any;
+}
+
+const AuthContext = createContext