diff --git a/core/scripts/chaincli/README.md b/core/scripts/chaincli/README.md index 7ca26c58a01..d18cca1f873 100644 --- a/core/scripts/chaincli/README.md +++ b/core/scripts/chaincli/README.md @@ -40,33 +40,13 @@ go build Create the `.env` file based on the example `.env.example`, adding the node endpoint URLs and the private key of your wallet ### Keeper Registry -Next, use chaincli to deploy the registry: +Set `KEEPER_REGISTRY_ADDRESS` in `.env` to your deployed keeper registry. -Example: -```shell -./chaincli keeper registry deploy -``` - -Other options include: +Registry management commands: - `./chaincli keeper registry update`: update existing keeper registry - `./chaincli keeper registry withdraw`: cancel upkeeps and withdraw funds from registry - `./chaincli keeper registry verify `: verify keeper registry contract -As the `keeper registry deploy` command executes, _two_ address are written to the terminal: - -- KeeperRegistry2.0 Logic _(can be ignored)_ -- KeeperRegistry2.0 - -The second address, `KeeperRegistry2.0` is the address you need; in the `.env` file, set `KEEPER_REGISTRY_ADDRESS` variable to the `KeeperRegistry2.0` address. - -Note that this command doesn't run contract verification by default. If you want to run verification (eth, op and arb supported), config your .env and add the `--verify=true` flag in command. - -If you already have keeper registry contract deployed and want to run only contract verification, you can use the following command: - -```shell -./chaincli keeper registry verify -``` - ### Bootstrap Nodes Run the following `bootstrap` command to start bootstrap nodes: @@ -83,26 +63,6 @@ Other options include: The output of this command will show the tcp address of the deployed bootstrap node in the following format: `@bootstrap:8000`. Copy this entire string, including the `@bootstrap:8000` suffix, and the set the `BOOTSTRAP_NODE_ADDR` variable to this address in the `.env` file. -### Keeper launch and test -Once the bootstrap node is running, run the following command to launch the ocr2keeper nodes: - -Example: -```shell -./chaincli keeper launch-and-test -``` - -Other options include: -- `--withdraw | -w`: default `true`, if funds should be withdrawn and upkeeps should be canceled after the test -- `--export-logs | -l`: default `false`, if container logs should be exported to ./ directory -- `--force | -f`: default `false`, if existing containers should be forcefully removed - -You can also combine the `bootstrap` and `launch-and-test` commands into a single command: - -```shell -./chaincli keeper launch-and-test --bootstrap -``` -In the output of this command, you will see the http address of the nodes, e.g. `http://localhost:6688`. This is the Chainlink Operator GUI. You can use the default username `notreal@fakeemail.ch` and password `fj293fbBnlQ!f9vNs` to log in. - ### Logs Now that the nodes are running, you can use the `logs` subcommand to stream the output of the containers to your local terminal: diff --git a/core/scripts/chaincli/command/keeper/deploy.go b/core/scripts/chaincli/command/keeper/deploy.go deleted file mode 100644 index 8a15c8aafba..00000000000 --- a/core/scripts/chaincli/command/keeper/deploy.go +++ /dev/null @@ -1,26 +0,0 @@ -package keeper - -import ( - "log" - - "github.com/spf13/cobra" - - "github.com/smartcontractkit/chainlink/core/scripts/chaincli/config" - "github.com/smartcontractkit/chainlink/core/scripts/chaincli/handler" -) - -// deployCmd represents the command to run the service -var deployCmd = &cobra.Command{ - Use: "deploy", - Short: "Deploy keepers", - Long: `This command deploys keepers (keeper registry + upkeeps).`, - Run: func(cmd *cobra.Command, args []string) { - cfg := config.New() - if err := cfg.Validate(); err != nil { - log.Fatal(err) - } - - hdlr := handler.NewKeeper(cfg) - hdlr.DeployKeepers(cmd.Context()) - }, -} diff --git a/core/scripts/chaincli/command/keeper/launch.go b/core/scripts/chaincli/command/keeper/launch.go deleted file mode 100644 index e918095edb4..00000000000 --- a/core/scripts/chaincli/command/keeper/launch.go +++ /dev/null @@ -1,53 +0,0 @@ -package keeper - -import ( - "log" - - "github.com/spf13/cobra" - - "github.com/smartcontractkit/chainlink/core/scripts/chaincli/config" - "github.com/smartcontractkit/chainlink/core/scripts/chaincli/handler" -) - -var launchAndTestCmd = &cobra.Command{ - Use: "launch-and-test", - Short: "Launches keepers and starts performing", - Long: `This command launches chainlink nodes, keeper setup and starts performing upkeeps.`, - Run: func(cmd *cobra.Command, args []string) { - cfg := config.New() - if err := cfg.Validate(); err != nil { - log.Fatal(err) - } - - hdlr := handler.NewKeeper(cfg) - - withdraw, err := cmd.Flags().GetBool("withdraw") - if err != nil { - log.Fatal("failed to get withdraw flag: ", err) - } - - bootstrap, err := cmd.Flags().GetBool("bootstrap") - if err != nil { - log.Fatal("failed to get bootstrap flag: ", err) - } - - printLogs, err := cmd.Flags().GetBool("export-logs") - if err != nil { - log.Fatal("failed to get export-logs flag: ", err) - } - - force, err := cmd.Flags().GetBool("force") - if err != nil { - log.Fatal("failed to get force flag: ", err) - } - - hdlr.LaunchAndTest(cmd.Context(), withdraw, printLogs, force, bootstrap) - }, -} - -func init() { - launchAndTestCmd.Flags().BoolP("withdraw", "w", true, "Specify if funds should be withdrawn and upkeeps should be canceled") - launchAndTestCmd.Flags().BoolP("bootstrap", "b", false, "Specify if launching bootstrap node is required. Default listen ports(5688, 8000) are used, if you need to use custom ports, please use bootstrap command") - launchAndTestCmd.Flags().BoolP("export-logs", "l", false, "Specify if container logs should be exported to ./") - launchAndTestCmd.Flags().BoolP("force", "f", false, "Specify if existing containers should be forcefully removed ./") -} diff --git a/core/scripts/chaincli/command/keeper/registry.go b/core/scripts/chaincli/command/keeper/registry.go index e087284daaa..262d7481aae 100644 --- a/core/scripts/chaincli/command/keeper/registry.go +++ b/core/scripts/chaincli/command/keeper/registry.go @@ -1,8 +1,6 @@ package keeper import ( - "log" - "github.com/spf13/cobra" "github.com/smartcontractkit/chainlink/core/scripts/chaincli/config" @@ -15,23 +13,6 @@ var registryCmd = &cobra.Command{ Long: `This command provides an interface to manage keeper registry.`, } -var deployRegistryCmd = &cobra.Command{ - Use: "deploy", - Short: "Deploy keeper registry", - Long: `This command deploys a new keeper registry.`, - Run: func(cmd *cobra.Command, args []string) { - cfg := config.New() - hdlr := handler.NewKeeper(cfg) - - verify, err := cmd.Flags().GetBool("verify") - if err != nil { - log.Fatal("failed to get verify flag: ", err) - } - - hdlr.DeployRegistry(cmd.Context(), verify) - }, -} - var verifyRegistryCmd = &cobra.Command{ Use: "verify", Short: "Verify keeper registry", @@ -70,8 +51,6 @@ var withdrawFromRegistryCmd = &cobra.Command{ } func init() { - deployRegistryCmd.Flags().BoolP("verify", "v", false, "Specify if contracts should be verified on Etherscan") - registryCmd.AddCommand(deployRegistryCmd) registryCmd.AddCommand(verifyRegistryCmd) registryCmd.AddCommand(updateRegistryCmd) registryCmd.AddCommand(withdrawFromRegistryCmd) diff --git a/core/scripts/chaincli/command/keeper/root.go b/core/scripts/chaincli/command/keeper/root.go index e00052e3ebb..70850dc672e 100644 --- a/core/scripts/chaincli/command/keeper/root.go +++ b/core/scripts/chaincli/command/keeper/root.go @@ -12,14 +12,11 @@ var RootCmd = &cobra.Command{ } func init() { - RootCmd.AddCommand(deployCmd) RootCmd.AddCommand(debugCmd) RootCmd.AddCommand(jobCmd) RootCmd.AddCommand(logsCmd) RootCmd.AddCommand(registryCmd) - RootCmd.AddCommand(launchAndTestCmd) RootCmd.AddCommand(upkeepEventsCmd) - RootCmd.AddCommand(upkeepHistoryCmd) RootCmd.AddCommand(ocr2UpkeepReportHistoryCmd) RootCmd.AddCommand(ocr2UpdateConfigCmd) RootCmd.AddCommand(scrapeNodes) diff --git a/core/scripts/chaincli/command/keeper/upkeep.go b/core/scripts/chaincli/command/keeper/upkeep.go index df295e821d0..5c30ca4c4d7 100644 --- a/core/scripts/chaincli/command/keeper/upkeep.go +++ b/core/scripts/chaincli/command/keeper/upkeep.go @@ -35,43 +35,6 @@ var upkeepEventsCmd = &cobra.Command{ }, } -// upkeepHistoryCmd represents the command to run the upkeep history command -var upkeepHistoryCmd = &cobra.Command{ - Use: "upkeep-history", - Short: "Print checkUpkeep history", - Long: `Print checkUpkeep status and keeper responsibility for a given upkeep in a set block range`, - Run: func(cmd *cobra.Command, args []string) { - upkeepIDStr, err := cmd.Flags().GetString("upkeep-id") - if err != nil { - log.Fatal("failed to get 'upkeep-id' flag: ", err) - } - upkeepID, ok := handler.ParseUpkeepID(upkeepIDStr) - if !ok { - log.Fatal("failed to parse upkeep-id") - } - - fromBlock, err := cmd.Flags().GetUint64("from") - if err != nil { - log.Fatal("failed to get 'from' flag: ", err) - } - - toBlock, err := cmd.Flags().GetUint64("to") - if err != nil { - log.Fatal("failed to get 'to' flag: ", err) - } - - gasPrice, err := cmd.Flags().GetUint64("gas-price") - if err != nil { - log.Fatal("failed to get 'gas-price' flag: ", err) - } - - cfg := config.New() - hdlr := handler.NewKeeper(cfg) - - hdlr.UpkeepHistory(cmd.Context(), upkeepID, fromBlock, toBlock, gasPrice) - }, -} - var ocr2UpkeepReportHistoryCmd = &cobra.Command{ Use: "ocr2-reports", Short: "Print ocr2 automation reports", @@ -125,11 +88,6 @@ var ocr2UpdateConfigCmd = &cobra.Command{ } func init() { - upkeepHistoryCmd.Flags().String("upkeep-id", "", "upkeep ID") - upkeepHistoryCmd.Flags().Uint64("from", 0, "from block") - upkeepHistoryCmd.Flags().Uint64("to", 0, "to block") - upkeepHistoryCmd.Flags().Uint64("gas-price", 0, "gas price to use") - ocr2UpkeepReportHistoryCmd.Flags().StringSlice("tx-hashes", []string{}, "list of transaction hashes to get information for") ocr2UpkeepReportHistoryCmd.Flags().String("csv", "", "path to csv file containing transaction hashes; first element per line should be transaction hash; file should not have headers") diff --git a/core/scripts/chaincli/handler/handler.go b/core/scripts/chaincli/handler/handler.go index 4d151c56c97..850cab538db 100644 --- a/core/scripts/chaincli/handler/handler.go +++ b/core/scripts/chaincli/handler/handler.go @@ -175,36 +175,6 @@ func (h *baseHandler) buildTxOpts(ctx context.Context) *bind.TransactOpts { return auth } -// Send eth from prefunded account. -// Amount is number of wei. -func (k *Keeper) sendEth(ctx context.Context, to common.Address, amount *big.Int) error { - txOpts := k.buildTxOpts(ctx) - - tx := ethtypes.NewTx(ðtypes.LegacyTx{ - Nonce: txOpts.Nonce.Uint64(), - To: &to, - Value: amount, - Gas: txOpts.GasLimit, - GasPrice: txOpts.GasPrice, - Data: nil, - }) - signedTx, err := ethtypes.SignTx(tx, ethtypes.NewEIP155Signer(big.NewInt(k.cfg.ChainID)), k.privateKey) - if err != nil { - return fmt.Errorf("failed to sign tx: %w", err) - } - - if err = k.client.SendTransaction(ctx, signedTx); err != nil { - return fmt.Errorf("failed to send tx: %w", err) - } - - if err := k.waitTx(ctx, signedTx); err != nil { - log.Fatalf("Send ETH failed, error is %s", err.Error()) - } - log.Println("Send ETH successfully") - - return nil -} - func (h *baseHandler) waitDeployment(ctx context.Context, tx *ethtypes.Transaction) { if _, err := bind.WaitDeployed(ctx, h.client, tx); err != nil { log.Fatal("WaitDeployed failed: ", err, " ", helpers.ExplorerLink(h.cfg.ChainID, tx.Hash())) @@ -565,21 +535,6 @@ func nodeRequest(ctx context.Context, client cmd.HTTPClient, path string) ([]byt return raw, nil } -// getNodeAddress returns chainlink node's wallet address -func getNodeAddress(ctx context.Context, client cmd.HTTPClient) (string, error) { - resp, err := nodeRequest(ctx, client, ethKeysEndpoint) - if err != nil { - return "", fmt.Errorf("failed to get ETH keys: %w", err) - } - - var keys cmd.EthKeyPresenters - if err = jsonapi.Unmarshal(resp, &keys); err != nil { - return "", fmt.Errorf("failed to unmarshal response body: %w", err) - } - - return keys[0].Address, nil -} - // getNodeOCR2Config returns chainlink node's OCR2 bundle key ID func getNodeOCR2Config(ctx context.Context, client cmd.HTTPClient) (*cmd.OCR2KeyBundlePresenter, error) { resp, err := nodeRequest(ctx, client, ocr2KeysEndpoint) diff --git a/core/scripts/chaincli/handler/jobs.go b/core/scripts/chaincli/handler/jobs.go index 89f1a3ea5bc..0a0275a7831 100644 --- a/core/scripts/chaincli/handler/jobs.go +++ b/core/scripts/chaincli/handler/jobs.go @@ -1,10 +1,18 @@ package handler import ( + "bytes" "context" + "encoding/json" + "errors" + "fmt" + "io" "log" + "github.com/smartcontractkit/chainlink/core/scripts/chaincli/config" + "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/web" ) func (k *Keeper) CreateJob(ctx context.Context) { @@ -15,7 +23,6 @@ func (k *Keeper) createJobs(ctx context.Context) { lggr, closeLggr := logger.NewLogger() logger.Sugared(lggr).ErrorIfFn(closeLggr, "Failed to close logger") - // Create Keeper Jobs on Nodes for Registry for i, keeperAddr := range k.cfg.Keepers { url := k.cfg.KeeperURLs[i] email := k.cfg.KeeperEmails[i] @@ -37,3 +44,81 @@ func (k *Keeper) createJobs(ctx context.Context) { } } } + +func (k *Keeper) createKeeperJob(ctx context.Context, client cmd.HTTPClient, registryAddr, nodeAddr string) error { + if !k.cfg.OCR2Keepers { + return errors.New("legacy keeper jobs are no longer supported; set KEEPER_OCR2=true and configure OCR2 automation") + } + if err := k.createOCR2KeeperJob(ctx, client, registryAddr, nodeAddr); err != nil { + return err + } + log.Println("Keeper job has been successfully created in the Chainlink node with address: ", nodeAddr) + return nil +} + +const ocr2keeperJobTemplate = `type = "offchainreporting2" +pluginType = "ocr2automation" +relay = "evm" +name = "ocr2-automation" +forwardingAllowed = false +schemaVersion = 1 +contractID = "%s" +contractConfigTrackerPollInterval = "15s" +ocrKeyBundleID = "%s" +transmitterID = "%s" +p2pv2Bootstrappers = [ + "%s" +] + +[relayConfig] +chainID = %d + +[pluginConfig] +maxServiceWorkers = 100 +cacheEvictionInterval = "1s" +contractVersion = "%s" +mercuryCredentialName = "%s"` + +func (k *Keeper) createOCR2KeeperJob(ctx context.Context, client cmd.HTTPClient, contractAddr, nodeAddr string) error { + ocr2KeyConfig, err := getNodeOCR2Config(ctx, client) + if err != nil { + return fmt.Errorf("failed to get node OCR2 key bundle ID: %w", err) + } + + contractVersion := "v2.0" + if k.cfg.RegistryVersion == config.RegistryVersion2_1 { + contractVersion = "v2.1" + } + + request, err := json.Marshal(web.CreateJobRequest{ + TOML: fmt.Sprintf(ocr2keeperJobTemplate, + contractAddr, + ocr2KeyConfig.ID, + nodeAddr, + k.cfg.BootstrapNodeAddr, + k.cfg.ChainID, + contractVersion, + k.cfg.DataStreamsCredName, + ), + }) + if err != nil { + return fmt.Errorf("failed to marshal request: %w", err) + } + + resp, err := client.Post(ctx, "/v2/jobs", bytes.NewReader(request)) + if err != nil { + return fmt.Errorf("failed to create ocr2keeper job: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode >= 400 { + body, err := io.ReadAll(resp.Body) + if err != nil { + return fmt.Errorf("failed to read error response body: %w", err) + } + + return fmt.Errorf("unable to create ocr2keeper job: '%v' [%d]", string(body), resp.StatusCode) + } + + return nil +} diff --git a/core/scripts/chaincli/handler/keeper.go b/core/scripts/chaincli/handler/keeper.go index d52e138fb19..8fa0078706d 100644 --- a/core/scripts/chaincli/handler/keeper.go +++ b/core/scripts/chaincli/handler/keeper.go @@ -2,208 +2,37 @@ package handler import ( "context" - "encoding/json" "fmt" "log" "math/big" - "os" "strings" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/umbracle/ethgo/abi" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams" - - automationForwarderLogic "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/automation_forwarder_logic" iregistry21 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1" - registrylogic20 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_logic2_0" - registrylogica21 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_logic_a_wrapper_2_1" - registrylogicb21 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_logic_b_wrapper_2_1" registry20 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper2_0" - registry21 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper_2_1" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/log_upkeep_counter_wrapper" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/streams_lookup_upkeep_wrapper" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/upkeep_counter_wrapper" - upkeep "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/upkeep_perform_counter_restrictive_wrapper" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/verifiable_load_streams_lookup_upkeep_wrapper" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/verifiable_load_upkeep_wrapper" "github.com/smartcontractkit/chainlink/core/scripts/chaincli/config" - helpers "github.com/smartcontractkit/chainlink/core/scripts/common" - "github.com/smartcontractkit/chainlink/v2/core/cmd" - "github.com/smartcontractkit/chainlink/v2/core/logger" ) // Keeper is the keepers commands handler type Keeper struct { *baseHandler - - addFundsAmount *big.Int } // NewKeeper creates new instance of Keeper func NewKeeper(cfg *config.Config) *Keeper { - addFundsAmount := big.NewInt(0) - addFundsAmount.SetString(cfg.AddFundsAmount, 10) - return &Keeper{ - baseHandler: NewBaseHandler(cfg), - addFundsAmount: addFundsAmount, + baseHandler: NewBaseHandler(cfg), } } -// DeployKeepers contains a logic to deploy keepers. -func (k *Keeper) DeployKeepers(ctx context.Context) { - lggr, closeLggr := logger.NewLogger() - logger.Sugared(lggr).ErrorIfFn(closeLggr, "Failed to close logger") - - keepers, owners := k.keepers() - upkeepCount, registryAddr, deployer := k.prepareRegistry(ctx) - - // Create Keeper Jobs on Nodes for Registry - cls := make([]cmd.HTTPClient, len(k.cfg.Keepers)) - for i, keeperAddr := range k.cfg.Keepers { - url := k.cfg.KeeperURLs[i] - email := k.cfg.KeeperEmails[i] - if len(email) == 0 { - email = defaultChainlinkNodeLogin - } - pwd := k.cfg.KeeperPasswords[i] - if len(pwd) == 0 { - pwd = defaultChainlinkNodePassword - } - - cl, err := authenticate(ctx, url, email, pwd, lggr) - if err != nil { - log.Fatal(err) - } - cls[i] = cl - - if err = k.createKeeperJob(ctx, cl, k.cfg.RegistryAddress, keeperAddr); err != nil { - log.Fatal(err) - } - } - - // Approve keeper registry - k.approveFunds(ctx, registryAddr) - - // Deploy Upkeeps - k.deployUpkeeps(ctx, registryAddr, deployer, upkeepCount) - - // Set Keepers on the registry - k.setKeepers(ctx, cls, deployer, keepers, owners) -} - -// DeployRegistry deploys a new keeper registry. -func (k *Keeper) DeployRegistry(ctx context.Context, verify bool) { - if verify { - if k.cfg.RegistryVersion != config.RegistryVersion2_1 && k.cfg.RegistryVersion != config.RegistryVersion2_0 { - log.Fatal("keeper registry verification is only supported for version 2.0 and 2.1") - } - if k.cfg.ExplorerAPIKey == "" || k.cfg.ExplorerAPIKey == "" || k.cfg.NetworkName == "" || k.cfg.NetworkName == "" { - log.Fatal("please set your explore API key and network name in the .env file to verify the registry contract") - } - - // Get the current working directory - currentDir, err := os.Getwd() - if err != nil { - log.Fatal("failed to get current working directory: %w", err) - } - - // Check if it is the root directory of chaincli - if !strings.HasSuffix(currentDir, "core/scripts/chaincli") { - log.Fatal("please run the command from the root directory of chaincli to verify the registry") - } - } - - switch k.cfg.RegistryVersion { - case config.RegistryVersion2_0: - k.deployRegistry20(ctx, verify) - case config.RegistryVersion2_1: - k.deployRegistry21(ctx, verify) - default: - panic("unsupported registry version") - } -} - -func (k *Keeper) prepareRegistry(ctx context.Context) (int64, common.Address, keepersDeployer) { - var upkeepCount int64 - var registryAddr common.Address - var deployer keepersDeployer - var keeperRegistry20 *registry20.KeeperRegistry - var keeperRegistry21 *iregistry21.IKeeperRegistryMaster - if k.cfg.RegistryAddress != "" { - callOpts := bind.CallOpts{ - From: k.fromAddr, - Context: ctx, - } - - // Get existing keeper registry - switch k.cfg.RegistryVersion { - case config.RegistryVersion2_0: - registryAddr, keeperRegistry20 = k.getRegistry20(ctx) - state, err := keeperRegistry20.GetState(&callOpts) - if err != nil { - log.Fatal(registryAddr.Hex(), ": failed to getState - ", err) - } - upkeepCount = state.State.NumUpkeeps.Int64() - deployer = &v20KeeperDeployer{KeeperRegistryInterface: keeperRegistry20, cfg: k.cfg} - case config.RegistryVersion2_1: - registryAddr, keeperRegistry21 = k.getRegistry21(ctx) - state, err := keeperRegistry21.GetState(&callOpts) - if err != nil { - log.Fatal(registryAddr.Hex(), ": failed to getState - ", err) - } - upkeepCount = state.State.NumUpkeeps.Int64() - deployer = &v21KeeperDeployer{IKeeperRegistryMasterInterface: keeperRegistry21, cfg: k.cfg} - default: - panic(fmt.Errorf("version %s is not supported", k.cfg.RegistryVersion)) - } - } else { - // Deploy keeper registry - switch k.cfg.RegistryVersion { - case config.RegistryVersion2_0: - registryAddr, keeperRegistry20 = k.deployRegistry20(ctx, true) - deployer = &v20KeeperDeployer{KeeperRegistryInterface: keeperRegistry20, cfg: k.cfg} - case config.RegistryVersion2_1: - registryAddr, keeperRegistry21 = k.deployRegistry21(ctx, false) - deployer = &v21KeeperDeployer{IKeeperRegistryMasterInterface: keeperRegistry21, cfg: k.cfg} - default: - panic(fmt.Errorf("version %s is not supported", k.cfg.RegistryVersion)) - } - } - - return upkeepCount, registryAddr, deployer -} - -func (k *Keeper) approveFunds(ctx context.Context, registryAddr common.Address) { - if k.approveAmount.Cmp(big.NewInt(0)) == 0 { - return - } - // Approve keeper registry - approveRegistryTx, err := k.linkToken.Approve(k.buildTxOpts(ctx), registryAddr, k.approveAmount) - if err != nil { - log.Fatal(registryAddr.Hex(), ": Approve failed - ", err) - } - - if err := k.waitTx(ctx, approveRegistryTx); err != nil { - log.Fatalf("KeeperRegistry ApproveFunds failed for registryAddr: %s, and approveAmount: %s, error is: %s", k.cfg.RegistryAddress, k.approveAmount, err.Error()) - } - - log.Println(registryAddr.Hex(), ": KeeperRegistry approved - ", helpers.ExplorerLink(k.cfg.ChainID, approveRegistryTx.Hash())) -} - func (k *Keeper) VerifyContract(params ...string) { - // Change to the contracts directory where the hardhat.config.ts file is located if err := k.changeToContractsDirectory(); err != nil { log.Fatalf("failed to change to directory where the hardhat.config.ts file is located: %v", err) } - // Append the address and params to the commandArgs slice commandArgs := append([]string{}, params...) - - // Format the command string with the commandArgs command := fmt.Sprintf( "NODE_HTTP_URL='%s' EXPLORER_API_KEY='%s' NETWORK_NAME='%s' pnpm hardhat verify --network env %s", k.cfg.NodeHttpURL, @@ -218,120 +47,6 @@ func (k *Keeper) VerifyContract(params ...string) { } } -// deployRegistry21 deploys a version 2.1 keeper registry -func (k *Keeper) deployRegistry21(ctx context.Context, verify bool) (common.Address, *iregistry21.IKeeperRegistryMaster) { - automationForwarderLogicAddr, tx, _, err := automationForwarderLogic.DeployAutomationForwarderLogic(k.buildTxOpts(ctx), k.client) - if err != nil { - log.Fatal("Deploy AutomationForwarderLogic failed: ", err) - } - k.waitDeployment(ctx, tx) - log.Println("AutomationForwarderLogic deployed:", automationForwarderLogicAddr.Hex(), "-", helpers.ExplorerLink(k.cfg.ChainID, tx.Hash())) - - registryLogicBAddr, tx, _, err := registrylogicb21.DeployKeeperRegistryLogicB( - k.buildTxOpts(ctx), - k.client, - k.cfg.Mode, - common.HexToAddress(k.cfg.LinkTokenAddr), - common.HexToAddress(k.cfg.LinkETHFeedAddr), - common.HexToAddress(k.cfg.FastGasFeedAddr), - automationForwarderLogicAddr, - ) - if err != nil { - log.Fatal("DeployAbi failed: ", err) - } - k.waitDeployment(ctx, tx) - log.Println("KeeperRegistry LogicB 2.1 deployed:", registryLogicBAddr.Hex(), "-", helpers.ExplorerLink(k.cfg.ChainID, tx.Hash())) - - // verify KeeperRegistryLogicB - if verify { - k.VerifyContract(registryLogicBAddr.String(), "0", k.cfg.LinkTokenAddr, k.cfg.LinkETHFeedAddr, k.cfg.FastGasFeedAddr) - log.Println("KeeperRegistry LogicB 2.1 verified successfully") - } - - registryLogicAAddr, tx, _, err := registrylogica21.DeployKeeperRegistryLogicA( - k.buildTxOpts(ctx), - k.client, - registryLogicBAddr, - ) - if err != nil { - log.Fatal("DeployAbi failed: ", err) - } - k.waitDeployment(ctx, tx) - log.Println("KeeperRegistry LogicA 2.1 deployed:", registryLogicAAddr.Hex(), "-", helpers.ExplorerLink(k.cfg.ChainID, tx.Hash())) - - // verify KeeperRegistryLogicA - if verify { - k.VerifyContract(registryLogicAAddr.String(), registryLogicBAddr.String()) - log.Println("KeeperRegistry LogicA 2.1 verified successfully") - } - - registryAddr, deployKeeperRegistryTx, _, err := registry21.DeployKeeperRegistry( - k.buildTxOpts(ctx), - k.client, - registryLogicAAddr, - ) - if err != nil { - log.Fatal("DeployAbi failed: ", err) - } - k.waitDeployment(ctx, deployKeeperRegistryTx) - log.Println("KeeperRegistry 2.1 deployed:", registryAddr.Hex(), "-", helpers.ExplorerLink(k.cfg.ChainID, deployKeeperRegistryTx.Hash())) - - registryInstance, err := iregistry21.NewIKeeperRegistryMaster(registryAddr, k.client) - if err != nil { - log.Fatal("Failed to attach to deployed contract: ", err) - } - - // verify KeeperRegistry - if verify { - k.VerifyContract(registryAddr.String(), registryLogicAAddr.String()) - log.Println("KeeperRegistry 2.1 verified successfully") - } - - return registryAddr, registryInstance -} - -// deployRegistry20 deploys a version 2.0 keeper registry -func (k *Keeper) deployRegistry20(ctx context.Context, verify bool) (common.Address, *registry20.KeeperRegistry) { - registryLogicAddr, deployKeeperRegistryLogicTx, _, err := registrylogic20.DeployKeeperRegistryLogic( - k.buildTxOpts(ctx), - k.client, - k.cfg.Mode, - common.HexToAddress(k.cfg.LinkTokenAddr), - common.HexToAddress(k.cfg.LinkETHFeedAddr), - common.HexToAddress(k.cfg.FastGasFeedAddr), - ) - if err != nil { - log.Fatal("DeployAbi failed: ", err) - } - k.waitDeployment(ctx, deployKeeperRegistryLogicTx) - log.Println("KeeperRegistry2.0 Logic deployed:", registryLogicAddr.Hex(), "-", helpers.ExplorerLink(k.cfg.ChainID, deployKeeperRegistryLogicTx.Hash())) - - // verify KeeperRegistryLogic - if verify { - k.VerifyContract(registryLogicAddr.String(), "0", k.cfg.LinkTokenAddr, k.cfg.LinkETHFeedAddr, k.cfg.FastGasFeedAddr) - log.Println("KeeperRegistry Logic 2.0 verified successfully") - } - - registryAddr, deployKeeperRegistryTx, registryInstance, err := registry20.DeployKeeperRegistry( - k.buildTxOpts(ctx), - k.client, - registryLogicAddr, - ) - if err != nil { - log.Fatal("DeployAbi failed: ", err) - } - k.waitDeployment(ctx, deployKeeperRegistryTx) - log.Println("KeeperRegistry2.0 deployed:", registryAddr.Hex(), "-", helpers.ExplorerLink(k.cfg.ChainID, deployKeeperRegistryTx.Hash())) - - // verify KeeperRegistry - if verify { - k.VerifyContract(registryAddr.String(), registryLogicAddr.String()) - log.Println("KeeperRegistry 2.0 verified successfully") - } - - return registryAddr, registryInstance -} - // UpdateRegistry attaches to an existing registry and possibly updates registry config func (k *Keeper) UpdateRegistry(ctx context.Context) { var registryAddr common.Address @@ -346,7 +61,6 @@ func (k *Keeper) UpdateRegistry(ctx context.Context) { log.Println("KeeperRegistry at:", registryAddr) } -// getRegistry20 attaches to an existing 2.0 registry and possibly updates registry config func (k *Keeper) getRegistry20(ctx context.Context) (common.Address, *registry20.KeeperRegistry) { registryAddr := common.HexToAddress(k.cfg.RegistryAddress) keeperRegistry20, err := registry20.NewKeeperRegistry( @@ -363,7 +77,6 @@ func (k *Keeper) getRegistry20(ctx context.Context) (common.Address, *registry20 return registryAddr, keeperRegistry20 } -// getRegistry21 attaches to an existing 2.1 registry and possibly updates registry config func (k *Keeper) getRegistry21(ctx context.Context) (common.Address, *iregistry21.IKeeperRegistryMaster) { registryAddr := common.HexToAddress(k.cfg.RegistryAddress) keeperRegistry21, err := iregistry21.NewIKeeperRegistryMaster( @@ -380,269 +93,11 @@ func (k *Keeper) getRegistry21(ctx context.Context) (common.Address, *iregistry2 return registryAddr, keeperRegistry21 } -// deployUpkeeps deploys upkeeps and funds upkeeps -func (k *Keeper) deployUpkeeps(ctx context.Context, registryAddr common.Address, deployer upkeepDeployer, existingCount int64) { - fmt.Println() - log.Println("Deploying upkeeps...") - var upkeepAddrs []common.Address - for i := existingCount; i < k.cfg.UpkeepCount+existingCount; i++ { - fmt.Println() - // Deploy - var upkeepAddr common.Address - var deployUpkeepTx *types.Transaction - var registerUpkeepTx *types.Transaction - var logUpkeepCounter *log_upkeep_counter_wrapper.LogUpkeepCounter - var checkData []byte - - switch k.cfg.UpkeepType { - case config.Conditional: - checkData = []byte(k.cfg.UpkeepCheckData) - var err error - if k.cfg.UpkeepAverageEligibilityCadence > 0 { - upkeepAddr, deployUpkeepTx, _, err = upkeep.DeployUpkeepPerformCounterRestrictive( - k.buildTxOpts(ctx), - k.client, - big.NewInt(k.cfg.UpkeepTestRange), - big.NewInt(k.cfg.UpkeepAverageEligibilityCadence), - ) - } else if k.cfg.VerifiableLoadTest { - upkeepAddr, deployUpkeepTx, _, err = verifiable_load_upkeep_wrapper.DeployVerifiableLoadUpkeep( - k.buildTxOpts(ctx), - k.client, - common.HexToAddress(k.cfg.Registrar), - k.cfg.UseArbBlockNumber, - ) - } else { - upkeepAddr, deployUpkeepTx, _, err = upkeep_counter_wrapper.DeployUpkeepCounter( - k.buildTxOpts(ctx), - k.client, - big.NewInt(k.cfg.UpkeepTestRange), - big.NewInt(k.cfg.UpkeepInterval), - ) - } - if err != nil { - log.Fatal(i, ": Deploy Upkeep failed - ", err) - } - k.waitDeployment(ctx, deployUpkeepTx) - log.Println(i, upkeepAddr.Hex(), ": Upkeep deployed - ", helpers.ExplorerLink(k.cfg.ChainID, deployUpkeepTx.Hash())) - registerUpkeepTx, err = deployer.RegisterUpkeep(k.buildTxOpts(ctx), - upkeepAddr, k.cfg.UpkeepGasLimit, k.fromAddr, checkData, []byte{}, - ) - if err != nil { - log.Fatal(i, upkeepAddr.Hex(), ": RegisterUpkeep failed - ", err) - } - case config.Mercury: - checkData = []byte(k.cfg.UpkeepCheckData) - var err error - if k.cfg.VerifiableLoadTest { - upkeepAddr, deployUpkeepTx, _, err = verifiable_load_streams_lookup_upkeep_wrapper.DeployVerifiableLoadStreamsLookupUpkeep( - k.buildTxOpts(ctx), - k.client, - common.HexToAddress(k.cfg.Registrar), - k.cfg.UseArbBlockNumber, - ) - } else { - upkeepAddr, deployUpkeepTx, _, err = streams_lookup_upkeep_wrapper.DeployStreamsLookupUpkeep( - k.buildTxOpts(ctx), - k.client, - big.NewInt(k.cfg.UpkeepTestRange), - big.NewInt(k.cfg.UpkeepInterval), - true, /* useArbBlock */ - true, /* staging */ - false, /* verify mercury response */ - ) - } - if err != nil { - log.Fatal(i, ": Deploy Upkeep failed - ", err) - } - k.waitDeployment(ctx, deployUpkeepTx) - log.Println(i, upkeepAddr.Hex(), ": Upkeep deployed - ", helpers.ExplorerLink(k.cfg.ChainID, deployUpkeepTx.Hash())) - registerUpkeepTx, err = deployer.RegisterUpkeep(k.buildTxOpts(ctx), - upkeepAddr, k.cfg.UpkeepGasLimit, k.fromAddr, checkData, []byte{}, - ) - if err != nil { - log.Fatal(i, upkeepAddr.Hex(), ": RegisterUpkeep failed - ", err) - } - case config.LogTrigger: - var err error - upkeepAddr, deployUpkeepTx, logUpkeepCounter, err = log_upkeep_counter_wrapper.DeployLogUpkeepCounter( - k.buildTxOpts(ctx), - k.client, - big.NewInt(k.cfg.UpkeepTestRange), - ) - if err != nil { - log.Fatal(i, ": Deploy Upkeep failed - ", err) - } - logTriggerConfigType := abi.MustNewType("tuple(address contractAddress, uint8 filterSelector, bytes32 topic0, bytes32 topic1, bytes32 topic2, bytes32 topic3)") - logTriggerConfig, err := abi.Encode(map[string]any{ - "contractAddress": upkeepAddr, - "filterSelector": 0, // no indexed topics filtered - "topic0": "0x3d53a39550e04688065827f3bb86584cb007ab9ebca7ebd528e7301c9c31eb5d", // event sig for Trigger() - "topic1": "0x", - "topic2": "0x", - "topic3": "0x", - }, logTriggerConfigType) - if err != nil { - log.Fatal("failed to encode log trigger config", err) - } - k.waitDeployment(ctx, deployUpkeepTx) - log.Println(i, upkeepAddr.Hex(), ": Upkeep deployed - ", helpers.ExplorerLink(k.cfg.ChainID, deployUpkeepTx.Hash())) - registerUpkeepTx, err = deployer.RegisterUpkeepV2(k.buildTxOpts(ctx), - upkeepAddr, k.cfg.UpkeepGasLimit, k.fromAddr, 1, []byte{}, logTriggerConfig, []byte{}, - ) - if err != nil { - log.Fatal(i, upkeepAddr.Hex(), ": RegisterUpkeep failed - ", err) - } - - // Start up log trigger cycle - logUpkeepStartTx, err := logUpkeepCounter.Start(k.buildTxOpts(ctx)) - if err != nil { - log.Fatal("failed to start log upkeep counter", err) - } - if err = k.waitTx(ctx, logUpkeepStartTx); err != nil { - log.Fatalf("Log upkeep Start() failed for upkeepId: %s, error is %s", upkeepAddr.Hex(), err.Error()) - } - log.Println(i, upkeepAddr.Hex(), ": Log upkeep successfully started - ", helpers.ExplorerLink(k.cfg.ChainID, logUpkeepStartTx.Hash())) - default: - log.Fatal("unexpected upkeep type") - } - - if err := k.waitTx(ctx, registerUpkeepTx); err != nil { - log.Fatalf("RegisterUpkeep failed for upkeepId: %s, error is %s", upkeepAddr.Hex(), err.Error()) - } - log.Println(i, upkeepAddr.Hex(), ": Upkeep registered - ", helpers.ExplorerLink(k.cfg.ChainID, registerUpkeepTx.Hash())) - - upkeepAddrs = append(upkeepAddrs, upkeepAddr) - } - - var upkeepGetter activeUpkeepGetter - upkeepCount := big.NewInt(k.cfg.UpkeepCount) // second arg in GetActiveUpkeepIds (on registry) - { - var err error - switch k.cfg.RegistryVersion { - case config.RegistryVersion2_0: - upkeepGetter, err = registry20.NewKeeperRegistry( - registryAddr, - k.client, - ) - case config.RegistryVersion2_1: - upkeepGetter, err = iregistry21.NewIKeeperRegistryMaster( - registryAddr, - k.client, - ) - default: - panic("unexpected registry address") - } - if err != nil { - log.Fatal("Registry failed: ", err) - } - } - - activeUpkeepIds := k.getActiveUpkeepIds(ctx, upkeepGetter, big.NewInt(existingCount), upkeepCount) - - for index, upkeepAddr := range upkeepAddrs { - // Approve - k.approveFunds(ctx, registryAddr) - - upkeepId := activeUpkeepIds[index] - - // Fund - addFundsTx, err := deployer.AddFunds(k.buildTxOpts(ctx), upkeepId, k.addFundsAmount) - if err != nil { - log.Fatal(upkeepId, upkeepAddr.Hex(), ": AddFunds failed - ", err) - } - - // Onchain transaction - if err := k.waitTx(ctx, addFundsTx); err != nil { - log.Fatalf("AddFunds failed for upkeepId: %s, and upkeepAddr: %s, error is: %s", upkeepId, upkeepAddr.Hex(), err.Error()) - } - - log.Println(upkeepId, upkeepAddr.Hex(), ": Upkeep funded - ", helpers.ExplorerLink(k.cfg.ChainID, addFundsTx.Hash())) - } - - // set administrative offchain config for mercury upkeeps - if (k.cfg.UpkeepType == config.Mercury || k.cfg.UpkeepType == config.LogTriggeredFeedLookup) && k.cfg.RegistryVersion == config.RegistryVersion2_1 { - reg21, err := iregistry21.NewIKeeperRegistryMaster(registryAddr, k.client) - if err != nil { - log.Fatalf("cannot create registry 2.1: %v", err) - } - v, err := reg21.TypeAndVersion(nil) - if err != nil { - log.Fatalf("failed to fetch type and version from registry 2.1: %v", err) - } - log.Printf("registry version is %s", v) - log.Printf("active upkeep ids: %v", activeUpkeepIds) - - adminBytes, err := json.Marshal(streams.UpkeepPrivilegeConfig{ - MercuryEnabled: true, - }) - if err != nil { - log.Fatalf("failed to marshal upkeep privilege config: %v", err) - } - - for _, id := range activeUpkeepIds { - tx, err2 := reg21.SetUpkeepPrivilegeConfig(k.buildTxOpts(ctx), id, adminBytes) - if err2 != nil { - log.Fatalf("failed to upkeep privilege config: %v", err2) - } - err2 = k.waitTx(ctx, tx) - if err2 != nil { - log.Fatalf("failed to wait for tx: %v", err2) - } - log.Printf("upkeep privilege config is set for %s", id.String()) - - info, err2 := reg21.GetUpkeep(nil, id) - if err2 != nil { - log.Fatalf("failed to fetch upkeep id %s from registry 2.1: %v", id, err2) - } - min, err2 := reg21.GetMinBalanceForUpkeep(nil, id) - if err2 != nil { - log.Fatalf("failed to fetch upkeep id %s from registry 2.1: %v", id, err2) - } - log.Printf(" Balance: %s", info.Balance) - log.Printf("Min Balance: %s", min.String()) - } - } - - fmt.Println() -} - -// setKeepers set the keeper list for a registry -func (k *Keeper) setKeepers(ctx context.Context, cls []cmd.HTTPClient, deployer keepersDeployer, keepers, owners []common.Address) { - if len(keepers) > 0 { - log.Println("Set keepers...") - opts := k.buildTxOpts(ctx) - setKeepersTx, err := deployer.SetKeepers(ctx, opts, cls, keepers, owners) - if err != nil { - log.Fatal("SetKeepers failed: ", err) - } - - if err = k.waitTx(ctx, setKeepersTx); err != nil { - log.Fatalf("SetKeepers failed, error is: %s", err.Error()) - } - - log.Println("Keepers registered:", helpers.ExplorerLink(k.cfg.ChainID, setKeepersTx.Hash())) - } else { - log.Println("No Keepers to register") - } -} - -func (k *Keeper) keepers() ([]common.Address, []common.Address) { - var addrs []common.Address - var fromAddrs []common.Address - for _, addr := range k.cfg.Keepers { - addrs = append(addrs, common.HexToAddress(addr)) - fromAddrs = append(fromAddrs, k.fromAddr) - } - return addrs, fromAddrs -} - type activeUpkeepGetter interface { Address() common.Address GetActiveUpkeepIDs(opts *bind.CallOpts, startIndex *big.Int, maxCount *big.Int) ([]*big.Int, error) } -// getActiveUpkeepIds retrieves active upkeep ids from registry func (k *Keeper) getActiveUpkeepIds(ctx context.Context, registry activeUpkeepGetter, from, to *big.Int) []*big.Int { activeUpkeepIds, _ := registry.GetActiveUpkeepIDs(&bind.CallOpts{ Pending: false, diff --git a/core/scripts/chaincli/handler/keeper_deployer.go b/core/scripts/chaincli/handler/keeper_deployer.go deleted file mode 100644 index 08cfe0c7692..00000000000 --- a/core/scripts/chaincli/handler/keeper_deployer.go +++ /dev/null @@ -1,340 +0,0 @@ -package handler - -import ( - "context" - "crypto/ed25519" - "encoding/hex" - "encoding/json" - "errors" - "fmt" - "math/big" - "strings" - "sync" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/umbracle/ethgo/abi" - - ocr2config "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" - "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" - ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - - "github.com/smartcontractkit/chainlink/core/scripts/chaincli/config" - - offchain20config "github.com/smartcontractkit/chainlink-automation/pkg/v2/config" - - iregistry21 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1" - registry20 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper2_0" - "github.com/smartcontractkit/chainlink/v2/core/cmd" -) - -// canceller describes the behavior to cancel upkeeps -type canceller interface { - CancelUpkeep(opts *bind.TransactOpts, id *big.Int) (*types.Transaction, error) - WithdrawFunds(opts *bind.TransactOpts, id *big.Int, to common.Address) (*types.Transaction, error) - RecoverFunds(opts *bind.TransactOpts) (*types.Transaction, error) -} - -// upkeepDeployer contains functions needed to deploy an upkeep -type upkeepDeployer interface { - RegisterUpkeep(opts *bind.TransactOpts, target common.Address, gasLimit uint32, admin common.Address, checkData []byte, offchainConfig []byte) (*types.Transaction, error) - RegisterUpkeepV2(opts *bind.TransactOpts, target common.Address, gasLimit uint32, admin common.Address, triggerType uint8, pipelineData []byte, triggerConfig []byte, offchainConfig []byte) (*types.Transaction, error) - AddFunds(opts *bind.TransactOpts, id *big.Int, amount *big.Int) (*types.Transaction, error) -} - -// keepersDeployer contains functions needed to deploy keepers -type keepersDeployer interface { - canceller - upkeepDeployer - SetKeepers(ctx context.Context, opts *bind.TransactOpts, _ []cmd.HTTPClient, keepers []common.Address, payees []common.Address) (*types.Transaction, error) -} - -type v20KeeperDeployer struct { - registry20.KeeperRegistryInterface - cfg *config.Config -} - -func (d *v20KeeperDeployer) SetKeepers(ctx context.Context, opts *bind.TransactOpts, cls []cmd.HTTPClient, keepers []common.Address, _ []common.Address) (*types.Transaction, error) { - S := make([]int, len(cls)) - oracleIdentities := make([]ocr2config.OracleIdentityExtra, len(cls)) - sharedSecretEncryptionPublicKeys := make([]ocr2types.ConfigEncryptionPublicKey, len(cls)) - var wg sync.WaitGroup - for i, cl := range cls { - wg.Add(1) - go func(i int, cl cmd.HTTPClient) { - defer wg.Done() - - ocr2Config, err := getNodeOCR2Config(ctx, cl) - if err != nil { - panic(err) - } - - p2pKeyID, err := getP2PKeyID(ctx, cl) - if err != nil { - panic(err) - } - - offchainPkBytes, err := hex.DecodeString(strings.TrimPrefix(ocr2Config.OffChainPublicKey, "ocr2off_evm_")) - if err != nil { - panic(fmt.Errorf("failed to decode %s: %w", ocr2Config.OffChainPublicKey, err)) - } - - offchainPkBytesFixed := [ed25519.PublicKeySize]byte{} - n := copy(offchainPkBytesFixed[:], offchainPkBytes) - if n != ed25519.PublicKeySize { - panic(errors.New("wrong num elements copied")) - } - - configPkBytes, err := hex.DecodeString(strings.TrimPrefix(ocr2Config.ConfigPublicKey, "ocr2cfg_evm_")) - if err != nil { - panic(fmt.Errorf("failed to decode %s: %w", ocr2Config.ConfigPublicKey, err)) - } - - configPkBytesFixed := [ed25519.PublicKeySize]byte{} - n = copy(configPkBytesFixed[:], configPkBytes) - if n != ed25519.PublicKeySize { - panic(errors.New("wrong num elements copied")) - } - - onchainPkBytes, err := hex.DecodeString(strings.TrimPrefix(ocr2Config.OnchainPublicKey, "ocr2on_evm_")) - if err != nil { - panic(fmt.Errorf("failed to decode %s: %w", ocr2Config.OnchainPublicKey, err)) - } - - sharedSecretEncryptionPublicKeys[i] = configPkBytesFixed - oracleIdentities[i] = ocr2config.OracleIdentityExtra{ - OracleIdentity: ocr2config.OracleIdentity{ - OnchainPublicKey: onchainPkBytes, - OffchainPublicKey: offchainPkBytesFixed, - PeerID: p2pKeyID, - TransmitAccount: ocr2types.Account(keepers[i].String()), - }, - ConfigEncryptionPublicKey: configPkBytesFixed, - } - S[i] = 1 - }(i, cl) - } - wg.Wait() - - offC, err := json.Marshal(offchain20config.OffchainConfig{ - PerformLockoutWindow: 100 * 3 * 1000, // ~100 block lockout (on mumbai) - MinConfirmations: 1, - }) - if err != nil { - panic(err) - } - - signerOnchainPublicKeys, transmitterAccounts, f, _, offchainConfigVersion, offchainConfig, err := ocr2config.ContractSetConfigArgsForTests( - 5*time.Second, // deltaProgress time.Duration, - 10*time.Second, // deltaResend time.Duration, - 2500*time.Millisecond, // deltaRound time.Duration, - 40*time.Millisecond, // deltaGrace time.Duration, - 30*time.Second, // deltaStage time.Duration, - 50, // rMax uint8, - S, // s []int, - oracleIdentities, // oracles []OracleIdentityExtra, - offC, // reportingPluginConfig []byte, - nil, - 20*time.Millisecond, // maxDurationQuery time.Duration, - 1600*time.Millisecond, // maxDurationObservation time.Duration, - 800*time.Millisecond, // maxDurationReport time.Duration, sum of MaxDurationQuery/Observation/Report must be less than DeltaProgress - 20*time.Millisecond, // maxDurationShouldAcceptFinalizedReport time.Duration, - 20*time.Millisecond, // maxDurationShouldTransmitAcceptedReport time.Duration, - 1, // f int, - nil, // onchainConfig []byte, - ) - if err != nil { - return nil, err - } - - var signers []common.Address - for _, signer := range signerOnchainPublicKeys { - if len(signer) != 20 { - return nil, errors.New("OnChainPublicKey has wrong length for address") - } - signers = append(signers, common.BytesToAddress(signer)) - } - - var transmitters []common.Address - for _, transmitter := range transmitterAccounts { - if !common.IsHexAddress(string(transmitter)) { - return nil, errors.New("TransmitAccount is not a valid Ethereum address") - } - transmitters = append(transmitters, common.HexToAddress(string(transmitter))) - } - - configType := abi.MustNewType("tuple(uint32 paymentPremiumPPB,uint32 flatFeeMicroLink,uint32 checkGasLimit,uint24 stalenessSeconds,uint16 gasCeilingMultiplier,uint96 minUpkeepSpend,uint32 maxPerformGas,uint32 maxCheckDataSize,uint32 maxPerformDataSize,uint256 fallbackGasPrice,uint256 fallbackLinkPrice,address transcoder,address registrar)") - onchainConfig, err := abi.Encode(map[string]any{ - "paymentPremiumPPB": d.cfg.PaymentPremiumPBB, - "flatFeeMicroLink": d.cfg.FlatFeeMicroLink, - "checkGasLimit": d.cfg.CheckGasLimit, - "stalenessSeconds": d.cfg.StalenessSeconds, - "gasCeilingMultiplier": d.cfg.GasCeilingMultiplier, - "minUpkeepSpend": d.cfg.MinUpkeepSpend, - "maxPerformGas": d.cfg.MaxPerformGas, - "maxCheckDataSize": d.cfg.MaxCheckDataSize, - "maxPerformDataSize": d.cfg.MaxPerformDataSize, - "fallbackGasPrice": big.NewInt(d.cfg.FallbackGasPrice), - "fallbackLinkPrice": big.NewInt(d.cfg.FallbackLinkPrice), - "transcoder": common.HexToAddress(d.cfg.Transcoder), - "registrar": common.HexToAddress(d.cfg.Registrar), - }, configType) - if err != nil { - return nil, err - } - - return d.SetConfig(opts, signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) -} - -func (d *v20KeeperDeployer) RegisterUpkeepV2(opts *bind.TransactOpts, target common.Address, gasLimit uint32, admin common.Address, triggerType uint8, pipelineData []byte, triggerConfig []byte, offchainConfig []byte) (*types.Transaction, error) { - panic("not implemented") -} - -type v21KeeperDeployer struct { - iregistry21.IKeeperRegistryMasterInterface - cfg *config.Config -} - -func (d *v21KeeperDeployer) SetKeepers(ctx context.Context, opts *bind.TransactOpts, cls []cmd.HTTPClient, keepers []common.Address, _ []common.Address) (*types.Transaction, error) { - S := make([]int, len(cls)) - oracleIdentities := make([]ocr2config.OracleIdentityExtra, len(cls)) - sharedSecretEncryptionPublicKeys := make([]ocr2types.ConfigEncryptionPublicKey, len(cls)) - var wg sync.WaitGroup - for i, cl := range cls { - wg.Add(1) - go func(i int, cl cmd.HTTPClient) { - defer wg.Done() - - ocr2Config, err := getNodeOCR2Config(ctx, cl) - if err != nil { - panic(err) - } - - p2pKeyID, err := getP2PKeyID(ctx, cl) - if err != nil { - panic(err) - } - - offchainPkBytes, err := hex.DecodeString(strings.TrimPrefix(ocr2Config.OffChainPublicKey, "ocr2off_evm_")) - if err != nil { - panic(fmt.Errorf("failed to decode %s: %w", ocr2Config.OffChainPublicKey, err)) - } - - offchainPkBytesFixed := [ed25519.PublicKeySize]byte{} - n := copy(offchainPkBytesFixed[:], offchainPkBytes) - if n != ed25519.PublicKeySize { - panic(errors.New("wrong num elements copied")) - } - - configPkBytes, err := hex.DecodeString(strings.TrimPrefix(ocr2Config.ConfigPublicKey, "ocr2cfg_evm_")) - if err != nil { - panic(fmt.Errorf("failed to decode %s: %w", ocr2Config.ConfigPublicKey, err)) - } - - configPkBytesFixed := [ed25519.PublicKeySize]byte{} - n = copy(configPkBytesFixed[:], configPkBytes) - if n != ed25519.PublicKeySize { - panic(errors.New("wrong num elements copied")) - } - - onchainPkBytes, err := hex.DecodeString(strings.TrimPrefix(ocr2Config.OnchainPublicKey, "ocr2on_evm_")) - if err != nil { - panic(fmt.Errorf("failed to decode %s: %w", ocr2Config.OnchainPublicKey, err)) - } - - sharedSecretEncryptionPublicKeys[i] = configPkBytesFixed - oracleIdentities[i] = ocr2config.OracleIdentityExtra{ - OracleIdentity: ocr2config.OracleIdentity{ - OnchainPublicKey: onchainPkBytes, - OffchainPublicKey: offchainPkBytesFixed, - PeerID: p2pKeyID, - TransmitAccount: ocr2types.Account(keepers[i].String()), - }, - ConfigEncryptionPublicKey: configPkBytesFixed, - } - S[i] = 1 - }(i, cl) - } - wg.Wait() - - offC, err := json.Marshal(offchain20config.OffchainConfig{ - PerformLockoutWindow: 100 * 3 * 1000, // ~100 block lockout (on mumbai) - MinConfirmations: 1, - MercuryLookup: d.cfg.UpkeepType == config.Mercury || d.cfg.UpkeepType == config.LogTriggeredFeedLookup, - }) - if err != nil { - panic(err) - } - - signerOnchainPublicKeys, transmitterAccounts, f, _, offchainConfigVersion, offchainConfig, err := ocr3confighelper.ContractSetConfigArgsForTests( - 5*time.Second, // deltaProgress time.Duration, - 10*time.Second, // deltaResend time.Duration, - 400*time.Millisecond, // deltaInitial time.Duration, - 2500*time.Millisecond, // deltaRound time.Duration, - 40*time.Millisecond, // deltaGrace time.Duration, - 300*time.Millisecond, // deltaCertifiedCommitRequest time.Duration, - 30*time.Second, // deltaStage time.Duration, - 50, // rMax uint8, - S, // s []int, - oracleIdentities, // oracles []OracleIdentityExtra, - offC, // reportingPluginConfig []byte, - nil, - 20*time.Millisecond, // maxDurationQuery time.Duration, - 1600*time.Millisecond, // maxDurationObservation time.Duration, - 20*time.Millisecond, // maxDurationShouldAcceptFinalizedReport time.Duration, - 20*time.Millisecond, // maxDurationShouldTransmitAcceptedReport time.Duration, - 1, // f int, - nil, // onchainConfig []byte, - ) - if err != nil { - return nil, err - } - - var signers []common.Address - for _, signer := range signerOnchainPublicKeys { - if len(signer) != 20 { - return nil, errors.New("OnChainPublicKey has wrong length for address") - } - signers = append(signers, common.BytesToAddress(signer)) - } - - var transmitters []common.Address - for _, transmitter := range transmitterAccounts { - if !common.IsHexAddress(string(transmitter)) { - return nil, errors.New("TransmitAccount is not a valid Ethereum address") - } - transmitters = append(transmitters, common.HexToAddress(string(transmitter))) - } - - onchainConfig := iregistry21.IAutomationV21PlusCommonOnchainConfigLegacy{ - PaymentPremiumPPB: d.cfg.PaymentPremiumPBB, - FlatFeeMicroLink: d.cfg.FlatFeeMicroLink, - CheckGasLimit: d.cfg.CheckGasLimit, - StalenessSeconds: big.NewInt(d.cfg.StalenessSeconds), - GasCeilingMultiplier: d.cfg.GasCeilingMultiplier, - MinUpkeepSpend: big.NewInt(d.cfg.MinUpkeepSpend), - MaxPerformGas: d.cfg.MaxPerformGas, - MaxCheckDataSize: d.cfg.MaxCheckDataSize, - MaxPerformDataSize: d.cfg.MaxPerformDataSize, - MaxRevertDataSize: d.cfg.MaxRevertDataSize, - FallbackGasPrice: big.NewInt(d.cfg.FallbackGasPrice), - FallbackLinkPrice: big.NewInt(d.cfg.FallbackLinkPrice), - Transcoder: common.HexToAddress(d.cfg.Transcoder), - Registrars: []common.Address{common.HexToAddress(d.cfg.Registrar)}, - UpkeepPrivilegeManager: common.HexToAddress(d.cfg.UpkeepPrivilegeManager), - } - - return d.SetConfigTypeSafe(opts, signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) -} - -// legacy support function -func (d *v21KeeperDeployer) RegisterUpkeep(opts *bind.TransactOpts, target common.Address, gasLimit uint32, admin common.Address, checkData []byte, offchainConfig []byte) (*types.Transaction, error) { - return d.RegisterUpkeep0(opts, target, gasLimit, admin, checkData, offchainConfig) -} - -// the new registerUpkeep function only available on version 2.1 and above -func (d *v21KeeperDeployer) RegisterUpkeepV2(opts *bind.TransactOpts, target common.Address, gasLimit uint32, admin common.Address, triggerType uint8, pipelineData []byte, triggerConfig []byte, offchainConfig []byte) (*types.Transaction, error) { - return d.IKeeperRegistryMasterInterface.RegisterUpkeep(opts, target, gasLimit, admin, triggerType, pipelineData, triggerConfig, offchainConfig) -} diff --git a/core/scripts/chaincli/handler/keeper_launch.go b/core/scripts/chaincli/handler/keeper_launch.go deleted file mode 100644 index a44fc43cd5f..00000000000 --- a/core/scripts/chaincli/handler/keeper_launch.go +++ /dev/null @@ -1,359 +0,0 @@ -package handler - -import ( - "bytes" - "context" - "encoding/json" - "errors" - "fmt" - "io" - "log" - "math/big" - "net/url" - "os" - "os/signal" - "strconv" - "sync" - "syscall" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - - "github.com/smartcontractkit/chainlink-common/keystore" - "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" - - "github.com/smartcontractkit/chainlink-common/keystore/corekeys/ethkey" - iregistry21 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1" - registry20 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper2_0" - "github.com/smartcontractkit/chainlink/core/scripts/chaincli/config" - "github.com/smartcontractkit/chainlink/v2/core/cmd" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/web" -) - -type startedNodeData struct { - url string - cleanup func(bool) -} - -// LaunchAndTest launches keeper registry, chainlink nodes, upkeeps and start performing. -// 1. launch chainlink node using docker image -// 2. get keeper registry instance, deploy if needed -// 3. deploy upkeeps -// 4. create keeper jobs -// 5. fund nodes if needed -// 6. set keepers in the registry -// 7. withdraw funds after tests are done -> TODO: wait until tests are done instead of cancel manually -func (k *Keeper) LaunchAndTest(ctx context.Context, withdraw, printLogs, force, bootstrap bool) { - lggr, closeLggr := logger.NewLogger() - logger.Sugared(lggr).ErrorIfFn(closeLggr, "Failed to close logger") - - if bootstrap { - baseHandler := NewBaseHandler(k.cfg) - tcpAddr := baseHandler.StartBootstrapNode(ctx, k.cfg.RegistryAddress, 5688, 8000, force) - k.cfg.BootstrapNodeAddr = tcpAddr - } - - var extraTOML string - if k.cfg.OCR2Keepers { - extraTOML = "[P2P]\n[P2P.V2]\nListenAddresses = [\"0.0.0.0:8000\"]" - } - - // Run chainlink nodes and create jobs - startedNodes := make([]startedNodeData, k.cfg.KeepersCount) - var wg sync.WaitGroup - for i := 0; i < k.cfg.KeepersCount; i++ { - wg.Add(1) - go func(i int) { - defer wg.Done() - - startedNodes[i] = startedNodeData{} - - // Run chainlink node - var err error - if startedNodes[i].url, startedNodes[i].cleanup, err = k.launchChainlinkNode(ctx, 6688+i, fmt.Sprintf("keeper-%d", i), extraTOML, force); err != nil { - log.Fatal("Failed to start node: ", err) - } - }(i) - } - wg.Wait() - - // Deploy keeper registry or get an existing one - upkeepCount, registryAddr, deployer := k.prepareRegistry(ctx) - - // Approve keeper registry - k.approveFunds(ctx, registryAddr) - - // Prepare keeper addresses and owners - var keepers []common.Address - var owners []common.Address - var cls []cmd.HTTPClient - for i, startedNode := range startedNodes { - // Create authenticated client - var cl cmd.HTTPClient - var err error - cl, err = authenticate(ctx, startedNode.url, defaultChainlinkNodeLogin, defaultChainlinkNodePassword, lggr) - if err != nil { - log.Fatal("Authentication failed, ", err) - } - - var nodeAddrHex string - - if len(k.cfg.KeeperKeys) > 0 { - // import key if exists - nodeAddrHex, err = k.addKeyToKeeper(ctx, cl, k.cfg.KeeperKeys[i]) - if err != nil { - log.Fatal("could not add key to keeper", err) - } - } else { - // get node's default wallet address - nodeAddrHex, err = getNodeAddress(ctx, cl) - if err != nil { - log.Println("Failed to get node addr: ", err) - continue - } - } - - nodeAddr := common.HexToAddress(nodeAddrHex) - - // Create keepers - if err = k.createKeeperJob(ctx, cl, registryAddr.Hex(), nodeAddr.Hex()); err != nil { - log.Println("Failed to create keeper job: ", err) - continue - } - - // Fund node if needed - fundAmt, ok := (&big.Int{}).SetString(k.cfg.FundNodeAmount, 10) - if !ok { - log.Printf("failed to parse FUND_CHAINLINK_NODE: %s", k.cfg.FundNodeAmount) - continue - } - if fundAmt.Cmp(big.NewInt(0)) != 0 { - if err = k.sendEth(ctx, nodeAddr, fundAmt); err != nil { - log.Println("Failed to fund chainlink node: ", err) - continue - } - } - - cls = append(cls, cl) - keepers = append(keepers, nodeAddr) - owners = append(owners, k.fromAddr) - } - - if len(keepers) == 0 { - log.Fatal("no keepers available") - } - - // Set Keepers - k.setKeepers(ctx, cls, deployer, keepers, owners) - - // Deploy Upkeeps - k.deployUpkeeps(ctx, registryAddr, deployer, upkeepCount) - - log.Println("All nodes successfully launched, now running. Use Ctrl+C to terminate") - - termChan := make(chan os.Signal, 1) - signal.Notify(termChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) - <-termChan // Blocks here until either SIGINT or SIGTERM is received. - log.Println("Stopping...") - - // Cleanup resources - for _, startedNode := range startedNodes { - if startedNode.cleanup != nil { - startedNode.cleanup(printLogs) - } - } - - // Cancel upkeeps and withdraw funds - if withdraw { - log.Println("Canceling upkeeps...") - switch k.cfg.RegistryVersion { - case config.RegistryVersion2_0: - registry, err := registry20.NewKeeperRegistry( - registryAddr, - k.client, - ) - if err != nil { - log.Fatal("Registry failed: ", err) - } - - activeUpkeepIds := k.getActiveUpkeepIds(ctx, registry, big.NewInt(0), big.NewInt(0)) - if err := k.cancelAndWithdrawActiveUpkeeps(ctx, activeUpkeepIds, deployer); err != nil { - log.Fatal("Failed to cancel upkeeps: ", err) - } - case config.RegistryVersion2_1: - registry, err := iregistry21.NewIKeeperRegistryMaster( - registryAddr, - k.client, - ) - if err != nil { - log.Fatal("Registry failed: ", err) - } - activeUpkeepIds := k.getActiveUpkeepIds(ctx, registry, big.NewInt(0), big.NewInt(0)) - if err := k.cancelAndWithdrawActiveUpkeeps(ctx, activeUpkeepIds, deployer); err != nil { - log.Fatal("Failed to cancel upkeeps: ", err) - } - default: - panic("unexpected registry address") - } - log.Println("Upkeeps successfully canceled") - } -} - -// cancelAndWithdrawActiveUpkeeps cancels all active upkeeps and withdraws funds via the registry canceller interface. -func (k *Keeper) cancelAndWithdrawActiveUpkeeps(ctx context.Context, activeUpkeepIds []*big.Int, canceller canceller) error { - for i := range activeUpkeepIds { - upkeepId := activeUpkeepIds[i] - tx, err := canceller.CancelUpkeep(k.buildTxOpts(ctx), upkeepId) - if err != nil { - return fmt.Errorf("failed to cancel upkeep %s: %w", upkeepId.String(), err) - } - - if err = k.waitTx(ctx, tx); err != nil { - log.Fatalf("failed to cancel upkeep for upkeepId: %s, error is: %s", upkeepId.String(), err.Error()) - } - - tx, err = canceller.WithdrawFunds(k.buildTxOpts(ctx), upkeepId, k.fromAddr) - if err != nil { - return fmt.Errorf("failed to withdraw upkeep %s: %w", upkeepId.String(), err) - } - - if err = k.waitTx(ctx, tx); err != nil { - log.Fatalf("failed to withdraw upkeep for upkeepId: %s, error is: %s", upkeepId.String(), err.Error()) - } - - log.Printf("Upkeep %s successfully canceled and refunded: ", upkeepId.String()) - } - - tx, err := canceller.RecoverFunds(k.buildTxOpts(ctx)) - if err != nil { - return fmt.Errorf("failed to recover funds: %w", err) - } - - if err = k.waitTx(ctx, tx); err != nil { - log.Fatalf("failed to recover funds, error is: %s", err.Error()) - } - - return nil -} - -// createKeeperJob creates a keeper job in the chainlink node by the given address -func (k *Keeper) createKeeperJob(ctx context.Context, client cmd.HTTPClient, registryAddr, nodeAddr string) error { - if !k.cfg.OCR2Keepers { - return errors.New("legacy keeper jobs are no longer supported; set KEEPER_OCR2=true and configure OCR2 automation") - } - if err := k.createOCR2KeeperJob(ctx, client, registryAddr, nodeAddr); err != nil { - return err - } - log.Println("Keeper job has been successfully created in the Chainlink node with address: ", nodeAddr) - return nil -} - -const ocr2keeperJobTemplate = `type = "offchainreporting2" -pluginType = "ocr2automation" -relay = "evm" -name = "ocr2-automation" -forwardingAllowed = false -schemaVersion = 1 -contractID = "%s" -contractConfigTrackerPollInterval = "15s" -ocrKeyBundleID = "%s" -transmitterID = "%s" -p2pv2Bootstrappers = [ - "%s" -] - -[relayConfig] -chainID = %d - -[pluginConfig] -maxServiceWorkers = 100 -cacheEvictionInterval = "1s" -contractVersion = "%s" -mercuryCredentialName = "%s"` - -// createOCR2KeeperJob creates an ocr2keeper job in the chainlink node by the given address -func (k *Keeper) createOCR2KeeperJob(ctx context.Context, client cmd.HTTPClient, contractAddr, nodeAddr string) error { - ocr2KeyConfig, err := getNodeOCR2Config(ctx, client) - if err != nil { - return fmt.Errorf("failed to get node OCR2 key bundle ID: %w", err) - } - - // Correctly assign contract version in OCR job spec. - contractVersion := "v2.0" - if k.cfg.RegistryVersion == config.RegistryVersion2_1 { - contractVersion = "v2.1" - } - - request, err := json.Marshal(web.CreateJobRequest{ - TOML: fmt.Sprintf(ocr2keeperJobTemplate, - contractAddr, // contractID - ocr2KeyConfig.ID, // ocrKeyBundleID - nodeAddr, // transmitterID - node wallet address - k.cfg.BootstrapNodeAddr, // bootstrap node key and address - k.cfg.ChainID, // chainID - contractVersion, // contractVersion - k.cfg.DataStreamsCredName, // mercury credential name - ), - }) - if err != nil { - return fmt.Errorf("failed to marshal request: %w", err) - } - - resp, err := client.Post(ctx, "/v2/jobs", bytes.NewReader(request)) - if err != nil { - return fmt.Errorf("failed to create ocr2keeper job: %w", err) - } - defer resp.Body.Close() - - if resp.StatusCode >= 400 { - body, err := io.ReadAll(resp.Body) - if err != nil { - return fmt.Errorf("failed to read error response body: %w", err) - } - - return fmt.Errorf("unable to create ocr2keeper job: '%v' [%d]", string(body), resp.StatusCode) - } - - return nil -} - -// addKeyToKeeper imports the provided ETH sending key to the keeper -func (k *Keeper) addKeyToKeeper(ctx context.Context, client cmd.HTTPClient, privKeyHex string) (string, error) { - privkey, err := crypto.HexToECDSA(hex.TrimPrefix(privKeyHex)) - if err != nil { - log.Fatalf("Failed to decode priv key %s: %v", privKeyHex, err) - } - address := crypto.PubkeyToAddress(privkey.PublicKey).Hex() - log.Printf("importing keeper key %s", address) - keyJSON, err := ethkey.FromPrivateKey(privkey).ToEncryptedJSON(defaultChainlinkNodePassword, keystore.FastScryptParams) - if err != nil { - log.Fatalf("Failed to encrypt piv key %s: %v", privKeyHex, err) - } - importUrl := url.URL{ - Path: "/v2/keys/evm/import", - } - query := importUrl.Query() - - query.Set("oldpassword", defaultChainlinkNodePassword) - query.Set("evmChainID", strconv.FormatInt(k.cfg.ChainID, 10)) - - importUrl.RawQuery = query.Encode() - resp, err := client.Post(ctx, importUrl.String(), bytes.NewReader(keyJSON)) - if err != nil { - log.Fatalf("Failed to import priv key %s: %v", privKeyHex, err) - } - - defer resp.Body.Close() - - if resp.StatusCode >= 400 { - body, err := io.ReadAll(resp.Body) - if err != nil { - return "", fmt.Errorf("failed to read error response body: %w", err) - } - - return "", fmt.Errorf("unable to create ocr2keeper job: '%v' [%d]", string(body), resp.StatusCode) - } - - return address, nil -} diff --git a/core/scripts/chaincli/handler/keeper_upkeep_history.go b/core/scripts/chaincli/handler/keeper_upkeep_history.go deleted file mode 100644 index c8665cba4f4..00000000000 --- a/core/scripts/chaincli/handler/keeper_upkeep_history.go +++ /dev/null @@ -1,14 +0,0 @@ -package handler - -import ( - "context" - "log" - "math/big" -) - -// UpkeepHistory prints the checkUpkeep status and keeper responsibility for a given upkeep in a set block range. -// Legacy keeper registry 1.1/1.2 support has been removed. -func (k *Keeper) UpkeepHistory(ctx context.Context, upkeepId *big.Int, from, to, gasPrice uint64) { - _, _, _, _, _ = ctx, upkeepId, from, to, gasPrice - log.Fatal("upkeep-history was only implemented for keeper registry 1.1/1.2, which are no longer supported") -} diff --git a/core/scripts/chaincli/handler/keeper_withdraw.go b/core/scripts/chaincli/handler/keeper_withdraw.go index 151acd7a5ba..407bd7d3416 100644 --- a/core/scripts/chaincli/handler/keeper_withdraw.go +++ b/core/scripts/chaincli/handler/keeper_withdraw.go @@ -2,16 +2,25 @@ package handler import ( "context" + "fmt" "log" "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" registry20 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_registry_wrapper2_0" "github.com/smartcontractkit/chainlink/core/scripts/chaincli/config" ) +type canceller interface { + CancelUpkeep(opts *bind.TransactOpts, id *big.Int) (*types.Transaction, error) + WithdrawFunds(opts *bind.TransactOpts, id *big.Int, to common.Address) (*types.Transaction, error) + RecoverFunds(opts *bind.TransactOpts) (*types.Transaction, error) +} + // Withdraw takes a keeper registry address, cancels all upkeeps and withdraws the funds func (k *Keeper) Withdraw(ctx context.Context, hexAddr string) { registryAddr := common.HexToAddress(hexAddr) @@ -36,3 +45,39 @@ func (k *Keeper) Withdraw(ctx context.Context, hexAddr string) { } log.Println("Upkeeps successfully canceled") } + +func (k *Keeper) cancelAndWithdrawActiveUpkeeps(ctx context.Context, activeUpkeepIds []*big.Int, canceller canceller) error { + for i := range activeUpkeepIds { + upkeepId := activeUpkeepIds[i] + tx, err := canceller.CancelUpkeep(k.buildTxOpts(ctx), upkeepId) + if err != nil { + return fmt.Errorf("failed to cancel upkeep %s: %w", upkeepId.String(), err) + } + + if err = k.waitTx(ctx, tx); err != nil { + log.Fatalf("failed to cancel upkeep for upkeepId: %s, error is: %s", upkeepId.String(), err.Error()) + } + + tx, err = canceller.WithdrawFunds(k.buildTxOpts(ctx), upkeepId, k.fromAddr) + if err != nil { + return fmt.Errorf("failed to withdraw upkeep %s: %w", upkeepId.String(), err) + } + + if err = k.waitTx(ctx, tx); err != nil { + log.Fatalf("failed to withdraw upkeep for upkeepId: %s, error is: %s", upkeepId.String(), err.Error()) + } + + log.Printf("Upkeep %s successfully canceled and refunded: ", upkeepId.String()) + } + + tx, err := canceller.RecoverFunds(k.buildTxOpts(ctx)) + if err != nil { + return fmt.Errorf("failed to recover funds: %w", err) + } + + if err = k.waitTx(ctx, tx); err != nil { + log.Fatalf("failed to recover funds, error is: %s", err.Error()) + } + + return nil +} diff --git a/core/scripts/chaincli/handler/upkeep_util.go b/core/scripts/chaincli/handler/upkeep_util.go deleted file mode 100644 index 39e190e0eaf..00000000000 --- a/core/scripts/chaincli/handler/upkeep_util.go +++ /dev/null @@ -1,33 +0,0 @@ -package handler - -import ( - "math" - "math/big" - "strings" - - ethmath "github.com/ethereum/go-ethereum/common/math" -) - -const ( - zeroPrefix = "0x" - upkeepPrefix = "UPx" -) - -// LeastSignificant32 returns the least significant 32 bits of the input as a uint64. -func LeastSignificant32(num *big.Int) uint64 { - max32 := big.NewInt(math.MaxUint32) - return big.NewInt(0).And(num, max32).Uint64() -} - -// ParseUpkeepID parses the upkeep id input string to a big int pointer. -func ParseUpkeepID(upkeepIDStr string) (*big.Int, bool) { - if strings.HasPrefix(upkeepIDStr, upkeepPrefix) { - upkeepIDStr = zeroPrefix + upkeepIDStr[len(upkeepPrefix):] - } - - upkeepID, ok := ethmath.ParseBig256(upkeepIDStr) - if !ok { - return ethmath.ParseBig256(zeroPrefix + upkeepIDStr) - } - return upkeepID, ok -} diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 9354a4c8f42..9ae99b58648 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -62,7 +62,6 @@ require ( github.com/spf13/viper v1.21.0 github.com/stretchr/testify v1.11.1 github.com/tidwall/gjson v1.18.0 - github.com/umbracle/ethgo v0.1.3 github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 github.com/urfave/cli v1.22.17 go.uber.org/zap v1.28.0 diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 8938c996c0d..14ef3101fa8 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -106,8 +106,6 @@ github.com/NethermindEth/juno v0.12.5 h1:a+KYQg8MxzNJIbbqGHq+vU9nTyuWu3acbyXxcUP github.com/NethermindEth/juno v0.12.5/go.mod h1:XonWmZVRwCVHv1gjoVCoTFiZnYObwdukpd3NCsl04bA= github.com/NethermindEth/starknet.go v0.8.0 h1:mGh7qDWrvuXJPcgGJP31DpifzP6+Ef2gt/BQhaqsV40= github.com/NethermindEth/starknet.go v0.8.0/go.mod h1:slNA8PxtxA/0LQv0FwHnL3lHFDNhVZfTK6U2gjVb7l8= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260416073033-7c2071eaa8d4 h1:/97whAzwYxMNHXeTfhAtCRzNCpyblmxCtSYpsfzCszM= github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260416073033-7c2071eaa8d4/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI= github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw= @@ -1354,8 +1352,6 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= -github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss= -github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8= github.com/opencontainers/runtime-spec v1.3.0 h1:YZupQUdctfhpZy3TM39nN9Ika5CBWT5diQ8ibYCRkxg= github.com/opencontainers/runtime-spec v1.3.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.13.1 h1:A8nNeceYngH9Ow++M+VVEwJVpdFmrlxsN22F+ISDCJE= @@ -1363,8 +1359,6 @@ github.com/opencontainers/selinux v1.13.1/go.mod h1:S10WXZ/osk2kWOYKy1x2f/eXF5ZH github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU= -github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= -github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= github.com/otiai10/copy v1.14.1 h1:5/7E6qsUMBaH5AnQ0sSLzzTg1oTECmcCmT6lvF45Na8= github.com/otiai10/copy v1.14.1/go.mod h1:oQwrEDDOci3IM8dJF0d8+jnbfPDllW6vUjNc3DoZm9I= github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs= diff --git a/devenv/contracts/automation.go b/devenv/contracts/automation.go index eba1fab4a20..a66a481470f 100644 --- a/devenv/contracts/automation.go +++ b/devenv/contracts/automation.go @@ -87,27 +87,6 @@ func DeployUpkeepTranscoder(client *seth.Client) (*EthereumUpkeepTranscoder, err }, nil } -func LoadUpkeepTranscoder(client *seth.Client, address common.Address) (*EthereumUpkeepTranscoder, error) { - abi, err := upkeep_transcoder.UpkeepTranscoderMetaData.GetAbi() - if err != nil { - return &EthereumUpkeepTranscoder{}, fmt.Errorf("failed to get UpkeepTranscoder ABI: %w", err) - } - - client.ContractStore.AddABI("UpkeepTranscoder", *abi) - client.ContractStore.AddBIN("UpkeepTranscoder", common.FromHex(upkeep_transcoder.UpkeepTranscoderMetaData.Bin)) - - transcoder, err := upkeep_transcoder.NewUpkeepTranscoder(address, MustNewWrappedContractBackend(nil, client)) - if err != nil { - return &EthereumUpkeepTranscoder{}, fmt.Errorf("failed to instantiate UpkeepTranscoder instance: %w", err) - } - - return &EthereumUpkeepTranscoder{ - client: client, - transcoder: transcoder, - address: &address, - }, nil -} - // EthereumKeeperRegistry represents keeper registry contract type EthereumKeeperRegistry struct { client *seth.Client diff --git a/devenv/contracts/keeper.go b/devenv/contracts/keeper.go index 66178fd2ab1..56d6f9dd715 100644 --- a/devenv/contracts/keeper.go +++ b/devenv/contracts/keeper.go @@ -2,24 +2,18 @@ package contracts import ( "context" - "fmt" "math/big" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" goabi "github.com/umbracle/ethgo/abi" ac "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/automation_compatible_utils" registrar21 "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/automation_registrar_wrapper2_1" + "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/i_automation_registry_master_wrapper_2_2" "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/i_automation_registry_master_wrapper_2_3" "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/keeper_consumer_performance_wrapper" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/perform_data_checker_wrapper" cltypes "github.com/smartcontractkit/chainlink-evm/pkg/types" - "github.com/smartcontractkit/chainlink-testing-framework/seth" - - "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/i_automation_registry_master_wrapper_2_2" ) // AbigenLog is an interface for abigen generated log topics @@ -67,10 +61,6 @@ type KeeperRegistrar interface { RegisterUpkeepFromKey(keyNum int, name string, email []byte, upkeepAddr string, gasLimit uint32, adminAddr string, checkData []byte, amount *big.Int, wethTokenAddr string, isLogTrigger bool, isMercury bool) (*types.Transaction, error) } -type UpkeepTranscoder interface { - Address() string -} - type KeeperRegistry interface { Address() string Fund(ethAmount *big.Float) error @@ -128,17 +118,6 @@ type StaleUpkeepReportLog struct { ID *big.Int } -// KeeperConsumerPerformance is a keeper consumer contract that is more complicated than the typical consumer, -// it's intended to only be used for performance tests. -type KeeperConsumerPerformance interface { - Address() string - Fund(ethAmount *big.Float) error - CheckEligible(ctx context.Context) (bool, error) - GetUpkeepCount(ctx context.Context) (*big.Int, error) - SetCheckGasToBurn(ctx context.Context, gas *big.Int) error - SetPerformGasToBurn(ctx context.Context, gas *big.Int) error -} - // KeeperRegistryOpts opts to deploy keeper registry version type KeeperRegistryOpts struct { RegistryVersion KeeperRegistryVersion @@ -285,126 +264,3 @@ type UpkeepInfo struct { Paused bool OffchainConfig []byte } - -// EthereumKeeperConsumerPerformance represents a more complicated keeper consumer contract, one intended only for -// performance tests. -type EthereumKeeperConsumerPerformance struct { - client *seth.Client - consumer *keeper_consumer_performance_wrapper.KeeperConsumerPerformance - address *common.Address -} - -func (v *EthereumKeeperConsumerPerformance) Address() string { - return v.address.Hex() -} - -func (v *EthereumKeeperConsumerPerformance) Fund(_ *big.Float) error { - panic("do not use this function, use actions.SendFunds instead") -} - -func (v *EthereumKeeperConsumerPerformance) CheckEligible(ctx context.Context) (bool, error) { - return v.consumer.CheckEligible(&bind.CallOpts{ - From: v.client.MustGetRootKeyAddress(), - Context: ctx, - }) -} - -func (v *EthereumKeeperConsumerPerformance) GetUpkeepCount(ctx context.Context) (*big.Int, error) { - return v.consumer.GetCountPerforms(&bind.CallOpts{ - From: v.client.MustGetRootKeyAddress(), - Context: ctx, - }) -} - -func (v *EthereumKeeperConsumerPerformance) SetCheckGasToBurn(_ context.Context, gas *big.Int) error { - _, err := v.client.Decode(v.consumer.SetCheckGasToBurn(v.client.NewTXOpts(), gas)) - return err -} - -func (v *EthereumKeeperConsumerPerformance) SetPerformGasToBurn(_ context.Context, gas *big.Int) error { - _, err := v.client.Decode(v.consumer.SetPerformGasToBurn(v.client.NewTXOpts(), gas)) - return err -} - -func DeployKeeperConsumerPerformance( - client *seth.Client, - testBlockRange, - averageCadence, - checkGasToBurn, - performGasToBurn *big.Int, -) (KeeperConsumerPerformance, error) { - abi, err := keeper_consumer_performance_wrapper.KeeperConsumerPerformanceMetaData.GetAbi() - if err != nil { - return &EthereumKeeperConsumerPerformance{}, fmt.Errorf("failed to get KeeperConsumerPerformance ABI: %w", err) - } - data, err := client.DeployContract(client.NewTXOpts(), "KeeperConsumerPerformance", *abi, common.FromHex(keeper_consumer_performance_wrapper.KeeperConsumerPerformanceMetaData.Bin), - testBlockRange, - averageCadence, - checkGasToBurn, - performGasToBurn) - if err != nil { - return &EthereumKeeperConsumerPerformance{}, fmt.Errorf("KeeperConsumerPerformance instance deployment have failed: %w", err) - } - - instance, err := keeper_consumer_performance_wrapper.NewKeeperConsumerPerformance(data.Address, MustNewWrappedContractBackend(nil, client)) - if err != nil { - return &EthereumKeeperConsumerPerformance{}, fmt.Errorf("failed to instantiate KeeperConsumerPerformance instance: %w", err) - } - - return &EthereumKeeperConsumerPerformance{ - client: client, - consumer: instance, - address: &data.Address, - }, nil -} - -type KeeperPerformDataChecker interface { - Address() string - Counter(ctx context.Context) (*big.Int, error) - SetExpectedData(ctx context.Context, expectedData []byte) error -} - -// EthereumKeeperPerformDataCheckerConsumer represents keeper perform data checker contract -type EthereumKeeperPerformDataCheckerConsumer struct { - client *seth.Client - performDataChecker *perform_data_checker_wrapper.PerformDataChecker - address *common.Address -} - -func (v *EthereumKeeperPerformDataCheckerConsumer) Address() string { - return v.address.Hex() -} - -func (v *EthereumKeeperPerformDataCheckerConsumer) Counter(ctx context.Context) (*big.Int, error) { - return v.performDataChecker.Counter(&bind.CallOpts{ - From: v.client.MustGetRootKeyAddress(), - Context: ctx, - }) -} - -func (v *EthereumKeeperPerformDataCheckerConsumer) SetExpectedData(_ context.Context, expectedData []byte) error { - _, err := v.client.Decode(v.performDataChecker.SetExpectedData(v.client.NewTXOpts(), expectedData)) - return err -} - -func DeployKeeperPerformDataChecker(client *seth.Client, expectedData []byte) (KeeperPerformDataChecker, error) { - abi, err := perform_data_checker_wrapper.PerformDataCheckerMetaData.GetAbi() - if err != nil { - return &EthereumKeeperPerformDataCheckerConsumer{}, fmt.Errorf("failed to get PerformDataChecker ABI: %w", err) - } - data, err := client.DeployContract(client.NewTXOpts(), "PerformDataChecker", *abi, common.FromHex(perform_data_checker_wrapper.PerformDataCheckerMetaData.Bin), expectedData) - if err != nil { - return &EthereumKeeperPerformDataCheckerConsumer{}, fmt.Errorf("PerformDataChecker instance deployment have failed: %w", err) - } - - instance, err := perform_data_checker_wrapper.NewPerformDataChecker(data.Address, MustNewWrappedContractBackend(nil, client)) - if err != nil { - return &EthereumKeeperPerformDataCheckerConsumer{}, fmt.Errorf("failed to instantiate PerformDataChecker instance: %w", err) - } - - return &EthereumKeeperPerformDataCheckerConsumer{ - client: client, - performDataChecker: instance, - address: &data.Address, - }, nil -} diff --git a/devenv/products/automation/keeper_helpers.go b/devenv/products/automation/keeper_helpers.go index e095273fc1a..6ff089341d3 100644 --- a/devenv/products/automation/keeper_helpers.go +++ b/devenv/products/automation/keeper_helpers.go @@ -19,8 +19,6 @@ import ( "github.com/smartcontractkit/chainlink/devenv/contracts" ) -var ZeroAddress = common.Address{} - func RegisterUpkeepContracts(t *testing.T, client *seth.Client, linkToken contracts.LinkToken, fundsForEachUpkeep *big.Int, upkeepGasLimit uint32, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, numberOfContracts int, upkeepAddresses []string, isLogTrigger bool, isMercury bool, isBillingTokenNative bool, wethToken contracts.WETHToken) []*big.Int { checkData := make([][]byte, 0) for range numberOfContracts { @@ -241,42 +239,6 @@ func SetupKeeperConsumers(t *testing.T, client *seth.Client, numberOfContracts i return results } -// RegisterNewUpkeeps concurrently registers the given amount of new upkeeps, using the registry and registrar, -// which are passed as parameters. It returns the newly deployed contracts (consumers), as well as their upkeep IDs. -func RegisterNewUpkeeps( - t *testing.T, - chainClient *seth.Client, - linkToken contracts.LinkToken, - registry contracts.KeeperRegistry, - registrar contracts.KeeperRegistrar, - upkeepGasLimit uint32, - numberOfNewUpkeeps int, -) ([]contracts.KeeperConsumer, []*big.Int) { - newlyDeployedUpkeeps := DeployKeeperConsumers(t, chainClient, numberOfNewUpkeeps, false, false) - - addressesOfNewUpkeeps := []string{} - for _, upkeep := range newlyDeployedUpkeeps { - addressesOfNewUpkeeps = append(addressesOfNewUpkeeps, upkeep.Address()) - } - - concurrency, err := GetAndAssertCorrectConcurrency(chainClient, 1) - require.NoError(t, err, "Insufficient concurrency to execute action") - - operationsPerAddress := numberOfNewUpkeeps / concurrency - - multicallAddress, err := contracts.DeployMultiCallContract(chainClient) - require.NoError(t, err, "Error deploying multicall contract") - - linkFundsForEachUpkeep := big.NewInt(9e18) - - err = SendLinkFundsToDeploymentAddresses(chainClient, concurrency, numberOfNewUpkeeps, operationsPerAddress, multicallAddress, linkFundsForEachUpkeep, linkToken) - require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") - - newUpkeepIDs := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfNewUpkeeps, addressesOfNewUpkeeps, false, false, false, nil) - - return newlyDeployedUpkeeps, newUpkeepIDs -} - var InsufficientStaticKeys = ` Error: Insufficient Private Keys for Live Network diff --git a/devenv/tests/automation/test_helpers.go b/devenv/tests/automation/test_helpers.go index 27972055e03..6d9a5b43936 100644 --- a/devenv/tests/automation/test_helpers.go +++ b/devenv/tests/automation/test_helpers.go @@ -71,7 +71,6 @@ type Test struct { Config *automation.Automation LinkToken contracts.LinkToken - Transcoder contracts.UpkeepTranscoder LINKETHFeed contracts.MockLINKETHFeed ETHUSDFeed contracts.MockETHUSDFeed LINKUSDFeed contracts.MockETHUSDFeed @@ -139,16 +138,6 @@ func (a *Test) LoadLINK(address string) error { return nil } -func (a *Test) LoadTranscoder(address string) error { - transcoder, err := contracts.LoadUpkeepTranscoder(a.ChainClient, common.HexToAddress(address)) - if err != nil { - return err - } - a.Transcoder = transcoder - a.Logger.Info().Str("Transcoder Address", a.Transcoder.Address()).Msg("Successfully loaded Transcoder") - return nil -} - func (a *Test) LoadLinkEthFeed(address string) error { ethLinkFeed, err := contracts.LoadMockLINKETHFeed(a.ChainClient, common.HexToAddress(address)) if err != nil { @@ -414,10 +403,6 @@ func (a *Test) LoadContracts() error { return fmt.Errorf("error loading link usd feed contract: %w", err) } - if err := a.LoadTranscoder(a.Config.DeployedContracts.Transcoder); err != nil { - return fmt.Errorf("error loading transcoder contract: %w", err) - } - if err := a.LoadRegistry(a.Config.DeployedContracts.Registry, a.Config.DeployedContracts.ChainModule); err != nil { return fmt.Errorf("error loading registry contract: %w", err) }