github.com/koko1123/flow-go-1@v0.29.6/fvm/systemcontracts/system_contracts.go (about) 1 // Package systemcontracts stores canonical address locations for all system 2 // smart contracts and service events. 3 // 4 // System contracts are special smart contracts controlled by the service account, 5 // a Flow account with special privileges to administer the network. 6 // 7 // Service events are special events defined within system contracts which 8 // are included within execution receipts and processed by the consensus committee 9 // to enable message-passing to the protocol state. 10 // 11 // For transient networks, all system contracts can be deployed to the service 12 // account. For long-lived networks, system contracts are spread across several 13 // accounts for historical reasons. 14 package systemcontracts 15 16 import ( 17 "fmt" 18 19 "github.com/koko1123/flow-go-1/model/flow" 20 ) 21 22 const ( 23 24 // Unqualified names of system smart contracts (not including address prefix) 25 26 ContractNameEpoch = "FlowEpoch" 27 ContractNameClusterQC = "FlowClusterQC" 28 ContractNameDKG = "FlowDKG" 29 ContractServiceAccount = "FlowServiceAccount" 30 ContractNameFlowFees = "FlowFees" 31 ContractStorageFees = "FlowStorageFees" 32 ContractDeploymentAudits = "FlowContractAudits" 33 34 // Unqualified names of service events (not including address prefix or contract name) 35 36 EventNameEpochSetup = "EpochSetup" 37 EventNameEpochCommit = "EpochCommit" 38 39 // Unqualified names of service event contract functions (not including address prefix or contract name) 40 41 ContractServiceAccountFunction_setupNewAccount = "setupNewAccount" 42 ContractServiceAccountFunction_defaultTokenBalance = "defaultTokenBalance" 43 ContractServiceAccountFunction_deductTransactionFee = "deductTransactionFee" 44 ContractServiceAccountFunction_verifyPayersBalanceForTransactionExecution = "verifyPayersBalanceForTransactionExecution" 45 ContractStorageFeesFunction_calculateAccountCapacity = "calculateAccountCapacity" 46 ContractStorageFeesFunction_getAccountsCapacityForTransactionStorageCheck = "getAccountsCapacityForTransactionStorageCheck" 47 ContractStorageFeesFunction_defaultTokenAvailableBalance = "defaultTokenAvailableBalance" 48 ContractDeploymentAuditsFunction_useVoucherForDeploy = "useVoucherForDeploy" 49 ) 50 51 // SystemContract represents a system contract on a particular chain. 52 type SystemContract struct { 53 Address flow.Address 54 Name string 55 } 56 57 // ServiceEvent represents a service event on a particular chain. 58 type ServiceEvent struct { 59 Address flow.Address 60 ContractName string 61 Name string 62 } 63 64 // QualifiedIdentifier returns the Cadence qualified identifier of the service 65 // event, which includes the contract name and the event type name. 66 func (se ServiceEvent) QualifiedIdentifier() string { 67 return fmt.Sprintf("%s.%s", se.ContractName, se.Name) 68 } 69 70 // EventType returns the full event type identifier, including the address, the 71 // contract name, and the event type name. 72 func (se ServiceEvent) EventType() flow.EventType { 73 return flow.EventType(fmt.Sprintf("A.%s.%s.%s", se.Address, se.ContractName, se.Name)) 74 } 75 76 // SystemContracts is a container for all system contracts on a particular chain. 77 type SystemContracts struct { 78 Epoch SystemContract 79 ClusterQC SystemContract 80 DKG SystemContract 81 } 82 83 // ServiceEvents is a container for all service events on a particular chain. 84 type ServiceEvents struct { 85 EpochSetup ServiceEvent 86 EpochCommit ServiceEvent 87 } 88 89 // All returns all service events as a slice. 90 func (se ServiceEvents) All() []ServiceEvent { 91 return []ServiceEvent{ 92 se.EpochSetup, 93 se.EpochCommit, 94 } 95 } 96 97 // SystemContractsForChain returns the system contract configuration for the given chain. 98 func SystemContractsForChain(chainID flow.ChainID) (*SystemContracts, error) { 99 addresses, ok := contractAddressesByChainID[chainID] 100 if !ok { 101 return nil, fmt.Errorf("unknown chain id (%s)", chainID.String()) 102 } 103 104 contracts := &SystemContracts{ 105 Epoch: SystemContract{ 106 Address: addresses[ContractNameEpoch], 107 Name: ContractNameEpoch, 108 }, 109 ClusterQC: SystemContract{ 110 Address: addresses[ContractNameClusterQC], 111 Name: ContractNameClusterQC, 112 }, 113 DKG: SystemContract{ 114 Address: addresses[ContractNameDKG], 115 Name: ContractNameDKG, 116 }, 117 } 118 119 return contracts, nil 120 } 121 122 // ServiceEventsForChain returns the service event confirmation for the given chain. 123 func ServiceEventsForChain(chainID flow.ChainID) (*ServiceEvents, error) { 124 addresses, ok := contractAddressesByChainID[chainID] 125 if !ok { 126 return nil, fmt.Errorf("unknown chain id (%s)", chainID.String()) 127 } 128 129 events := &ServiceEvents{ 130 EpochSetup: ServiceEvent{ 131 Address: addresses[ContractNameEpoch], 132 ContractName: ContractNameEpoch, 133 Name: EventNameEpochSetup, 134 }, 135 EpochCommit: ServiceEvent{ 136 Address: addresses[ContractNameEpoch], 137 ContractName: ContractNameEpoch, 138 Name: EventNameEpochCommit, 139 }, 140 } 141 142 return events, nil 143 } 144 145 // contractAddressesByChainID stores the default system smart contract 146 // addresses for each chain. 147 var contractAddressesByChainID map[flow.ChainID]map[string]flow.Address 148 149 // Well-known addresses for system contracts on long-running networks. 150 // For now, all system contracts tracked by this package are deployed to the same 151 // address (per chain) as the staking contract. 152 // 153 // Ref: https://docs.onflow.org/core-contracts/staking-contract-reference/ 154 var ( 155 // stakingContractAddressMainnet is the address of the FlowIDTableStaking contract on Mainnet 156 stakingContractAddressMainnet = flow.HexToAddress("8624b52f9ddcd04a") 157 // stakingContractAddressTestnet is the address of the FlowIDTableStaking contract on Testnet 158 stakingContractAddressTestnet = flow.HexToAddress("9eca2b38b18b5dfe") 159 ) 160 161 func init() { 162 contractAddressesByChainID = make(map[flow.ChainID]map[string]flow.Address) 163 164 // Main Flow network 165 // All system contracts are deployed to the account of the staking contract 166 mainnet := map[string]flow.Address{ 167 ContractNameEpoch: stakingContractAddressMainnet, 168 ContractNameClusterQC: stakingContractAddressMainnet, 169 ContractNameDKG: stakingContractAddressMainnet, 170 } 171 contractAddressesByChainID[flow.Mainnet] = mainnet 172 173 // Long-lived test networks 174 // All system contracts are deployed to the account of the staking contract 175 testnet := map[string]flow.Address{ 176 ContractNameEpoch: stakingContractAddressTestnet, 177 ContractNameClusterQC: stakingContractAddressTestnet, 178 ContractNameDKG: stakingContractAddressTestnet, 179 } 180 contractAddressesByChainID[flow.Testnet] = testnet 181 182 // Sandboxnet test network 183 // All system contracts are deployed to the service account 184 sandboxnet := map[string]flow.Address{ 185 ContractNameEpoch: flow.Sandboxnet.Chain().ServiceAddress(), 186 ContractNameClusterQC: flow.Sandboxnet.Chain().ServiceAddress(), 187 ContractNameDKG: flow.Sandboxnet.Chain().ServiceAddress(), 188 } 189 contractAddressesByChainID[flow.Sandboxnet] = sandboxnet 190 191 // Transient test networks 192 // All system contracts are deployed to the service account 193 transient := map[string]flow.Address{ 194 ContractNameEpoch: flow.Emulator.Chain().ServiceAddress(), 195 ContractNameClusterQC: flow.Emulator.Chain().ServiceAddress(), 196 ContractNameDKG: flow.Emulator.Chain().ServiceAddress(), 197 } 198 contractAddressesByChainID[flow.Emulator] = transient 199 contractAddressesByChainID[flow.Localnet] = transient 200 contractAddressesByChainID[flow.BftTestnet] = transient 201 contractAddressesByChainID[flow.Benchnet] = transient 202 203 }