diff --git a/fvm/blueprints/bridge.go b/fvm/blueprints/bridge.go new file mode 100644 index 00000000000..cefa474dd60 --- /dev/null +++ b/fvm/blueprints/bridge.go @@ -0,0 +1,290 @@ +package blueprints + +import ( + _ "embed" + + "github.com/onflow/cadence" + jsoncdc "github.com/onflow/cadence/encoding/json" + "github.com/onflow/flow-core-contracts/lib/go/templates" + + bridge "github.com/onflow/flow-evm-bridge" + + "github.com/onflow/flow-go/model/flow" +) + +var BridgeContracts = []string{ + "cadence/contracts/utils/ArrayUtils.cdc", + "cadence/contracts/utils/StringUtils.cdc", + "cadence/contracts/utils/ScopedFTProviders.cdc", + "cadence/contracts/utils/Serialize.cdc", + "cadence/contracts/utils/SerializeMetadata.cdc", + "cadence/contracts/bridge/interfaces/FlowEVMBridgeHandlerInterfaces.cdc", + "cadence/contracts/bridge/interfaces/IBridgePermissions.cdc", + "cadence/contracts/bridge/interfaces/ICrossVM.cdc", + "cadence/contracts/bridge/interfaces/ICrossVMAsset.cdc", + "cadence/contracts/bridge/interfaces/CrossVMNFT.cdc", + "cadence/contracts/bridge/interfaces/CrossVMToken.cdc", + "cadence/contracts/bridge/interfaces/IEVMBridgeNFTMinter.cdc", + "cadence/contracts/bridge/interfaces/IEVMBridgeTokenMinter.cdc", + "cadence/contracts/bridge/FlowEVMBridgeConfig.cdc", + "cadence/contracts/bridge/interfaces/IFlowEVMNFTBridge.cdc", + "cadence/contracts/bridge/interfaces/IFlowEVMTokenBridge.cdc", + "cadence/contracts/bridge/FlowEVMBridgeUtils.cdc", + "cadence/contracts/bridge/FlowEVMBridgeResolver.cdc", + "cadence/contracts/bridge/FlowEVMBridgeHandlers.cdc", + "cadence/contracts/bridge/FlowEVMBridgeNFTEscrow.cdc", + "cadence/contracts/bridge/FlowEVMBridgeTokenEscrow.cdc", + "cadence/contracts/bridge/FlowEVMBridgeTemplates.cdc", + "cadence/contracts/bridge/FlowEVMBridge.cdc", +} + +// CreateCOATransaction returns the transaction body for the create COA transaction +func CreateCOATransaction( + service flow.Address, + bridgeEnv bridge.Environment, + env templates.Environment, +) *flow.TransactionBody { + txScript, _ := bridge.GetCadenceTransactionCode("cadence/transactions/evm/create_account.cdc", bridgeEnv, env) + return flow.NewTransactionBody(). + SetScript([]byte( + txScript, + ), + ). + AddArgument(jsoncdc.MustEncode(cadence.UFix64(0.0))). + AddAuthorizer(service) +} + +// DeployEVMContractTransaction returns the transaction body for +// the deploy EVM contract transaction +func DeployEVMContractTransaction( + service flow.Address, + bytecode string, + gasLimit int, + deploymentValue float64, + bridgeEnv bridge.Environment, + env templates.Environment, +) *flow.TransactionBody { + txScript, _ := bridge.GetCadenceTransactionCode("cadence/transactions/evm/deploy.cdc", bridgeEnv, env) + return flow.NewTransactionBody(). + SetScript([]byte( + txScript, + ), + ). + AddArgument(jsoncdc.MustEncode(cadence.String(bytecode))). + AddArgument(jsoncdc.MustEncode(cadence.UInt64(gasLimit))). + AddArgument(jsoncdc.MustEncode(cadence.UFix64(deploymentValue))). + AddAuthorizer(service) +} + +// DeployFlowEVMBridgeUtilsContractTransaction returns the transaction body for +// the deploy FlowEVMBridgeUtils contract transaction +func DeployFlowEVMBridgeUtilsContractTransaction( + service flow.Address, + bridgeEnv *bridge.Environment, + env templates.Environment, + contract []byte, + contractName string, + factoryAddress string, +) *flow.TransactionBody { + txScript, _ := bridge.GetCadenceTransactionCode("cadence/transactions/bridge/admin/deploy_bridge_utils.cdc", *bridgeEnv, env) + return flow.NewTransactionBody(). + SetScript([]byte( + txScript, + ), + ). + AddArgument(jsoncdc.MustEncode(cadence.String(contractName))). + AddArgument(jsoncdc.MustEncode(cadence.String(contract))). + AddArgument(jsoncdc.MustEncode(cadence.String(factoryAddress))). + AddAuthorizer(service) +} + +// PauseBridgeTransaction returns the transaction body for the transaction +// to pause or unpause the VM bridge +func PauseBridgeTransaction( + service flow.Address, + bridgeEnv bridge.Environment, + env templates.Environment, + pause bool, +) *flow.TransactionBody { + txScript, _ := bridge.GetCadenceTransactionCode("cadence/transactions/bridge/admin/pause/update_bridge_pause_status.cdc", bridgeEnv, env) + return flow.NewTransactionBody(). + SetScript([]byte( + txScript, + ), + ). + AddArgument(jsoncdc.MustEncode(cadence.Bool(pause))). + AddAuthorizer(service) +} + +// SetRegistrarTransaction returns the transaction body for the transaction to set the factory as registrar +func SetRegistrarTransaction( + service flow.Address, + bridgeEnv bridge.Environment, + env templates.Environment, + registryAddress string, +) *flow.TransactionBody { + txScript, _ := bridge.GetCadenceTransactionCode("cadence/transactions/bridge/admin/evm/set_registrar.cdc", bridgeEnv, env) + return flow.NewTransactionBody(). + SetScript([]byte( + txScript, + ), + ). + AddArgument(jsoncdc.MustEncode(cadence.String(registryAddress))). + AddAuthorizer(service) +} + +// SetDeploymentRegistryTransaction returns the transaction body for the transaction +// to add the registry to the factory +func SetDeploymentRegistryTransaction( + service flow.Address, + bridgeEnv bridge.Environment, + env templates.Environment, + registryAddress string, +) *flow.TransactionBody { + txScript, _ := bridge.GetCadenceTransactionCode("cadence/transactions/bridge/admin/evm/set_deployment_registry.cdc", bridgeEnv, env) + return flow.NewTransactionBody(). + SetScript([]byte( + txScript, + ), + ). + AddArgument(jsoncdc.MustEncode(cadence.String(registryAddress))). + AddAuthorizer(service) +} + +// SetDelegatedDeployerTransaction returns the transaction body for the transaction +// to set a delegated deployer for a particular token type +func SetDelegatedDeployerTransaction( + service flow.Address, + bridgeEnv bridge.Environment, + env templates.Environment, + deployerAddress string, +) *flow.TransactionBody { + txScript, _ := bridge.GetCadenceTransactionCode("cadence/transactions/bridge/admin/evm/set_delegated_deployer.cdc", bridgeEnv, env) + return flow.NewTransactionBody(). + SetScript([]byte( + txScript, + ), + ). + AddArgument(jsoncdc.MustEncode(cadence.String(deployerAddress))). + AddAuthorizer(service) +} + +// AddDeployerTransaction returns the transaction body for the transaction +// to add a deployer for a particular token type +func AddDeployerTransaction( + service flow.Address, + bridgeEnv bridge.Environment, + env templates.Environment, + deployerTag, + deployerAddress string, +) *flow.TransactionBody { + txScript, _ := bridge.GetCadenceTransactionCode("cadence/transactions/bridge/admin/evm/add_deployer.cdc", bridgeEnv, env) + return flow.NewTransactionBody(). + SetScript([]byte( + txScript, + ), + ). + AddArgument(jsoncdc.MustEncode(cadence.String(deployerTag))). + AddArgument(jsoncdc.MustEncode(cadence.String(deployerAddress))). + AddAuthorizer(service) +} + +// DeployFlowEVMBridgeAccessorContractTransaction returns the transaction body for the deploy FlowEVMBridgeAccessor contract transaction +func DeployFlowEVMBridgeAccessorContractTransaction( + service flow.Address, + bridgeEnv bridge.Environment, + env templates.Environment, +) *flow.TransactionBody { + contract, _ := bridge.GetCadenceContractCode("cadence/contracts/bridge/FlowEVMBridgeAccessor.cdc", bridgeEnv, env) + contractName := "FlowEVMBridgeAccessor" + txScript, _ := bridge.GetCadenceTransactionCode("cadence/transactions/bridge/admin/deploy_bridge_accessor.cdc", bridgeEnv, env) + return flow.NewTransactionBody(). + SetScript([]byte( + txScript, + ), + ). + AddArgument(jsoncdc.MustEncode(cadence.String(contractName))). + AddArgument(jsoncdc.MustEncode(cadence.String(contract))). + AddArgument(jsoncdc.MustEncode(cadence.Address(service))). + AddAuthorizer(service) +} + +// IntegrateEVMWithBridgeAccessorTransaction returns the transaction body for the transaction +// that claims the bridge accessor capability and saves the bridge router +func IntegrateEVMWithBridgeAccessorTransaction( + service flow.Address, + bridgeEnv bridge.Environment, + env templates.Environment, +) *flow.TransactionBody { + txScript, _ := bridge.GetCadenceTransactionCode("cadence/transactions/bridge/admin/evm-integration/claim_accessor_capability_and_save_router.cdc", bridgeEnv, env) + return flow.NewTransactionBody(). + SetScript([]byte( + txScript, + ), + ). + AddArgument(jsoncdc.MustEncode(cadence.String("FlowEVMBridgeAccessor"))). + AddArgument(jsoncdc.MustEncode(cadence.Address(service))). + AddAuthorizer(service) +} + +// UpdateOnboardFeeTransaction returns the transaction body for the transaction +// that updates the onboarding fees for the bridge +func UpdateOnboardFeeTransaction( + service flow.Address, + bridgeEnv bridge.Environment, + env templates.Environment, + fee float64, +) *flow.TransactionBody { + txScript, _ := bridge.GetCadenceTransactionCode("cadence/transactions/bridge/admin/fee/update_onboard_fee.cdc", bridgeEnv, env) + return flow.NewTransactionBody(). + SetScript([]byte( + txScript, + ), + ). + AddArgument(jsoncdc.MustEncode(cadence.UFix64(fee))). + AddAuthorizer(service) +} + +// UpdateBaseFeeTransaction returns the transaction body for the transaction +// that updates the base fees for the bridge +func UpdateBaseFeeTransaction( + service flow.Address, + bridgeEnv bridge.Environment, + env templates.Environment, + fee float64, +) *flow.TransactionBody { + txScript, _ := bridge.GetCadenceTransactionCode("cadence/transactions/bridge/admin/fee/update_base_fee.cdc", bridgeEnv, env) + return flow.NewTransactionBody(). + SetScript([]byte( + txScript, + ), + ). + AddArgument(jsoncdc.MustEncode(cadence.UFix64(fee))). + AddAuthorizer(service) +} + +// UpsertContractCodeChunksTransaction returns the transaction body for the transaction +// that adds the code chunks for the FT or NFT templates to the bridge +func UpsertContractCodeChunksTransaction( + service flow.Address, + bridgeEnv bridge.Environment, + env templates.Environment, + forTemplate string, + newChunks []string, +) *flow.TransactionBody { + txScript, _ := bridge.GetCadenceTransactionCode("cadence/transactions/bridge/admin/templates/upsert_contract_code_chunks.cdc", bridgeEnv, env) + + chunks := make([]cadence.Value, len(newChunks)) + for i, chunk := range newChunks { + chunks[i] = cadence.String(chunk) + } + + return flow.NewTransactionBody(). + SetScript([]byte( + txScript, + ), + ). + AddArgument(jsoncdc.MustEncode(cadence.String(forTemplate))). + AddArgument(jsoncdc.MustEncode(cadence.NewArray(chunks))). + AddAuthorizer(service) +} diff --git a/fvm/bootstrap.go b/fvm/bootstrap.go index d75ae503907..8c30aba524a 100644 --- a/fvm/bootstrap.go +++ b/fvm/bootstrap.go @@ -2,13 +2,17 @@ package fvm import ( "fmt" + "log" "math" + "strings" "github.com/onflow/cadence" + "github.com/onflow/cadence/encoding/ccf" "github.com/onflow/flow-core-contracts/lib/go/contracts" "github.com/onflow/flow-core-contracts/lib/go/templates" usdc "github.com/onflow/bridged-usdc/lib/go/contracts" + bridge "github.com/onflow/flow-evm-bridge" storefront "github.com/onflow/nft-storefront/lib/go/contracts" "github.com/onflow/flow-go/fvm/accountV2Migration" @@ -446,7 +450,8 @@ func (b *bootstrapExecutor) Execute() error { b.deployStakingCollection(service, &env) // sets up the EVM environment - b.setupEVM(service, nonFungibleToken, fungibleToken, flowToken) + b.setupEVM(service, nonFungibleToken, fungibleToken, flowToken, &env) + b.setupVMBridge(service, &env) err = expectAccounts(systemcontracts.EVMStorageAccountIndex) if err != nil { @@ -978,7 +983,7 @@ func (b *bootstrapExecutor) setStakingAllowlist( panicOnMetaInvokeErrf("failed to set staking allow-list: %s", txError, err) } -func (b *bootstrapExecutor) setupEVM(serviceAddress, nonFungibleTokenAddress, fungibleTokenAddress, flowTokenAddress flow.Address) { +func (b *bootstrapExecutor) setupEVM(serviceAddress, nonFungibleTokenAddress, fungibleTokenAddress, flowTokenAddress flow.Address, env *templates.Environment) { if b.setupEVMEnabled { // account for storage // we dont need to deploy anything to this account, but it needs to exist @@ -998,9 +1003,303 @@ func (b *bootstrapExecutor) setupEVM(serviceAddress, nonFungibleTokenAddress, fu Transaction(tx, 0), ) panicOnMetaInvokeErrf("failed to deploy EVM contract: %s", txError, err) + + env.EVMAddress = env.ServiceAccountAddress } } +type stubEntropyProvider struct{} + +func (stubEntropyProvider) RandomSource() ([]byte, error) { + return []byte{0}, nil +} + +func (b *bootstrapExecutor) setupVMBridge(serviceAddress flow.Address, env *templates.Environment) { + // only setup VM bridge for transient networks + // this is because the evm storage account for testnet and mainnet do not exist yet after boostrapping + if bool(b.setupEVMEnabled) && b.ctx.Chain.ChainID().Transient() { + + bridgeEnv := bridge.Environment{ + CrossVMNFTAddress: env.ServiceAccountAddress, + CrossVMTokenAddress: env.ServiceAccountAddress, + FlowEVMBridgeHandlerInterfacesAddress: env.ServiceAccountAddress, + IBridgePermissionsAddress: env.ServiceAccountAddress, + ICrossVMAddress: env.ServiceAccountAddress, + ICrossVMAssetAddress: env.ServiceAccountAddress, + IEVMBridgeNFTMinterAddress: env.ServiceAccountAddress, + IEVMBridgeTokenMinterAddress: env.ServiceAccountAddress, + IFlowEVMNFTBridgeAddress: env.ServiceAccountAddress, + IFlowEVMTokenBridgeAddress: env.ServiceAccountAddress, + FlowEVMBridgeAddress: env.ServiceAccountAddress, + FlowEVMBridgeAccessorAddress: env.ServiceAccountAddress, + FlowEVMBridgeConfigAddress: env.ServiceAccountAddress, + FlowEVMBridgeHandlersAddress: env.ServiceAccountAddress, + FlowEVMBridgeNFTEscrowAddress: env.ServiceAccountAddress, + FlowEVMBridgeResolverAddress: env.ServiceAccountAddress, + FlowEVMBridgeTemplatesAddress: env.ServiceAccountAddress, + FlowEVMBridgeTokenEscrowAddress: env.ServiceAccountAddress, + FlowEVMBridgeUtilsAddress: env.ServiceAccountAddress, + ArrayUtilsAddress: env.ServiceAccountAddress, + ScopedFTProvidersAddress: env.ServiceAccountAddress, + SerializeAddress: env.ServiceAccountAddress, + SerializeMetadataAddress: env.ServiceAccountAddress, + StringUtilsAddress: env.ServiceAccountAddress, + } + + ctx := NewContextFromParent(b.ctx, + WithBlockHeader(b.rootBlock), + WithEntropyProvider(stubEntropyProvider{}), + WithEVMEnabled(true), + ) + + // Create a COA in the bridge account + tx := blueprints.CreateCOATransaction(serviceAddress, bridgeEnv, *env) + txError, err := b.invokeMetaTransaction( + ctx, + Transaction(tx, 0), + ) + panicOnMetaInvokeErrf("failed to create COA in Service Account: %s", txError, err) + + gasLimit := 15000000 + deploymentValue := 0.0 + + // Retrieve the factory bytecode from the JSON args + factoryBytecode := bridge.GetBytecodeFromArgsJSON("cadence/args/deploy-factory-args.json") + + // deploy the Solidity Factory contract to the service account's COA + tx = blueprints.DeployEVMContractTransaction(serviceAddress, factoryBytecode, gasLimit, deploymentValue, bridgeEnv, *env) + + txOutput, err := b.runMetaTransaction( + ctx, + Transaction(tx, 0), + ) + panicOnMetaInvokeErrf("failed to deploy the Factory in the Service Account COA: %s", txOutput.Err, err) + + factoryAddress := getContractAddressFromEVMEvent(txOutput) + + // Retrieve the factory bytecode from the JSON args + registryBytecode := bridge.GetBytecodeFromArgsJSON("cadence/args/deploy-deployment-registry-args.json") + + // deploy the Solidity Registry contract to the service account's COA + tx = blueprints.DeployEVMContractTransaction(serviceAddress, registryBytecode, gasLimit, deploymentValue, bridgeEnv, *env) + + txOutput, err = b.runMetaTransaction( + ctx, + Transaction(tx, 0), + ) + panicOnMetaInvokeErrf("failed to deploy the Registry in the Service Account COA: %s", txOutput.Err, err) + + registryAddress := getContractAddressFromEVMEvent(txOutput) + + // Retrieve the erc20Deployer bytecode from the JSON args + erc20DeployerBytecode := bridge.GetBytecodeFromArgsJSON("cadence/args/deploy-erc20-deployer-args.json") + + // deploy the Solidity ERC20 Deployer contract to the service account's COA + tx = blueprints.DeployEVMContractTransaction(serviceAddress, erc20DeployerBytecode, gasLimit, deploymentValue, bridgeEnv, *env) + + txOutput, err = b.runMetaTransaction( + ctx, + Transaction(tx, 0), + ) + panicOnMetaInvokeErrf("failed to deploy the ERC20 Deployer in the Service Account COA: %s", txOutput.Err, err) + + erc20DeployerAddress := getContractAddressFromEVMEvent(txOutput) + + erc721DeployerBytecode := bridge.GetBytecodeFromArgsJSON("cadence/args/deploy-erc721-deployer-args.json") + + // deploy the Solidity Registry contract to the service account's COA + tx = blueprints.DeployEVMContractTransaction(serviceAddress, erc721DeployerBytecode, gasLimit, deploymentValue, bridgeEnv, *env) + + txOutput, err = b.runMetaTransaction( + ctx, + Transaction(tx, 0), + ) + panicOnMetaInvokeErrf("failed to deploy the ERC721 Deployer in the Service Account COA: %s", txOutput.Err, err) + + erc721DeployerAddress := getContractAddressFromEVMEvent(txOutput) + + for _, path := range blueprints.BridgeContracts { + + contract, _ := bridge.GetCadenceContractCode(path, bridgeEnv, *env) + + slashSplit := strings.Split(path, "/") + nameWithCDC := slashSplit[len(slashSplit)-1] + name := nameWithCDC[:len(nameWithCDC)-4] + + if name == "FlowEVMBridgeUtils" { + txError, err := b.invokeMetaTransaction( + ctx, + Transaction( + blueprints.DeployFlowEVMBridgeUtilsContractTransaction(serviceAddress, &bridgeEnv, *env, contract, name, factoryAddress), + 0), + ) + panicOnMetaInvokeErrf("failed to deploy FlowEVMBridgeUtils contract: %s", txError, err) + } else { + txError, err := b.invokeMetaTransaction( + ctx, + Transaction( + blueprints.DeployContractTransaction(serviceAddress, contract, name), + 0), + ) + panicOnMetaInvokeErrf("failed to deploy "+name+" contract: %s", txError, err) + } + } + + // Pause the bridge for setup + txError, err = b.invokeMetaTransaction( + ctx, + Transaction( + blueprints.PauseBridgeTransaction(serviceAddress, bridgeEnv, *env, true), + 0), + ) + panicOnMetaInvokeErrf("failed to pause the bridge contracts: %s", txError, err) + + // Set the factory as registrar in the registry + txError, err = b.invokeMetaTransaction( + ctx, + Transaction( + blueprints.SetRegistrarTransaction(serviceAddress, bridgeEnv, *env, registryAddress), + 0), + ) + panicOnMetaInvokeErrf("failed to set the factory as registrar: %s", txError, err) + + // Add the registry to the factory + txError, err = b.invokeMetaTransaction( + ctx, + Transaction( + blueprints.SetDeploymentRegistryTransaction(serviceAddress, bridgeEnv, *env, registryAddress), + 0), + ) + panicOnMetaInvokeErrf("failed to add the registry to the factory: %s", txError, err) + + // Set the factory as delegated deployer in the ERC20 deployer + txError, err = b.invokeMetaTransaction( + ctx, + Transaction( + blueprints.SetDelegatedDeployerTransaction(serviceAddress, bridgeEnv, *env, erc20DeployerAddress), + 0), + ) + panicOnMetaInvokeErrf("failed to set the erc20 deployer as delegated deployer: %s", txError, err) + + // Set the factory as delegated deployer in the ERC721 deployer + txError, err = b.invokeMetaTransaction( + ctx, + Transaction( + blueprints.SetDelegatedDeployerTransaction(serviceAddress, bridgeEnv, *env, erc721DeployerAddress), + 0), + ) + panicOnMetaInvokeErrf("failed to set the erc721 deployer as delegated deployer: %s", txError, err) + + // Add the ERC20 Deployer as a deployer in the factory + txError, err = b.invokeMetaTransaction( + ctx, + Transaction( + blueprints.AddDeployerTransaction(serviceAddress, bridgeEnv, *env, "ERC20", erc20DeployerAddress), + 0), + ) + panicOnMetaInvokeErrf("failed to add the erc20 deployer in the factory: %s", txError, err) + + // Add the ERC721 Deployer as a deployer in the factory + txError, err = b.invokeMetaTransaction( + ctx, + Transaction( + blueprints.AddDeployerTransaction(serviceAddress, bridgeEnv, *env, "ERC721", erc721DeployerAddress), + 0), + ) + panicOnMetaInvokeErrf("failed to add the erc721 deployer in the factory: %s", txError, err) + + // /* --- EVM Contract Integration --- */ + + // Deploy FlowEVMBridgeAccessor, providing EVM contract host (network service account) as argument + txError, err = b.invokeMetaTransaction( + ctx, + Transaction( + blueprints.DeployFlowEVMBridgeAccessorContractTransaction(serviceAddress, bridgeEnv, *env), + 0), + ) + panicOnMetaInvokeErrf("failed to deploy FlowEVMBridgeAccessor contract: %s", txError, err) + + // Integrate the EVM contract with the BridgeAccessor + txError, err = b.invokeMetaTransaction( + ctx, + Transaction( + blueprints.IntegrateEVMWithBridgeAccessorTransaction(serviceAddress, bridgeEnv, *env), + 0), + ) + panicOnMetaInvokeErrf("failed to integrate the EVM contract with the BridgeAccessor: %s", txError, err) + + // Set the bridge onboarding fees + txError, err = b.invokeMetaTransaction( + ctx, + Transaction( + blueprints.UpdateOnboardFeeTransaction(serviceAddress, bridgeEnv, *env, 1.0), + 0), + ) + panicOnMetaInvokeErrf("failed to update the bridge onboarding fees: %s", txError, err) + + // Set the bridge base fee + txError, err = b.invokeMetaTransaction( + ctx, + Transaction( + blueprints.UpdateBaseFeeTransaction(serviceAddress, bridgeEnv, *env, 0.001), + 0), + ) + panicOnMetaInvokeErrf("failed to update the bridge base fees: %s", txError, err) + + tokenChunks := bridge.GetCadenceTokenChunkedJSONArguments(false) + nftChunks := bridge.GetCadenceTokenChunkedJSONArguments(true) + + // Add the FT Template Cadence Code Chunks + txError, err = b.invokeMetaTransaction( + ctx, + Transaction( + blueprints.UpsertContractCodeChunksTransaction(serviceAddress, bridgeEnv, *env, "bridgedToken", tokenChunks), + 0), + ) + panicOnMetaInvokeErrf("failed to add the FT template code chunks: %s", txError, err) + + // Add the NFT Template Cadence Code Chunks + txError, err = b.invokeMetaTransaction( + ctx, + Transaction( + blueprints.UpsertContractCodeChunksTransaction(serviceAddress, bridgeEnv, *env, "bridgedNFT", nftChunks), + 0), + ) + panicOnMetaInvokeErrf("failed to add the NFT template code chunks: %s", txError, err) + + // Unpause the bridge + txError, err = b.invokeMetaTransaction( + ctx, + Transaction( + blueprints.PauseBridgeTransaction(serviceAddress, bridgeEnv, *env, false), + 0), + ) + panicOnMetaInvokeErrf("failed to un-pause the bridge contracts: %s", txError, err) + } +} + +// getContractAddressFromEVMEvent gets the deployment address from a evm deployment transaction +func getContractAddressFromEVMEvent(output ProcedureOutput) string { + for _, event := range output.Events { + if strings.Contains(string(event.Type), "TransactionExecuted") { + // decode the event payload + data, _ := ccf.Decode(nil, event.Payload) + // get the contractAddress field from the event + contractAddr := cadence.SearchFieldByName( + data.(cadence.Event), + "contractAddress", + ).(cadence.String) + + if contractAddr.String() == "" { + log.Fatal("Contract address not found in event") + } + address := strings.ToLower(strings.Split(contractAddr.String(), "x")[1]) + return address[:len(address)-1] + } + } + return "" +} + func (b *bootstrapExecutor) registerNodes(service, fungibleToken, flowToken flow.Address) { for _, id := range b.identities { @@ -1220,3 +1519,28 @@ func (b *bootstrapExecutor) invokeMetaTransaction( return executor.Output().Err, err } + +func (b *bootstrapExecutor) runMetaTransaction( + parentCtx Context, + tx *TransactionProcedure, +) ( + ProcedureOutput, + error, +) { + // do not deduct fees or check storage in meta transactions + ctx := NewContextFromParent(parentCtx, + WithAccountStorageLimit(false), + WithTransactionFeesEnabled(false), + WithAuthorizationChecksEnabled(false), + WithSequenceNumberCheckAndIncrementEnabled(false), + + // disable interaction and computation limits for bootstrapping + WithMemoryAndInteractionLimitsDisabled(), + WithComputationLimit(math.MaxUint64), + ) + + executor := tx.NewExecutor(ctx, b.txnState) + err := Run(executor) + + return executor.Output(), err +} diff --git a/go.mod b/go.mod index 6275b7bbb83..6d6863c6245 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.5.1 github.com/aws/aws-sdk-go-v2/service/s3 v1.15.0 github.com/btcsuite/btcd/btcec/v2 v2.3.4 - github.com/davecgh/go-spew v1.1.1 + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc github.com/dgraph-io/badger/v2 v2.2007.4 github.com/ef-ds/deque v1.0.4 github.com/ethereum/go-ethereum v1.13.10 @@ -108,6 +108,7 @@ require ( github.com/libp2p/go-libp2p-routing-helpers v0.7.4 github.com/mitchellh/mapstructure v1.5.0 github.com/onflow/bridged-usdc/lib/go/contracts v1.0.0 + github.com/onflow/flow-evm-bridge v0.0.0-20250220231823-b59c1dc4881e github.com/onflow/go-ethereum v1.14.7 github.com/onflow/nft-storefront/lib/go/contracts v1.0.0 github.com/onflow/wal v1.0.2 @@ -283,7 +284,7 @@ require ( github.com/pion/transport/v3 v3.0.7 // indirect github.com/pion/turn/v2 v2.1.6 // indirect github.com/pion/webrtc/v3 v3.3.5 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/polydawn/refmt v0.89.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/prometheus/client_model v0.6.1 // indirect diff --git a/go.sum b/go.sum index 11cb33499dd..25d62cd0281 100644 --- a/go.sum +++ b/go.sum @@ -262,8 +262,9 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/cskr/pubsub v1.0.2 h1:vlOzMhl6PFn60gRlTQQsIfVwaPB/B/8MziK8FhEPt/0= github.com/cskr/pubsub v1.0.2/go.mod h1:/8MzYXk/NJAz782G8RPkFzXTZVu63VotefPnR9TIRis= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= @@ -924,6 +925,8 @@ github.com/onflow/flow-core-contracts/lib/go/contracts v1.6.0 h1:zbJaqR3bHicNz68 github.com/onflow/flow-core-contracts/lib/go/contracts v1.6.0/go.mod h1:ufT77Epq1gfXAHQQk13WcAHWEv+Aarecn5PMnljWJ1A= github.com/onflow/flow-core-contracts/lib/go/templates v1.6.0 h1:hVlyGbZ+gkeX0mTxTC4D65HulJCUbbVFgOvVWdMfRI8= github.com/onflow/flow-core-contracts/lib/go/templates v1.6.0/go.mod h1:pN768Al/wLRlf3bwugv9TyxniqJxMu4sxnX9eQJam64= +github.com/onflow/flow-evm-bridge v0.0.0-20250220231823-b59c1dc4881e h1:GlFteKWlHV9FEAuT95b0v1aDHDTqXm0D+a8IgyF+M7s= +github.com/onflow/flow-evm-bridge v0.0.0-20250220231823-b59c1dc4881e/go.mod h1:5UYwsnu6WcBNrwitGFxphCl5yq7fbWYGYuiCSTVF6pk= github.com/onflow/flow-ft/lib/go/contracts v1.0.1 h1:Ts5ob+CoCY2EjEd0W6vdLJ7hLL3SsEftzXG2JlmSe24= github.com/onflow/flow-ft/lib/go/contracts v1.0.1/go.mod h1:PwsL8fC81cjnUnTfmyL/HOIyHnyaw/JA474Wfj2tl6A= github.com/onflow/flow-ft/lib/go/templates v1.0.1 h1:FDYKAiGowABtoMNusLuRCILIZDtVqJ/5tYI4VkF5zfM= @@ -1038,8 +1041,9 @@ github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6J github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4= github.com/polydawn/refmt v0.89.0/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= diff --git a/insecure/go.mod b/insecure/go.mod index f4a46072ade..a461044c1ab 100644 --- a/insecure/go.mod +++ b/insecure/go.mod @@ -68,7 +68,7 @@ require ( github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c // indirect github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect github.com/cskr/pubsub v1.0.2 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect @@ -207,6 +207,7 @@ require ( github.com/onflow/cadence v1.3.3 // indirect github.com/onflow/flow-core-contracts/lib/go/contracts v1.6.0 // indirect github.com/onflow/flow-core-contracts/lib/go/templates v1.6.0 // indirect + github.com/onflow/flow-evm-bridge v0.0.0-20250220231823-b59c1dc4881e // indirect github.com/onflow/flow-ft/lib/go/contracts v1.0.1 // indirect github.com/onflow/flow-ft/lib/go/templates v1.0.1 // indirect github.com/onflow/flow-go-sdk v1.3.3 // indirect @@ -241,7 +242,7 @@ require ( github.com/pion/turn/v2 v2.1.6 // indirect github.com/pion/webrtc/v3 v3.3.5 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/polydawn/refmt v0.89.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/prometheus/client_golang v1.20.5 // indirect diff --git a/insecure/go.sum b/insecure/go.sum index cc1450b632e..c141bfd07a3 100644 --- a/insecure/go.sum +++ b/insecure/go.sum @@ -235,8 +235,9 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/cskr/pubsub v1.0.2 h1:vlOzMhl6PFn60gRlTQQsIfVwaPB/B/8MziK8FhEPt/0= github.com/cskr/pubsub v1.0.2/go.mod h1:/8MzYXk/NJAz782G8RPkFzXTZVu63VotefPnR9TIRis= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= @@ -870,6 +871,8 @@ github.com/onflow/flow-core-contracts/lib/go/contracts v1.6.0 h1:zbJaqR3bHicNz68 github.com/onflow/flow-core-contracts/lib/go/contracts v1.6.0/go.mod h1:ufT77Epq1gfXAHQQk13WcAHWEv+Aarecn5PMnljWJ1A= github.com/onflow/flow-core-contracts/lib/go/templates v1.6.0 h1:hVlyGbZ+gkeX0mTxTC4D65HulJCUbbVFgOvVWdMfRI8= github.com/onflow/flow-core-contracts/lib/go/templates v1.6.0/go.mod h1:pN768Al/wLRlf3bwugv9TyxniqJxMu4sxnX9eQJam64= +github.com/onflow/flow-evm-bridge v0.0.0-20250220231823-b59c1dc4881e h1:GlFteKWlHV9FEAuT95b0v1aDHDTqXm0D+a8IgyF+M7s= +github.com/onflow/flow-evm-bridge v0.0.0-20250220231823-b59c1dc4881e/go.mod h1:5UYwsnu6WcBNrwitGFxphCl5yq7fbWYGYuiCSTVF6pk= github.com/onflow/flow-ft/lib/go/contracts v1.0.1 h1:Ts5ob+CoCY2EjEd0W6vdLJ7hLL3SsEftzXG2JlmSe24= github.com/onflow/flow-ft/lib/go/contracts v1.0.1/go.mod h1:PwsL8fC81cjnUnTfmyL/HOIyHnyaw/JA474Wfj2tl6A= github.com/onflow/flow-ft/lib/go/templates v1.0.1 h1:FDYKAiGowABtoMNusLuRCILIZDtVqJ/5tYI4VkF5zfM= @@ -982,8 +985,9 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4= github.com/polydawn/refmt v0.89.0/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= diff --git a/integration/go.mod b/integration/go.mod index 55cfd00f1fc..5c17afb6f2b 100644 --- a/integration/go.mod +++ b/integration/go.mod @@ -99,7 +99,7 @@ require ( github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect github.com/cskr/pubsub v1.0.2 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect @@ -245,6 +245,7 @@ require ( github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/onflow/atree v0.9.0 // indirect github.com/onflow/bridged-usdc/lib/go/contracts v1.0.0 // indirect + github.com/onflow/flow-evm-bridge v0.0.0-20250220231823-b59c1dc4881e // indirect github.com/onflow/flow-ft/lib/go/contracts v1.0.1 // indirect github.com/onflow/flow-ft/lib/go/templates v1.0.1 // indirect github.com/onflow/flow-nft/lib/go/contracts v1.2.3 // indirect @@ -280,7 +281,7 @@ require ( github.com/pion/webrtc/v3 v3.3.5 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/polydawn/refmt v0.89.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/prometheus/procfs v0.15.1 // indirect diff --git a/integration/go.sum b/integration/go.sum index 302e611b0c1..2c623de1edc 100644 --- a/integration/go.sum +++ b/integration/go.sum @@ -194,8 +194,9 @@ github.com/danieljoos/wincred v1.2.0/go.mod h1:FzQLLMKBFdvu+osBrnFODiv32YGwCfx0S github.com/dapperlabs/testingdock v0.4.5-0.20231020233342-a2853fe18724 h1:zOOpPLu5VvH8ixyoDWHnQHWoEHtryT1ne31vwz0G7Fo= github.com/dapperlabs/testingdock v0.4.5-0.20231020233342-a2853fe18724/go.mod h1:U0cEcbf9hAwPSuuoPVqXKhcWV+IU4CStK75cJ52f2/A= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= @@ -743,6 +744,8 @@ github.com/onflow/flow-core-contracts/lib/go/contracts v1.6.0 h1:zbJaqR3bHicNz68 github.com/onflow/flow-core-contracts/lib/go/contracts v1.6.0/go.mod h1:ufT77Epq1gfXAHQQk13WcAHWEv+Aarecn5PMnljWJ1A= github.com/onflow/flow-core-contracts/lib/go/templates v1.6.0 h1:hVlyGbZ+gkeX0mTxTC4D65HulJCUbbVFgOvVWdMfRI8= github.com/onflow/flow-core-contracts/lib/go/templates v1.6.0/go.mod h1:pN768Al/wLRlf3bwugv9TyxniqJxMu4sxnX9eQJam64= +github.com/onflow/flow-evm-bridge v0.0.0-20250220231823-b59c1dc4881e h1:GlFteKWlHV9FEAuT95b0v1aDHDTqXm0D+a8IgyF+M7s= +github.com/onflow/flow-evm-bridge v0.0.0-20250220231823-b59c1dc4881e/go.mod h1:5UYwsnu6WcBNrwitGFxphCl5yq7fbWYGYuiCSTVF6pk= github.com/onflow/flow-ft/lib/go/contracts v1.0.1 h1:Ts5ob+CoCY2EjEd0W6vdLJ7hLL3SsEftzXG2JlmSe24= github.com/onflow/flow-ft/lib/go/contracts v1.0.1/go.mod h1:PwsL8fC81cjnUnTfmyL/HOIyHnyaw/JA474Wfj2tl6A= github.com/onflow/flow-ft/lib/go/templates v1.0.1 h1:FDYKAiGowABtoMNusLuRCILIZDtVqJ/5tYI4VkF5zfM= @@ -847,8 +850,9 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4= github.com/polydawn/refmt v0.89.0/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=