github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/cmd/util/ledger/migrations/change_contract_code_migration.go (about)

     1  package migrations
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/onflow/cadence/runtime/common"
     7  	coreContracts "github.com/onflow/flow-core-contracts/lib/go/contracts"
     8  	"github.com/rs/zerolog"
     9  
    10  	"github.com/onflow/flow-go/cmd/util/ledger/reporters"
    11  	evm "github.com/onflow/flow-go/fvm/evm/stdlib"
    12  	"github.com/onflow/flow-go/fvm/systemcontracts"
    13  	"github.com/onflow/flow-go/model/flow"
    14  )
    15  
    16  func NewSystemContractChange(
    17  	systemContract systemcontracts.SystemContract,
    18  	newContractCode []byte,
    19  ) StagedContract {
    20  	return StagedContract{
    21  		Address: common.Address(systemContract.Address),
    22  		Contract: Contract{
    23  			Name: systemContract.Name,
    24  			Code: newContractCode,
    25  		},
    26  	}
    27  }
    28  
    29  type EVMContractChange uint8
    30  
    31  const (
    32  	EVMContractChangeNone EVMContractChange = iota
    33  	EVMContractChangeDeploy
    34  	EVMContractChangeUpdate
    35  )
    36  
    37  type BurnerContractChange uint8
    38  
    39  const (
    40  	BurnerContractChangeNone BurnerContractChange = iota
    41  	BurnerContractChangeDeploy
    42  	BurnerContractChangeUpdate
    43  )
    44  
    45  func BurnerAddressForChain(chainID flow.ChainID) flow.Address {
    46  
    47  	systemContracts := systemcontracts.SystemContractsForChain(chainID)
    48  	serviceAccountAddress := systemContracts.FlowServiceAccount.Address
    49  	fungibleTokenAddress := systemContracts.FungibleToken.Address
    50  
    51  	switch chainID {
    52  	case flow.Mainnet, flow.Testnet:
    53  		return fungibleTokenAddress
    54  
    55  	case flow.Emulator, flow.Localnet:
    56  		return serviceAccountAddress
    57  
    58  	default:
    59  		panic(fmt.Errorf("unsupported chain ID: %s", chainID))
    60  	}
    61  }
    62  
    63  func SystemContractChanges(chainID flow.ChainID, options SystemContractsMigrationOptions) []StagedContract {
    64  	systemContracts := systemcontracts.SystemContractsForChain(chainID)
    65  
    66  	env := systemContracts.AsTemplateEnv()
    67  	env.BurnerAddress = BurnerAddressForChain(chainID).Hex()
    68  
    69  	switch chainID {
    70  	case flow.Mainnet:
    71  		env.StakingCollectionAddress = "0x8d0e87b65159ae63"
    72  		env.StakingProxyAddress = "0x62430cf28c26d095"
    73  
    74  	case flow.Testnet:
    75  		env.StakingCollectionAddress = "0x95e019a17d0e23d7"
    76  		env.StakingProxyAddress = "0x7aad92e5a0715d21"
    77  
    78  	case flow.Emulator, flow.Localnet:
    79  		env.StakingCollectionAddress = env.ServiceAccountAddress
    80  		env.StakingProxyAddress = env.ServiceAccountAddress
    81  
    82  	default:
    83  		panic(fmt.Errorf("unsupported chain ID: %s", chainID))
    84  	}
    85  
    86  	env.LockedTokensAddress = env.StakingCollectionAddress
    87  
    88  	contractChanges := []StagedContract{
    89  		// epoch related contracts
    90  		NewSystemContractChange(
    91  			systemContracts.Epoch,
    92  			coreContracts.FlowEpoch(
    93  				env,
    94  			),
    95  		),
    96  		NewSystemContractChange(
    97  			systemContracts.IDTableStaking,
    98  			coreContracts.FlowIDTableStaking(
    99  				env,
   100  			),
   101  		),
   102  		NewSystemContractChange(
   103  			systemContracts.ClusterQC,
   104  			coreContracts.FlowQC(),
   105  		),
   106  		NewSystemContractChange(
   107  			systemContracts.DKG,
   108  			coreContracts.FlowDKG(),
   109  		),
   110  
   111  		// service account related contracts
   112  		NewSystemContractChange(
   113  			systemContracts.FlowServiceAccount,
   114  			coreContracts.FlowServiceAccount(
   115  				env,
   116  			),
   117  		),
   118  		NewSystemContractChange(
   119  			systemContracts.NodeVersionBeacon,
   120  			coreContracts.NodeVersionBeacon(),
   121  		),
   122  		NewSystemContractChange(
   123  			systemContracts.RandomBeaconHistory,
   124  			coreContracts.RandomBeaconHistory(),
   125  		),
   126  		NewSystemContractChange(
   127  			systemContracts.FlowStorageFees,
   128  			coreContracts.FlowStorageFees(
   129  				env,
   130  			),
   131  		),
   132  		{
   133  			Address: common.Address(flow.HexToAddress(env.StakingCollectionAddress)),
   134  			Contract: Contract{
   135  				Name: "FlowStakingCollection",
   136  				Code: coreContracts.FlowStakingCollection(env),
   137  			},
   138  		},
   139  		{
   140  			Address: common.Address(flow.HexToAddress(env.StakingProxyAddress)),
   141  			Contract: Contract{
   142  				Name: "StakingProxy",
   143  				Code: coreContracts.FlowStakingProxy(),
   144  			},
   145  		},
   146  		{
   147  			Address: common.Address(flow.HexToAddress(env.LockedTokensAddress)),
   148  			Contract: Contract{
   149  				Name: "LockedTokens",
   150  				Code: coreContracts.FlowLockedTokens(env),
   151  			},
   152  		},
   153  
   154  		// token related contracts
   155  		NewSystemContractChange(
   156  			systemContracts.FlowFees,
   157  			coreContracts.FlowFees(
   158  				env,
   159  			),
   160  		),
   161  		NewSystemContractChange(
   162  			systemContracts.FlowToken,
   163  			coreContracts.FlowToken(
   164  				env,
   165  			),
   166  		),
   167  		NewSystemContractChange(
   168  			systemContracts.FungibleToken,
   169  			coreContracts.FungibleToken(
   170  				env,
   171  			),
   172  		),
   173  		{
   174  			Address: common.Address(flow.HexToAddress(env.FungibleTokenMetadataViewsAddress)),
   175  			Contract: Contract{
   176  				Name: "FungibleTokenMetadataViews",
   177  				Code: coreContracts.FungibleTokenMetadataViews(env),
   178  			},
   179  		},
   180  
   181  		// NFT related contracts
   182  		NewSystemContractChange(
   183  			systemContracts.NonFungibleToken,
   184  			coreContracts.NonFungibleToken(
   185  				env,
   186  			),
   187  		),
   188  		NewSystemContractChange(
   189  			systemContracts.MetadataViews,
   190  			coreContracts.MetadataViews(
   191  				env,
   192  			),
   193  		),
   194  		NewSystemContractChange(
   195  			systemContracts.ViewResolver,
   196  			coreContracts.ViewResolver(),
   197  		),
   198  	}
   199  
   200  	switch chainID {
   201  	case flow.Emulator, flow.Localnet:
   202  		// skip
   203  
   204  	default:
   205  		contractChanges = append(
   206  			contractChanges,
   207  			StagedContract{
   208  				Address: common.Address(flow.HexToAddress(env.FungibleTokenSwitchboardAddress)),
   209  				Contract: Contract{
   210  					Name: "FungibleTokenSwitchboard",
   211  					Code: coreContracts.FungibleTokenSwitchboard(env),
   212  				},
   213  			},
   214  		)
   215  	}
   216  
   217  	// EVM contract
   218  	if options.EVM == EVMContractChangeUpdate {
   219  		contractChanges = append(
   220  			contractChanges,
   221  			NewSystemContractChange(
   222  				systemContracts.EVMContract,
   223  				evm.ContractCode(
   224  					systemContracts.NonFungibleToken.Address,
   225  					systemContracts.FungibleToken.Address,
   226  					systemContracts.FlowToken.Address,
   227  				),
   228  			),
   229  		)
   230  	}
   231  
   232  	// Burner contract
   233  	if options.Burner == BurnerContractChangeUpdate {
   234  		contractChanges = append(
   235  			contractChanges,
   236  			StagedContract{
   237  				Address: common.Address(flow.HexToAddress(env.BurnerAddress)),
   238  				Contract: Contract{
   239  					Name: "Burner",
   240  					Code: coreContracts.Burner(),
   241  				},
   242  			},
   243  		)
   244  	}
   245  
   246  	return contractChanges
   247  }
   248  
   249  type SystemContractsMigrationOptions struct {
   250  	StagedContractsMigrationOptions
   251  	EVM    EVMContractChange
   252  	Burner BurnerContractChange
   253  }
   254  
   255  func NewSystemContractsMigration(
   256  	log zerolog.Logger,
   257  	rwf reporters.ReportWriterFactory,
   258  	options SystemContractsMigrationOptions,
   259  ) *StagedContractsMigration {
   260  	migration := NewStagedContractsMigration(
   261  		"SystemContractsMigration",
   262  		"system-contracts-migration",
   263  		log,
   264  		rwf,
   265  		options.StagedContractsMigrationOptions,
   266  	)
   267  	for _, change := range SystemContractChanges(options.ChainID, options) {
   268  		migration.registerContractChange(change)
   269  	}
   270  	return migration
   271  }