From 78aabee98d440bf9c61114a2efeebd01330d7f4f Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 20 May 2024 14:02:13 -0400 Subject: [PATCH 01/87] add skel --- cmd/root.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmd/root.go b/cmd/root.go index 7c157fba4..76e1cb466 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -18,6 +18,7 @@ import ( "github.com/ava-labs/avalanche-cli/cmd/configcmd" "github.com/ava-labs/avalanche-cli/cmd/backendcmd" + "github.com/ava-labs/avalanche-cli/cmd/contractcmd" "github.com/ava-labs/avalanche-cli/cmd/keycmd" "github.com/ava-labs/avalanche-cli/cmd/networkcmd" "github.com/ava-labs/avalanche-cli/cmd/subnetcmd" @@ -98,6 +99,9 @@ in with avalanche subnet create myNewSubnet.`, // add teleporter command rootCmd.AddCommand(teleportercmd.NewCmd(app)) + // add contract command + rootCmd.AddCommand(contractcmd.NewCmd(app)) + cobrautils.ConfigureRootCmd(rootCmd) return rootCmd From a2d0d6e48994da00896be51c2fb424312471a441 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 20 May 2024 14:06:10 -0400 Subject: [PATCH 02/87] add missing files --- cmd/contractcmd/contract.go | 26 +++ cmd/contractcmd/deploy.go | 21 ++ cmd/contractcmd/deployBridge.go | 326 ++++++++++++++++++++++++++++++++ 3 files changed, 373 insertions(+) create mode 100644 cmd/contractcmd/contract.go create mode 100644 cmd/contractcmd/deploy.go create mode 100644 cmd/contractcmd/deployBridge.go diff --git a/cmd/contractcmd/contract.go b/cmd/contractcmd/contract.go new file mode 100644 index 000000000..52f866299 --- /dev/null +++ b/cmd/contractcmd/contract.go @@ -0,0 +1,26 @@ +// Copyright (C) 2022, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +package contractcmd + +import ( + "github.com/ava-labs/avalanche-cli/pkg/application" + "github.com/ava-labs/avalanche-cli/pkg/cobrautils" + "github.com/spf13/cobra" +) + +var app *application.Avalanche + +// avalanche contract +func NewCmd(injectedApp *application.Avalanche) *cobra.Command { + cmd := &cobra.Command{ + Use: "contract", + Short: "Interact with smart contracts", + Long: `The contract command suite provides a collection of tools for interacting +with Smart Contracts.`, + RunE: cobrautils.CommandSuiteUsage, + } + app = injectedApp + // contract deploy + cmd.AddCommand(newDeployCmd()) + return cmd +} diff --git a/cmd/contractcmd/deploy.go b/cmd/contractcmd/deploy.go new file mode 100644 index 000000000..2b5c0376a --- /dev/null +++ b/cmd/contractcmd/deploy.go @@ -0,0 +1,21 @@ +// Copyright (C) 2022, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +package contractcmd + +import ( + "github.com/ava-labs/avalanche-cli/pkg/cobrautils" + "github.com/spf13/cobra" +) + +// avalanche contract deploy +func newDeployCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "deploy", + Short: "Deploy smart contracts", + Long: `The deploy command suite provides deploy flows for different Smart Contracts.`, + RunE: cobrautils.CommandSuiteUsage, + } + // contract deploy + cmd.AddCommand(newDeployBridgeCmd()) + return cmd +} diff --git a/cmd/contractcmd/deployBridge.go b/cmd/contractcmd/deployBridge.go new file mode 100644 index 000000000..0ee467506 --- /dev/null +++ b/cmd/contractcmd/deployBridge.go @@ -0,0 +1,326 @@ +// Copyright (C) 2022, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +package contractcmd + +import ( + "fmt" + + cmdflags "github.com/ava-labs/avalanche-cli/cmd/flags" + "github.com/ava-labs/avalanche-cli/cmd/subnetcmd" + "github.com/ava-labs/avalanche-cli/pkg/cobrautils" + "github.com/ava-labs/avalanche-cli/pkg/models" + "github.com/ava-labs/avalanche-cli/pkg/networkoptions" + "github.com/ava-labs/avalanche-cli/pkg/prompts" + "github.com/ava-labs/avalanche-cli/pkg/subnet" + "github.com/ava-labs/avalanche-cli/pkg/teleporter" + "github.com/ava-labs/avalanche-cli/pkg/utils" + "github.com/ava-labs/avalanchego/ids" + + "github.com/spf13/cobra" +) + +type DeployFlags struct { + Network networkoptions.NetworkFlags + SubnetName string + BlockchainID string + CChain bool + PrivateKey string + KeyName string + GenesisKey bool + DeployMessenger bool + DeployRegistry bool + TeleporterVersion string + RPCURL string +} + +const ( + cChainAlias = "C" + cChainName = "c-chain" +) + +var ( + deploySupportedNetworkOptions = []networkoptions.NetworkOption{ + networkoptions.Local, + networkoptions.Devnet, + networkoptions.Fuji, + } + deployFlags DeployFlags +) + +// avalanche contract deploy bridge +func newDeployBridgeCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "bridge", + Short: "Deploys Tokeb Bridge into a given Network and Subnets", + Long: "Deploys Tokeb Bridge into a given Network and Subnets", + RunE: deployBridge, + Args: cobrautils.ExactArgs(0), + } + networkoptions.AddNetworkFlagsToCmd(cmd, &deployFlags.Network, true, deploySupportedNetworkOptions) + cmd.Flags().StringVar(&deployFlags.SubnetName, "subnet", "", "deploy teleporter into the given CLI subnet") + cmd.Flags().StringVar(&deployFlags.BlockchainID, "blockchain-id", "", "deploy teleporter into the given blockchain ID/Alias") + cmd.Flags().BoolVar(&deployFlags.CChain, "c-chain", false, "deploy teleporter into C-Chain") + cmd.Flags().StringVar(&deployFlags.PrivateKey, "private-key", "", "private key to use to fund teleporter deploy)") + cmd.Flags().StringVar(&deployFlags.KeyName, "key", "", "CLI stored key to use to fund teleporter deploy)") + cmd.Flags().BoolVar(&deployFlags.GenesisKey, "genesis-key", false, "use genesis aidrop key to fund teleporter deploy") + cmd.Flags().BoolVar(&deployFlags.DeployMessenger, "deploy-messenger", true, "deploy Teleporter Messenger") + cmd.Flags().BoolVar(&deployFlags.DeployRegistry, "deploy-registry", true, "deploy Teleporter Registry") + cmd.Flags().StringVar(&deployFlags.TeleporterVersion, "version", "latest", "version to deploy") + cmd.Flags().StringVar(&deployFlags.RPCURL, "rpc-url", "", "use the given RPC URL to connect to the subnet") + return cmd +} + +func deployBridge(_ *cobra.Command, args []string) error { + return CallDeployBridge(args, deployFlags) +} + +func CallDeployBridge(_ []string, flags DeployFlags) error { + network, err := networkoptions.GetNetworkFromCmdLineFlags( + app, + "On what Network do you want to deploy the Teleporter Messenger?", + flags.Network, + true, + false, + deploySupportedNetworkOptions, + "", + ) + if err != nil { + return err + } + if !cmdflags.EnsureMutuallyExclusive([]bool{flags.SubnetName != "", flags.BlockchainID != "", flags.CChain}) { + return fmt.Errorf("--subnet, --blockchain-id and --cchain are mutually exclusive flags") + } + if !cmdflags.EnsureMutuallyExclusive([]bool{flags.PrivateKey != "", flags.KeyName != "", flags.GenesisKey}) { + return fmt.Errorf("--private-key, --key and --genesis-key are mutually exclusive flags") + } + if !flags.DeployMessenger && !flags.DeployRegistry { + return fmt.Errorf("you should set at least one of --deploy-messenger/--deploy-registry to true") + } + if flags.SubnetName == "" && flags.BlockchainID == "" && !flags.CChain { + // fill flags based on user prompts + blockchainIDOptions := []string{ + "Get Blockchain ID from an existing subnet (deployed with avalanche subnet deploy)", + "Use C-Chain Blockchain ID", + "Custom", + } + blockchainIDOption, err := app.Prompt.CaptureList("Which Blockchain ID would you like to deploy Teleporter to?", blockchainIDOptions) + if err != nil { + return err + } + switch blockchainIDOption { + case blockchainIDOptions[0]: + subnetNames, err := app.GetSubnetNames() + if err != nil { + return err + } + flags.SubnetName, err = app.Prompt.CaptureList( + "Choose a Subnet", + subnetNames, + ) + if err != nil { + return err + } + case blockchainIDOptions[1]: + flags.CChain = true + default: + flags.BlockchainID, err = app.Prompt.CaptureString("Blockchain ID/Alias") + if err != nil { + return err + } + } + } + + var ( + blockchainID string + teleporterSubnetDesc string + privateKey = flags.PrivateKey + teleporterVersion string + ) + switch { + case flags.SubnetName != "": + teleporterSubnetDesc = flags.SubnetName + sc, err := app.LoadSidecar(flags.SubnetName) + if err != nil { + return fmt.Errorf("failed to load sidecar: %w", err) + } + if b, _, err := subnetcmd.HasSubnetEVMGenesis(flags.SubnetName); err != nil { + return err + } else if !b { + return fmt.Errorf("only Subnet-EVM based vms can be used for teleporter") + } + if sc.Networks[network.Name()].BlockchainID == ids.Empty { + return fmt.Errorf("subnet has not been deployed to %s", network.Name()) + } + blockchainID = sc.Networks[network.Name()].BlockchainID.String() + if sc.TeleporterVersion != "" { + teleporterVersion = sc.TeleporterVersion + } + if sc.TeleporterKey != "" { + k, err := app.GetKey(sc.TeleporterKey, network, true) + if err != nil { + return err + } + privateKey = k.PrivKeyHex() + } + case flags.BlockchainID != "": + teleporterSubnetDesc = flags.BlockchainID + blockchainID = flags.BlockchainID + case flags.CChain: + teleporterSubnetDesc = cChainName + blockchainID = cChainAlias + } + var chainID ids.ID + if flags.CChain || !network.StandardPublicEndpoint() { + chainID, err = utils.GetChainID(network.Endpoint, blockchainID) + if err != nil { + return err + } + } else { + chainID, err = ids.FromString(blockchainID) + if err != nil { + return err + } + } + createChainTx, err := utils.GetBlockchainTx(network.Endpoint, chainID) + if err != nil { + return err + } + if !utils.ByteSliceIsSubnetEvmGenesis(createChainTx.GenesisData) { + return fmt.Errorf("teleporter can only be deployed to Subnet-EVM based vms") + } + if flags.KeyName != "" { + k, err := app.GetKey(flags.KeyName, network, false) + if err != nil { + return err + } + privateKey = k.PrivKeyHex() + } + _, genesisAddress, genesisPrivateKey, err := subnet.GetSubnetAirdropKeyInfo(app, network, flags.SubnetName, createChainTx.GenesisData) + if err != nil { + return err + } + if flags.GenesisKey { + privateKey = genesisPrivateKey + } + if privateKey == "" { + cliKeyOpt := "Get private key from an existing stored key (created from avalanche key create or avalanche key import)" + customKeyOpt := "Custom" + genesisKeyOpt := fmt.Sprintf("Use the private key of the Genesis Aidrop address %s", genesisAddress) + keyOptions := []string{cliKeyOpt, customKeyOpt} + if genesisPrivateKey != "" { + keyOptions = []string{genesisKeyOpt, cliKeyOpt, customKeyOpt} + } + keyOption, err := app.Prompt.CaptureList("Which private key do you want to use to pay fees?", keyOptions) + if err != nil { + return err + } + switch keyOption { + case cliKeyOpt: + keyName, err := prompts.CaptureKeyName(app.Prompt, "pay fees", app.GetKeyDir(), true) + if err != nil { + return err + } + k, err := app.GetKey(keyName, network, false) + if err != nil { + return err + } + privateKey = k.PrivKeyHex() + case customKeyOpt: + privateKey, err = app.Prompt.CaptureString("Private Key") + if err != nil { + return err + } + case genesisKeyOpt: + privateKey = genesisPrivateKey + } + } + if flags.TeleporterVersion != "" && flags.TeleporterVersion != "latest" { + teleporterVersion = flags.TeleporterVersion + } else if teleporterVersion == "" { + teleporterInfo, err := teleporter.GetInfo(app) + if err != nil { + return err + } + teleporterVersion = teleporterInfo.Version + } + // deploy to subnet + rpcURL := network.BlockchainEndpoint(blockchainID) + if flags.RPCURL != "" { + rpcURL = flags.RPCURL + } + td := teleporter.Deployer{} + alreadyDeployed, teleporterMessengerAddress, teleporterRegistryAddress, err := td.Deploy( + app.GetTeleporterBinDir(), + teleporterVersion, + teleporterSubnetDesc, + rpcURL, + privateKey, + flags.DeployMessenger, + flags.DeployRegistry, + ) + if err != nil { + return err + } + if flags.SubnetName != "" && !alreadyDeployed { + // update sidecar + sc, err := app.LoadSidecar(flags.SubnetName) + if err != nil { + return fmt.Errorf("failed to load sidecar: %w", err) + } + sc.TeleporterReady = true + sc.TeleporterVersion = teleporterVersion + networkInfo := sc.Networks[network.Name()] + if teleporterMessengerAddress != "" { + networkInfo.TeleporterMessengerAddress = teleporterMessengerAddress + } + if teleporterRegistryAddress != "" { + networkInfo.TeleporterRegistryAddress = teleporterRegistryAddress + } + sc.Networks[network.Name()] = networkInfo + if err := app.UpdateSidecar(&sc); err != nil { + return err + } + } + // automatic deploy to cchain for local/devnet + if !flags.CChain && (network.Kind == models.Local || network.Kind == models.Devnet) { + ewoq, err := app.GetKey("ewoq", network, false) + if err != nil { + return err + } + alreadyDeployed, teleporterMessengerAddress, teleporterRegistryAddress, err := td.Deploy( + app.GetTeleporterBinDir(), + teleporterVersion, + cChainName, + network.BlockchainEndpoint(cChainAlias), + ewoq.PrivKeyHex(), + flags.DeployMessenger, + flags.DeployRegistry, + ) + if err != nil { + return err + } + if !alreadyDeployed { + if network.Kind == models.Local { + if err := subnet.WriteExtraLocalNetworkData(app, teleporterMessengerAddress, teleporterRegistryAddress); err != nil { + return err + } + } + if network.ClusterName != "" { + clusterConfig, err := app.GetClusterConfig(network.ClusterName) + if err != nil { + return err + } + if teleporterMessengerAddress != "" { + clusterConfig.ExtraNetworkData.CChainTeleporterMessengerAddress = teleporterMessengerAddress + } + if teleporterRegistryAddress != "" { + clusterConfig.ExtraNetworkData.CChainTeleporterRegistryAddress = teleporterRegistryAddress + } + if err := app.SetClusterConfig(network.ClusterName, clusterConfig); err != nil { + return err + } + } + } + } + return nil +} From 7781e6263086a191d22c4d8a7893acddb0fde7cf Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 20 May 2024 14:40:28 -0400 Subject: [PATCH 03/87] check for forge to have been installed --- cmd/contractcmd/deployBridge.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/cmd/contractcmd/deployBridge.go b/cmd/contractcmd/deployBridge.go index 0ee467506..3781714fb 100644 --- a/cmd/contractcmd/deployBridge.go +++ b/cmd/contractcmd/deployBridge.go @@ -3,7 +3,9 @@ package contractcmd import ( + "errors" "fmt" + "os/exec" cmdflags "github.com/ava-labs/avalanche-cli/cmd/flags" "github.com/ava-labs/avalanche-cli/cmd/subnetcmd" @@ -14,6 +16,7 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/subnet" "github.com/ava-labs/avalanche-cli/pkg/teleporter" "github.com/ava-labs/avalanche-cli/pkg/utils" + "github.com/ava-labs/avalanche-cli/pkg/ux" "github.com/ava-labs/avalanchego/ids" "github.com/spf13/cobra" @@ -47,6 +50,21 @@ var ( deployFlags DeployFlags ) +// ~/.foundry/bin/forge +// make a first install just using this two commands and assuming bash +// curl -L https://foundry.paradigm.xyz | bash +// foundryup (~/.foundry/bin/foundryup) +func checkForgeIsInstalled() error { + if err := exec.Command("~/.foundry/bin/forge").Run(); errors.Is(err, exec.ErrNotFound) { + ux.Logger.PrintToUser("Forge tool (from foundry toolset) is not available. It is a necessary dependency for CLI to compile smart contracts.") + ux.Logger.PrintToUser("") + ux.Logger.PrintToUser("Please follow install instructions at https://book.getfoundry.sh/getting-started/installation and try again") + ux.Logger.PrintToUser("") + return err + } + return nil +} + // avalanche contract deploy bridge func newDeployBridgeCmd() *cobra.Command { cmd := &cobra.Command{ @@ -75,6 +93,9 @@ func deployBridge(_ *cobra.Command, args []string) error { } func CallDeployBridge(_ []string, flags DeployFlags) error { + if err := checkForgeIsInstalled(); err != nil { + return err + } network, err := networkoptions.GetNetworkFromCmdLineFlags( app, "On what Network do you want to deploy the Teleporter Messenger?", From b09875713c31a9b56e8f65ad3bbefad6655dfc93 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 20 May 2024 17:11:20 -0400 Subject: [PATCH 04/87] add comments --- cmd/contractcmd/deployBridge.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cmd/contractcmd/deployBridge.go b/cmd/contractcmd/deployBridge.go index 3781714fb..1288d7604 100644 --- a/cmd/contractcmd/deployBridge.go +++ b/cmd/contractcmd/deployBridge.go @@ -54,6 +54,11 @@ var ( // make a first install just using this two commands and assuming bash // curl -L https://foundry.paradigm.xyz | bash // foundryup (~/.foundry/bin/foundryup) +// don't forget this +// inside avalanche-starter-kit repo +// git submodule update --init --recursive +// forge create --rpc-url http://127.0.0.1:9650/ext/bc/2tvKVYuMmKg2NwGWKtaHUgnS8Wc35RaAXyTNm9riDP622DEYgy/rpc --private-key 6e6cb03f2f64e298b28e56bc53a051257bff62be978b6df010fce46a8fdde2cb src/5-native-token-bridge/ExampleWNATV.sol:WNATV +// deployer to 0x3058749395527bF64e687A05d23d38cfeC9e7682 func checkForgeIsInstalled() error { if err := exec.Command("~/.foundry/bin/forge").Run(); errors.Is(err, exec.ErrNotFound) { ux.Logger.PrintToUser("Forge tool (from foundry toolset) is not available. It is a necessary dependency for CLI to compile smart contracts.") From 9c2cb9cf155333fb108f5428912f5a5334ed94b8 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 20 May 2024 17:37:43 -0400 Subject: [PATCH 05/87] start automating foundry install --- cmd/contractcmd/deployBridge.go | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/cmd/contractcmd/deployBridge.go b/cmd/contractcmd/deployBridge.go index 1288d7604..0b05558d2 100644 --- a/cmd/contractcmd/deployBridge.go +++ b/cmd/contractcmd/deployBridge.go @@ -3,7 +3,6 @@ package contractcmd import ( - "errors" "fmt" "os/exec" @@ -59,15 +58,23 @@ var ( // git submodule update --init --recursive // forge create --rpc-url http://127.0.0.1:9650/ext/bc/2tvKVYuMmKg2NwGWKtaHUgnS8Wc35RaAXyTNm9riDP622DEYgy/rpc --private-key 6e6cb03f2f64e298b28e56bc53a051257bff62be978b6df010fce46a8fdde2cb src/5-native-token-bridge/ExampleWNATV.sol:WNATV // deployer to 0x3058749395527bF64e687A05d23d38cfeC9e7682 -func checkForgeIsInstalled() error { - if err := exec.Command("~/.foundry/bin/forge").Run(); errors.Is(err, exec.ErrNotFound) { - ux.Logger.PrintToUser("Forge tool (from foundry toolset) is not available. It is a necessary dependency for CLI to compile smart contracts.") +func foundryIsInstalled() bool { + return utils.IsExecutable(utils.ExpandHome("~/.foundry/bin/forge")) +} + +func installFoundry() error { + ux.Logger.PrintToUser("Installing Foundry") + ux.Logger.PrintToUser("") + out, err := exec.Command(utils.ExpandHome("~/.foundry/bin/foundryup")).Output() + ux.Logger.PrintToUser(string(out)) + if err != nil { + ux.Logger.PrintToUser("") + ux.Logger.PrintToUser("Foundry toolset is not available and couldn't automatically be installed. It is a necessary dependency for CLI to compile smart contracts.") ux.Logger.PrintToUser("") ux.Logger.PrintToUser("Please follow install instructions at https://book.getfoundry.sh/getting-started/installation and try again") ux.Logger.PrintToUser("") - return err } - return nil + return err } // avalanche contract deploy bridge @@ -98,9 +105,11 @@ func deployBridge(_ *cobra.Command, args []string) error { } func CallDeployBridge(_ []string, flags DeployFlags) error { - if err := checkForgeIsInstalled(); err != nil { - return err + if !foundryIsInstalled() { + return installFoundry() } + return installFoundry() + return nil network, err := networkoptions.GetNetworkFromCmdLineFlags( app, "On what Network do you want to deploy the Teleporter Messenger?", From aceff272bbbcc838cd3ef8d38ff382bbbae2d214 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 20 May 2024 18:18:26 -0400 Subject: [PATCH 06/87] added automated froundry install --- cmd/contractcmd/deployBridge.go | 46 +++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/cmd/contractcmd/deployBridge.go b/cmd/contractcmd/deployBridge.go index 0b05558d2..9a53a0476 100644 --- a/cmd/contractcmd/deployBridge.go +++ b/cmd/contractcmd/deployBridge.go @@ -4,7 +4,9 @@ package contractcmd import ( "fmt" + "io" "os/exec" + "strings" cmdflags "github.com/ava-labs/avalanche-cli/cmd/flags" "github.com/ava-labs/avalanche-cli/cmd/subnetcmd" @@ -49,22 +51,50 @@ var ( deployFlags DeployFlags ) -// ~/.foundry/bin/forge -// make a first install just using this two commands and assuming bash -// curl -L https://foundry.paradigm.xyz | bash -// foundryup (~/.foundry/bin/foundryup) -// don't forget this // inside avalanche-starter-kit repo // git submodule update --init --recursive -// forge create --rpc-url http://127.0.0.1:9650/ext/bc/2tvKVYuMmKg2NwGWKtaHUgnS8Wc35RaAXyTNm9riDP622DEYgy/rpc --private-key 6e6cb03f2f64e298b28e56bc53a051257bff62be978b6df010fce46a8fdde2cb src/5-native-token-bridge/ExampleWNATV.sol:WNATV -// deployer to 0x3058749395527bF64e687A05d23d38cfeC9e7682 + func foundryIsInstalled() bool { return utils.IsExecutable(utils.ExpandHome("~/.foundry/bin/forge")) } func installFoundry() error { ux.Logger.PrintToUser("Installing Foundry") - ux.Logger.PrintToUser("") + downloadCmd := exec.Command("curl", "-L", "https://foundry.paradigm.xyz") + installCmd := exec.Command("sh") + var downloadOutbuf, downloadErrbuf strings.Builder + downloadCmdStdoutPipe, err := downloadCmd.StdoutPipe() + if err != nil { + return err + } + downloadCmd.Stderr = &downloadErrbuf + installCmd.Stdin = io.TeeReader(downloadCmdStdoutPipe, &downloadOutbuf) + var installOutbuf, installErrbuf strings.Builder + installCmd.Stdout = &installOutbuf + installCmd.Stderr = &installErrbuf + if err := installCmd.Start(); err != nil { + return err + } + if err := downloadCmd.Run(); err != nil { + if downloadOutbuf.String() != "" { + ux.Logger.PrintToUser(strings.TrimSuffix(downloadOutbuf.String(), "\n")) + } + if downloadErrbuf.String() != "" { + ux.Logger.PrintToUser(strings.TrimSuffix(downloadErrbuf.String(), "\n")) + } + return err + } + if err := installCmd.Wait(); err != nil { + if installOutbuf.String() != "" { + ux.Logger.PrintToUser(strings.TrimSuffix(installOutbuf.String(), "\n")) + } + if installErrbuf.String() != "" { + ux.Logger.PrintToUser(strings.TrimSuffix(installErrbuf.String(), "\n")) + } + ux.Logger.PrintToUser("installation failed: %s", err.Error()) + return err + } + ux.Logger.PrintToUser(strings.TrimSuffix(installOutbuf.String(), "\n")) out, err := exec.Command(utils.ExpandHome("~/.foundry/bin/foundryup")).Output() ux.Logger.PrintToUser(string(out)) if err != nil { From 17e6c81d1d37d11d86b6ae8c06467f90dcc4c26b Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Tue, 21 May 2024 11:15:53 -0400 Subject: [PATCH 07/87] start working agains teleporter repo --- cmd/contractcmd/deployBridge.go | 77 +++++++++++++++++++++++++++++---- pkg/vm/createCustom.go | 11 +++-- 2 files changed, 73 insertions(+), 15 deletions(-) diff --git a/cmd/contractcmd/deployBridge.go b/cmd/contractcmd/deployBridge.go index 9a53a0476..5dbbfa59d 100644 --- a/cmd/contractcmd/deployBridge.go +++ b/cmd/contractcmd/deployBridge.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "os/exec" + "path/filepath" "strings" cmdflags "github.com/ava-labs/avalanche-cli/cmd/flags" @@ -18,6 +19,7 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/teleporter" "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" + "github.com/ava-labs/avalanche-cli/pkg/vm" "github.com/ava-labs/avalanchego/ids" "github.com/spf13/cobra" @@ -43,19 +45,21 @@ const ( ) var ( - deploySupportedNetworkOptions = []networkoptions.NetworkOption{ + deployBridgeSupportedNetworkOptions = []networkoptions.NetworkOption{ networkoptions.Local, networkoptions.Devnet, networkoptions.Fuji, } - deployFlags DeployFlags + deployFlags DeployFlags + foundryupPath = utils.ExpandHome("~/.foundry/bin/foundryup") + forgePath = utils.ExpandHome("~/.foundry/bin/forge") ) // inside avalanche-starter-kit repo // git submodule update --init --recursive func foundryIsInstalled() bool { - return utils.IsExecutable(utils.ExpandHome("~/.foundry/bin/forge")) + return utils.IsExecutable(forgePath) } func installFoundry() error { @@ -95,7 +99,7 @@ func installFoundry() error { return err } ux.Logger.PrintToUser(strings.TrimSuffix(installOutbuf.String(), "\n")) - out, err := exec.Command(utils.ExpandHome("~/.foundry/bin/foundryup")).Output() + out, err := exec.Command(foundryupPath).CombinedOutput() ux.Logger.PrintToUser(string(out)) if err != nil { ux.Logger.PrintToUser("") @@ -116,7 +120,7 @@ func newDeployBridgeCmd() *cobra.Command { RunE: deployBridge, Args: cobrautils.ExactArgs(0), } - networkoptions.AddNetworkFlagsToCmd(cmd, &deployFlags.Network, true, deploySupportedNetworkOptions) + networkoptions.AddNetworkFlagsToCmd(cmd, &deployFlags.Network, true, deployBridgeSupportedNetworkOptions) cmd.Flags().StringVar(&deployFlags.SubnetName, "subnet", "", "deploy teleporter into the given CLI subnet") cmd.Flags().StringVar(&deployFlags.BlockchainID, "blockchain-id", "", "deploy teleporter into the given blockchain ID/Alias") cmd.Flags().BoolVar(&deployFlags.CChain, "c-chain", false, "deploy teleporter into C-Chain") @@ -135,23 +139,78 @@ func deployBridge(_ *cobra.Command, args []string) error { } func CallDeployBridge(_ []string, flags DeployFlags) error { + if err := vm.CheckGitIsInstalled(); err != nil { + return err + } if !foundryIsInstalled() { return installFoundry() } - return installFoundry() - return nil network, err := networkoptions.GetNetworkFromCmdLineFlags( app, - "On what Network do you want to deploy the Teleporter Messenger?", + "On what Network do you want to deploy the Teleporter bridge?", flags.Network, true, false, - deploySupportedNetworkOptions, + deployBridgeSupportedNetworkOptions, "", ) if err != nil { return err } + bridgeSrcDir := utils.ExpandHome("~/Workspace/projects/teleporter-token-bridge/") + // install bridge src dependencies + cmd := exec.Command( + "git", + "submodule", + "update", + "--init", + "--recursive", + ) + cmd.Dir = bridgeSrcDir + out, err := cmd.CombinedOutput() + if err != nil { + ux.Logger.PrintToUser(string(out)) + return err + } + // build teleporter contracts + cmd = exec.Command( + forgePath, + "build", + ) + cmd.Dir = filepath.Join(bridgeSrcDir, "contracts") + out, err = cmd.CombinedOutput() + if err != nil { + ux.Logger.PrintToUser(string(out)) + return err + } + return nil + cmd = exec.Command( + forgePath, + "install", + "openzeppelin/openzeppelin-contracts@v4.8.1", + "--no-commit", + ) + cmd.Dir = utils.ExpandHome("~/Workspace/projects/avalanche-cli/") + out, err = cmd.CombinedOutput() + fmt.Println(string(out)) + fmt.Println(err) + createCmd := exec.Command( + forgePath, + "create", + "--rpc-url", + network.BlockchainEndpoint("2FZA3PDpQvYy6uevt34xr7Sv4RczKe3827PWPqAymfqXhJkkGL"), + "--private-key", + "6e6cb03f2f64e298b28e56bc53a051257bff62be978b6df010fce46a8fdde2cb", + "src/5-native-token-bridge/WrappedNativeToken.sol:WrappedNativeToken", + "--constructor-args", + "Wrapped TOK Name", + "WTOK", + ) + createCmd.Dir = utils.ExpandHome("~/Workspace/projects/avalanche-cli/") + out, err = createCmd.CombinedOutput() + fmt.Println(string(out)) + fmt.Println(err) + return nil if !cmdflags.EnsureMutuallyExclusive([]bool{flags.SubnetName != "", flags.BlockchainID != "", flags.CChain}) { return fmt.Errorf("--subnet, --blockchain-id and --cchain are mutually exclusive flags") } diff --git a/pkg/vm/createCustom.go b/pkg/vm/createCustom.go index 5a9fcd3b4..0c6b527c8 100644 --- a/pkg/vm/createCustom.go +++ b/pkg/vm/createCustom.go @@ -3,7 +3,6 @@ package vm import ( - "errors" "fmt" "os" "os/exec" @@ -144,22 +143,22 @@ func SetCustomVMSourceCodeFields(app *application.Avalanche, sc *models.Sidecar, return nil } -func checkGitIsInstalled() error { - if err := exec.Command("git").Run(); errors.Is(err, exec.ErrNotFound) { +func CheckGitIsInstalled() error { + err := exec.Command("git", "--version").Run() + if err != nil { ux.Logger.PrintToUser("Git tool is not available. It is a necessary dependency for CLI to import a custom VM.") ux.Logger.PrintToUser("") ux.Logger.PrintToUser("Please follow install instructions at https://git-scm.com/book/en/v2/Getting-Started-Installing-Git and try again") ux.Logger.PrintToUser("") - return err } - return nil + return err } func BuildCustomVM( app *application.Avalanche, sc *models.Sidecar, ) error { - if err := checkGitIsInstalled(); err != nil { + if err := CheckGitIsInstalled(); err != nil { return err } From fe993a1ff12e3d9a06a9fd973677d341a48c2a9e Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Tue, 21 May 2024 13:06:13 -0400 Subject: [PATCH 08/87] deploying contract given abi and bin files --- cmd/contractcmd/deployBridge.go | 62 ++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/cmd/contractcmd/deployBridge.go b/cmd/contractcmd/deployBridge.go index 5dbbfa59d..42330644c 100644 --- a/cmd/contractcmd/deployBridge.go +++ b/cmd/contractcmd/deployBridge.go @@ -5,6 +5,7 @@ package contractcmd import ( "fmt" "io" + "os" "os/exec" "path/filepath" "strings" @@ -12,6 +13,7 @@ import ( cmdflags "github.com/ava-labs/avalanche-cli/cmd/flags" "github.com/ava-labs/avalanche-cli/cmd/subnetcmd" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" + "github.com/ava-labs/avalanche-cli/pkg/evm" "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/networkoptions" "github.com/ava-labs/avalanche-cli/pkg/prompts" @@ -21,6 +23,8 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/ux" "github.com/ava-labs/avalanche-cli/pkg/vm" "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/subnet-evm/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" "github.com/spf13/cobra" ) @@ -55,9 +59,6 @@ var ( forgePath = utils.ExpandHome("~/.foundry/bin/forge") ) -// inside avalanche-starter-kit repo -// git submodule update --init --recursive - func foundryIsInstalled() bool { return utils.IsExecutable(forgePath) } @@ -138,6 +139,52 @@ func deployBridge(_ *cobra.Command, args []string) error { return CallDeployBridge(args, deployFlags) } +func test( + rpcURL string, + prefundedPrivateKey string, +) error { + srcDir := utils.ExpandHome("~/Workspace/projects/teleporter-token-bridge/") + abiPath := filepath.Join(srcDir, "contracts/out/WrappedNativeToken.sol/WrappedNativeToken.abi.json") + binPath := filepath.Join(srcDir, "contracts/out/WrappedNativeToken.sol/WrappedNativeToken.bin") + abiBytes, err := os.ReadFile(abiPath) + if err != nil { + return err + } + binBytes, err := os.ReadFile(binPath) + if err != nil { + return err + } + metadata := &bind.MetaData{ + ABI: string(abiBytes), + Bin: string(binBytes), + } + abi, err := metadata.GetAbi() + if err != nil { + return err + } + bin := common.FromHex(metadata.Bin) + client, err := evm.GetClient(rpcURL) + if err != nil { + return err + } + defer client.Close() + txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) + if err != nil { + return err + } + address, tx, _, err := bind.DeployContract(txOpts, *abi, bin, client, "Al fin", "ALFIN") + if err != nil { + return err + } + if _, success, err := evm.WaitForTransaction(client, tx); err != nil { + return err + } else if !success { + return fmt.Errorf("failed receipt status deploying contract") + } + fmt.Println(address) + return nil +} + func CallDeployBridge(_ []string, flags DeployFlags) error { if err := vm.CheckGitIsInstalled(); err != nil { return err @@ -157,6 +204,10 @@ func CallDeployBridge(_ []string, flags DeployFlags) error { if err != nil { return err } + return test( + network.BlockchainEndpoint("2FZA3PDpQvYy6uevt34xr7Sv4RczKe3827PWPqAymfqXhJkkGL"), + "6e6cb03f2f64e298b28e56bc53a051257bff62be978b6df010fce46a8fdde2cb", + ) bridgeSrcDir := utils.ExpandHome("~/Workspace/projects/teleporter-token-bridge/") // install bridge src dependencies cmd := exec.Command( @@ -172,10 +223,13 @@ func CallDeployBridge(_ []string, flags DeployFlags) error { ux.Logger.PrintToUser(string(out)) return err } - // build teleporter contracts + // build teleporter contracts bytecode + abi cmd = exec.Command( forgePath, "build", + "--extra-output-files", + "abi", + "bin", ) cmd.Dir = filepath.Join(bridgeSrcDir, "contracts") out, err = cmd.CombinedOutput() From a158f30c71116836d09aaa8a39665b3eed6e290d Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Tue, 21 May 2024 16:11:49 -0400 Subject: [PATCH 09/87] adding destination deploy --- cmd/contractcmd/deployBridge.go | 235 +++++++++++++++++++++++++------- 1 file changed, 185 insertions(+), 50 deletions(-) diff --git a/cmd/contractcmd/deployBridge.go b/cmd/contractcmd/deployBridge.go index 42330644c..b21457a0e 100644 --- a/cmd/contractcmd/deployBridge.go +++ b/cmd/contractcmd/deployBridge.go @@ -139,20 +139,22 @@ func deployBridge(_ *cobra.Command, args []string) error { return CallDeployBridge(args, deployFlags) } -func test( +func deployWrappedNativeToken( + srcDir string, rpcURL string, prefundedPrivateKey string, -) error { - srcDir := utils.ExpandHome("~/Workspace/projects/teleporter-token-bridge/") + tokenName string, +) (common.Address, error) { + srcDir = utils.ExpandHome(srcDir) abiPath := filepath.Join(srcDir, "contracts/out/WrappedNativeToken.sol/WrappedNativeToken.abi.json") binPath := filepath.Join(srcDir, "contracts/out/WrappedNativeToken.sol/WrappedNativeToken.bin") abiBytes, err := os.ReadFile(abiPath) if err != nil { - return err + return common.Address{}, err } binBytes, err := os.ReadFile(binPath) if err != nil { - return err + return common.Address{}, err } metadata := &bind.MetaData{ ABI: string(abiBytes), @@ -160,29 +162,143 @@ func test( } abi, err := metadata.GetAbi() if err != nil { - return err + return common.Address{}, err } bin := common.FromHex(metadata.Bin) client, err := evm.GetClient(rpcURL) if err != nil { - return err + return common.Address{}, err } defer client.Close() txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) if err != nil { - return err + return common.Address{}, err } - address, tx, _, err := bind.DeployContract(txOpts, *abi, bin, client, "Al fin", "ALFIN") + address, tx, _, err := bind.DeployContract(txOpts, *abi, bin, client, tokenName) if err != nil { - return err + return common.Address{}, err } if _, success, err := evm.WaitForTransaction(client, tx); err != nil { - return err + return common.Address{}, err } else if !success { - return fmt.Errorf("failed receipt status deploying contract") + return common.Address{}, fmt.Errorf("failed receipt status deploying contract") } - fmt.Println(address) - return nil + return address, nil +} + +func deployNativeTokenSource( + srcDir string, + rpcURL string, + prefundedPrivateKey string, + teleporterRegistryAddress common.Address, + teleporterManagerAddress common.Address, + wrappedNativeTokenAddress common.Address, +) (common.Address, error) { + srcDir = utils.ExpandHome(srcDir) + abiPath := filepath.Join(srcDir, "contracts/out/NativeTokenSource.sol/NativeTokenSource.abi.json") + binPath := filepath.Join(srcDir, "contracts/out/NativeTokenSource.sol/NativeTokenSource.bin") + abiBytes, err := os.ReadFile(abiPath) + if err != nil { + return common.Address{}, err + } + binBytes, err := os.ReadFile(binPath) + if err != nil { + return common.Address{}, err + } + metadata := &bind.MetaData{ + ABI: string(abiBytes), + Bin: string(binBytes), + } + abi, err := metadata.GetAbi() + if err != nil { + return common.Address{}, err + } + bin := common.FromHex(metadata.Bin) + client, err := evm.GetClient(rpcURL) + if err != nil { + return common.Address{}, err + } + defer client.Close() + txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) + if err != nil { + return common.Address{}, err + } + address, tx, _, err := bind.DeployContract(txOpts, *abi, bin, client, teleporterRegistryAddress, teleporterManagerAddress, wrappedNativeTokenAddress) + if err != nil { + return common.Address{}, err + } + if _, success, err := evm.WaitForTransaction(client, tx); err != nil { + return common.Address{}, err + } else if !success { + return common.Address{}, fmt.Errorf("failed receipt status deploying contract") + } + return address, nil +} + +type TeleporterTokenDestinationSettings struct { + TeleporterRegistryAddress common.Address + TeleporterManager common.Address + SourceBlockchainID [32]byte + TokenSourceAddress common.Address +} + +func deployERC20Destination( + srcDir string, + rpcURL string, + prefundedPrivateKey string, + teleporterTokenDestinationSettings TeleporterTokenDestinationSettings, + tokenName string, + tokenSymbol string, + tokenDecimals uint8, +) (common.Address, error) { + srcDir = utils.ExpandHome(srcDir) + abiPath := filepath.Join(srcDir, "contracts/out/ERC20Destination.sol/ERC20Destination.abi.json") + binPath := filepath.Join(srcDir, "contracts/out/ERC20Destination.sol/ERC20Destination.bin") + abiBytes, err := os.ReadFile(abiPath) + if err != nil { + return common.Address{}, err + } + binBytes, err := os.ReadFile(binPath) + if err != nil { + return common.Address{}, err + } + metadata := &bind.MetaData{ + ABI: string(abiBytes), + Bin: string(binBytes), + } + abi, err := metadata.GetAbi() + if err != nil { + return common.Address{}, err + } + bin := common.FromHex(metadata.Bin) + client, err := evm.GetClient(rpcURL) + if err != nil { + return common.Address{}, err + } + defer client.Close() + txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) + if err != nil { + return common.Address{}, err + } + address, tx, _, err := bind.DeployContract( + txOpts, + *abi, + bin, + client, + teleporterTokenDestinationSettings, + tokenName, + tokenSymbol, + tokenDecimals, + ) + if err != nil { + return common.Address{}, err + } + if _, success, err := evm.WaitForTransaction(client, tx); err != nil { + return common.Address{}, err + } else if !success { + return common.Address{}, fmt.Errorf("failed receipt status deploying contract") + } + return address, nil } func CallDeployBridge(_ []string, flags DeployFlags) error { @@ -204,11 +320,57 @@ func CallDeployBridge(_ []string, flags DeployFlags) error { if err != nil { return err } - return test( + bridgeSrcDir := utils.ExpandHome("~/Workspace/projects/teleporter-token-bridge/") + wrappedNativeTokenAddress, err := deployWrappedNativeToken( + bridgeSrcDir, network.BlockchainEndpoint("2FZA3PDpQvYy6uevt34xr7Sv4RczKe3827PWPqAymfqXhJkkGL"), "6e6cb03f2f64e298b28e56bc53a051257bff62be978b6df010fce46a8fdde2cb", + "TOK", ) - bridgeSrcDir := utils.ExpandHome("~/Workspace/projects/teleporter-token-bridge/") + if err != nil { + return err + } + teleporterRegistryAddress := common.HexToAddress("0xbD9e8eC38E43d34CAB4194881B9BF39d639D7Bd3") + teleporterManagerAddress := common.HexToAddress("0x13D42261c6970023fBD486A24AB57c7c8e5DfcB9") + nativeTokenSourceAddress, err := deployNativeTokenSource( + bridgeSrcDir, + network.BlockchainEndpoint("2FZA3PDpQvYy6uevt34xr7Sv4RczKe3827PWPqAymfqXhJkkGL"), + "6e6cb03f2f64e298b28e56bc53a051257bff62be978b6df010fce46a8fdde2cb", + teleporterRegistryAddress, + teleporterManagerAddress, + wrappedNativeTokenAddress, + ) + if err != nil { + return err + } + teleporterRegistryAddress = common.HexToAddress("0x17aB05351fC94a1a67Bf3f56DdbB941aE6c63E25") + teleporterManagerAddress = common.HexToAddress("0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC") + sourceBlockchainID, err := ids.FromString("2FZA3PDpQvYy6uevt34xr7Sv4RczKe3827PWPqAymfqXhJkkGL") + if err != nil { + return err + } + teleporterTokenDestinationSettings := TeleporterTokenDestinationSettings{ + TeleporterRegistryAddress: teleporterRegistryAddress, + TeleporterManager: teleporterManagerAddress, + SourceBlockchainID: sourceBlockchainID, + TokenSourceAddress: wrappedNativeTokenAddress, + } + erc20DestinationAddress, err := deployERC20Destination( + bridgeSrcDir, + network.BlockchainEndpoint("2FZA3PDpQvYy6uevt34xr7Sv4RczKe3827PWPqAymfqXhJkkGL"), + "6e6cb03f2f64e298b28e56bc53a051257bff62be978b6df010fce46a8fdde2cb", + teleporterTokenDestinationSettings, + "Wrapped Token", + "WTOK", + 18, + ) + if err != nil { + return err + } + fmt.Println(wrappedNativeTokenAddress) + fmt.Println(nativeTokenSourceAddress) + fmt.Println(erc20DestinationAddress) + return nil // install bridge src dependencies cmd := exec.Command( "git", @@ -238,33 +400,6 @@ func CallDeployBridge(_ []string, flags DeployFlags) error { return err } return nil - cmd = exec.Command( - forgePath, - "install", - "openzeppelin/openzeppelin-contracts@v4.8.1", - "--no-commit", - ) - cmd.Dir = utils.ExpandHome("~/Workspace/projects/avalanche-cli/") - out, err = cmd.CombinedOutput() - fmt.Println(string(out)) - fmt.Println(err) - createCmd := exec.Command( - forgePath, - "create", - "--rpc-url", - network.BlockchainEndpoint("2FZA3PDpQvYy6uevt34xr7Sv4RczKe3827PWPqAymfqXhJkkGL"), - "--private-key", - "6e6cb03f2f64e298b28e56bc53a051257bff62be978b6df010fce46a8fdde2cb", - "src/5-native-token-bridge/WrappedNativeToken.sol:WrappedNativeToken", - "--constructor-args", - "Wrapped TOK Name", - "WTOK", - ) - createCmd.Dir = utils.ExpandHome("~/Workspace/projects/avalanche-cli/") - out, err = createCmd.CombinedOutput() - fmt.Println(string(out)) - fmt.Println(err) - return nil if !cmdflags.EnsureMutuallyExclusive([]bool{flags.SubnetName != "", flags.BlockchainID != "", flags.CChain}) { return fmt.Errorf("--subnet, --blockchain-id and --cchain are mutually exclusive flags") } @@ -427,7 +562,7 @@ func CallDeployBridge(_ []string, flags DeployFlags) error { rpcURL = flags.RPCURL } td := teleporter.Deployer{} - alreadyDeployed, teleporterMessengerAddress, teleporterRegistryAddress, err := td.Deploy( + alreadyDeployed, teleporterMessengerAddress, teleporterRegistryAddressStr, err := td.Deploy( app.GetTeleporterBinDir(), teleporterVersion, teleporterSubnetDesc, @@ -451,8 +586,8 @@ func CallDeployBridge(_ []string, flags DeployFlags) error { if teleporterMessengerAddress != "" { networkInfo.TeleporterMessengerAddress = teleporterMessengerAddress } - if teleporterRegistryAddress != "" { - networkInfo.TeleporterRegistryAddress = teleporterRegistryAddress + if teleporterRegistryAddressStr != "" { + networkInfo.TeleporterRegistryAddress = teleporterRegistryAddressStr } sc.Networks[network.Name()] = networkInfo if err := app.UpdateSidecar(&sc); err != nil { @@ -465,7 +600,7 @@ func CallDeployBridge(_ []string, flags DeployFlags) error { if err != nil { return err } - alreadyDeployed, teleporterMessengerAddress, teleporterRegistryAddress, err := td.Deploy( + alreadyDeployed, teleporterMessengerAddress, teleporterRegistryAddressStr, err := td.Deploy( app.GetTeleporterBinDir(), teleporterVersion, cChainName, @@ -479,7 +614,7 @@ func CallDeployBridge(_ []string, flags DeployFlags) error { } if !alreadyDeployed { if network.Kind == models.Local { - if err := subnet.WriteExtraLocalNetworkData(app, teleporterMessengerAddress, teleporterRegistryAddress); err != nil { + if err := subnet.WriteExtraLocalNetworkData(app, teleporterMessengerAddress, teleporterRegistryAddressStr); err != nil { return err } } @@ -491,8 +626,8 @@ func CallDeployBridge(_ []string, flags DeployFlags) error { if teleporterMessengerAddress != "" { clusterConfig.ExtraNetworkData.CChainTeleporterMessengerAddress = teleporterMessengerAddress } - if teleporterRegistryAddress != "" { - clusterConfig.ExtraNetworkData.CChainTeleporterRegistryAddress = teleporterRegistryAddress + if teleporterRegistryAddressStr != "" { + clusterConfig.ExtraNetworkData.CChainTeleporterRegistryAddress = teleporterRegistryAddressStr } if err := app.SetClusterConfig(network.ClusterName, clusterConfig); err != nil { return err From 7adfec98e7e67aba95b9e7a35ffa4fb4aee9a294 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Tue, 21 May 2024 16:25:28 -0400 Subject: [PATCH 10/87] deploying the destination --- cmd/contractcmd/deployBridge.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cmd/contractcmd/deployBridge.go b/cmd/contractcmd/deployBridge.go index b21457a0e..e911e2f7f 100644 --- a/cmd/contractcmd/deployBridge.go +++ b/cmd/contractcmd/deployBridge.go @@ -343,6 +343,7 @@ func CallDeployBridge(_ []string, flags DeployFlags) error { if err != nil { return err } + fmt.Println("HASTA ACA LLEGO") teleporterRegistryAddress = common.HexToAddress("0x17aB05351fC94a1a67Bf3f56DdbB941aE6c63E25") teleporterManagerAddress = common.HexToAddress("0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC") sourceBlockchainID, err := ids.FromString("2FZA3PDpQvYy6uevt34xr7Sv4RczKe3827PWPqAymfqXhJkkGL") @@ -353,12 +354,12 @@ func CallDeployBridge(_ []string, flags DeployFlags) error { TeleporterRegistryAddress: teleporterRegistryAddress, TeleporterManager: teleporterManagerAddress, SourceBlockchainID: sourceBlockchainID, - TokenSourceAddress: wrappedNativeTokenAddress, + TokenSourceAddress: nativeTokenSourceAddress, } erc20DestinationAddress, err := deployERC20Destination( bridgeSrcDir, - network.BlockchainEndpoint("2FZA3PDpQvYy6uevt34xr7Sv4RczKe3827PWPqAymfqXhJkkGL"), - "6e6cb03f2f64e298b28e56bc53a051257bff62be978b6df010fce46a8fdde2cb", + network.BlockchainEndpoint("C"), + "56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027", teleporterTokenDestinationSettings, "Wrapped Token", "WTOK", From 92e573c865cf2494c4a723ae564f3588d0a2ff99 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Wed, 22 May 2024 07:43:22 -0400 Subject: [PATCH 11/87] ux design 2 for bridge deploy of fuji --- cmd/contractcmd/deployBridge.go | 635 +++++--------------------------- 1 file changed, 88 insertions(+), 547 deletions(-) diff --git a/cmd/contractcmd/deployBridge.go b/cmd/contractcmd/deployBridge.go index e911e2f7f..c2a108b50 100644 --- a/cmd/contractcmd/deployBridge.go +++ b/cmd/contractcmd/deployBridge.go @@ -3,28 +3,13 @@ package contractcmd import ( - "fmt" - "io" - "os" - "os/exec" - "path/filepath" "strings" - cmdflags "github.com/ava-labs/avalanche-cli/cmd/flags" - "github.com/ava-labs/avalanche-cli/cmd/subnetcmd" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" - "github.com/ava-labs/avalanche-cli/pkg/evm" "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/networkoptions" - "github.com/ava-labs/avalanche-cli/pkg/prompts" - "github.com/ava-labs/avalanche-cli/pkg/subnet" - "github.com/ava-labs/avalanche-cli/pkg/teleporter" "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" - "github.com/ava-labs/avalanche-cli/pkg/vm" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/subnet-evm/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" "github.com/spf13/cobra" ) @@ -43,75 +28,15 @@ type DeployFlags struct { RPCURL string } -const ( - cChainAlias = "C" - cChainName = "c-chain" -) - var ( deployBridgeSupportedNetworkOptions = []networkoptions.NetworkOption{ networkoptions.Local, networkoptions.Devnet, networkoptions.Fuji, } - deployFlags DeployFlags - foundryupPath = utils.ExpandHome("~/.foundry/bin/foundryup") - forgePath = utils.ExpandHome("~/.foundry/bin/forge") + deployFlags DeployFlags ) -func foundryIsInstalled() bool { - return utils.IsExecutable(forgePath) -} - -func installFoundry() error { - ux.Logger.PrintToUser("Installing Foundry") - downloadCmd := exec.Command("curl", "-L", "https://foundry.paradigm.xyz") - installCmd := exec.Command("sh") - var downloadOutbuf, downloadErrbuf strings.Builder - downloadCmdStdoutPipe, err := downloadCmd.StdoutPipe() - if err != nil { - return err - } - downloadCmd.Stderr = &downloadErrbuf - installCmd.Stdin = io.TeeReader(downloadCmdStdoutPipe, &downloadOutbuf) - var installOutbuf, installErrbuf strings.Builder - installCmd.Stdout = &installOutbuf - installCmd.Stderr = &installErrbuf - if err := installCmd.Start(); err != nil { - return err - } - if err := downloadCmd.Run(); err != nil { - if downloadOutbuf.String() != "" { - ux.Logger.PrintToUser(strings.TrimSuffix(downloadOutbuf.String(), "\n")) - } - if downloadErrbuf.String() != "" { - ux.Logger.PrintToUser(strings.TrimSuffix(downloadErrbuf.String(), "\n")) - } - return err - } - if err := installCmd.Wait(); err != nil { - if installOutbuf.String() != "" { - ux.Logger.PrintToUser(strings.TrimSuffix(installOutbuf.String(), "\n")) - } - if installErrbuf.String() != "" { - ux.Logger.PrintToUser(strings.TrimSuffix(installErrbuf.String(), "\n")) - } - ux.Logger.PrintToUser("installation failed: %s", err.Error()) - return err - } - ux.Logger.PrintToUser(strings.TrimSuffix(installOutbuf.String(), "\n")) - out, err := exec.Command(foundryupPath).CombinedOutput() - ux.Logger.PrintToUser(string(out)) - if err != nil { - ux.Logger.PrintToUser("") - ux.Logger.PrintToUser("Foundry toolset is not available and couldn't automatically be installed. It is a necessary dependency for CLI to compile smart contracts.") - ux.Logger.PrintToUser("") - ux.Logger.PrintToUser("Please follow install instructions at https://book.getfoundry.sh/getting-started/installation and try again") - ux.Logger.PrintToUser("") - } - return err -} - // avalanche contract deploy bridge func newDeployBridgeCmd() *cobra.Command { cmd := &cobra.Command{ @@ -122,16 +47,6 @@ func newDeployBridgeCmd() *cobra.Command { Args: cobrautils.ExactArgs(0), } networkoptions.AddNetworkFlagsToCmd(cmd, &deployFlags.Network, true, deployBridgeSupportedNetworkOptions) - cmd.Flags().StringVar(&deployFlags.SubnetName, "subnet", "", "deploy teleporter into the given CLI subnet") - cmd.Flags().StringVar(&deployFlags.BlockchainID, "blockchain-id", "", "deploy teleporter into the given blockchain ID/Alias") - cmd.Flags().BoolVar(&deployFlags.CChain, "c-chain", false, "deploy teleporter into C-Chain") - cmd.Flags().StringVar(&deployFlags.PrivateKey, "private-key", "", "private key to use to fund teleporter deploy)") - cmd.Flags().StringVar(&deployFlags.KeyName, "key", "", "CLI stored key to use to fund teleporter deploy)") - cmd.Flags().BoolVar(&deployFlags.GenesisKey, "genesis-key", false, "use genesis aidrop key to fund teleporter deploy") - cmd.Flags().BoolVar(&deployFlags.DeployMessenger, "deploy-messenger", true, "deploy Teleporter Messenger") - cmd.Flags().BoolVar(&deployFlags.DeployRegistry, "deploy-registry", true, "deploy Teleporter Registry") - cmd.Flags().StringVar(&deployFlags.TeleporterVersion, "version", "latest", "version to deploy") - cmd.Flags().StringVar(&deployFlags.RPCURL, "rpc-url", "", "use the given RPC URL to connect to the subnet") return cmd } @@ -139,175 +54,7 @@ func deployBridge(_ *cobra.Command, args []string) error { return CallDeployBridge(args, deployFlags) } -func deployWrappedNativeToken( - srcDir string, - rpcURL string, - prefundedPrivateKey string, - tokenName string, -) (common.Address, error) { - srcDir = utils.ExpandHome(srcDir) - abiPath := filepath.Join(srcDir, "contracts/out/WrappedNativeToken.sol/WrappedNativeToken.abi.json") - binPath := filepath.Join(srcDir, "contracts/out/WrappedNativeToken.sol/WrappedNativeToken.bin") - abiBytes, err := os.ReadFile(abiPath) - if err != nil { - return common.Address{}, err - } - binBytes, err := os.ReadFile(binPath) - if err != nil { - return common.Address{}, err - } - metadata := &bind.MetaData{ - ABI: string(abiBytes), - Bin: string(binBytes), - } - abi, err := metadata.GetAbi() - if err != nil { - return common.Address{}, err - } - bin := common.FromHex(metadata.Bin) - client, err := evm.GetClient(rpcURL) - if err != nil { - return common.Address{}, err - } - defer client.Close() - txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) - if err != nil { - return common.Address{}, err - } - address, tx, _, err := bind.DeployContract(txOpts, *abi, bin, client, tokenName) - if err != nil { - return common.Address{}, err - } - if _, success, err := evm.WaitForTransaction(client, tx); err != nil { - return common.Address{}, err - } else if !success { - return common.Address{}, fmt.Errorf("failed receipt status deploying contract") - } - return address, nil -} - -func deployNativeTokenSource( - srcDir string, - rpcURL string, - prefundedPrivateKey string, - teleporterRegistryAddress common.Address, - teleporterManagerAddress common.Address, - wrappedNativeTokenAddress common.Address, -) (common.Address, error) { - srcDir = utils.ExpandHome(srcDir) - abiPath := filepath.Join(srcDir, "contracts/out/NativeTokenSource.sol/NativeTokenSource.abi.json") - binPath := filepath.Join(srcDir, "contracts/out/NativeTokenSource.sol/NativeTokenSource.bin") - abiBytes, err := os.ReadFile(abiPath) - if err != nil { - return common.Address{}, err - } - binBytes, err := os.ReadFile(binPath) - if err != nil { - return common.Address{}, err - } - metadata := &bind.MetaData{ - ABI: string(abiBytes), - Bin: string(binBytes), - } - abi, err := metadata.GetAbi() - if err != nil { - return common.Address{}, err - } - bin := common.FromHex(metadata.Bin) - client, err := evm.GetClient(rpcURL) - if err != nil { - return common.Address{}, err - } - defer client.Close() - txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) - if err != nil { - return common.Address{}, err - } - address, tx, _, err := bind.DeployContract(txOpts, *abi, bin, client, teleporterRegistryAddress, teleporterManagerAddress, wrappedNativeTokenAddress) - if err != nil { - return common.Address{}, err - } - if _, success, err := evm.WaitForTransaction(client, tx); err != nil { - return common.Address{}, err - } else if !success { - return common.Address{}, fmt.Errorf("failed receipt status deploying contract") - } - return address, nil -} - -type TeleporterTokenDestinationSettings struct { - TeleporterRegistryAddress common.Address - TeleporterManager common.Address - SourceBlockchainID [32]byte - TokenSourceAddress common.Address -} - -func deployERC20Destination( - srcDir string, - rpcURL string, - prefundedPrivateKey string, - teleporterTokenDestinationSettings TeleporterTokenDestinationSettings, - tokenName string, - tokenSymbol string, - tokenDecimals uint8, -) (common.Address, error) { - srcDir = utils.ExpandHome(srcDir) - abiPath := filepath.Join(srcDir, "contracts/out/ERC20Destination.sol/ERC20Destination.abi.json") - binPath := filepath.Join(srcDir, "contracts/out/ERC20Destination.sol/ERC20Destination.bin") - abiBytes, err := os.ReadFile(abiPath) - if err != nil { - return common.Address{}, err - } - binBytes, err := os.ReadFile(binPath) - if err != nil { - return common.Address{}, err - } - metadata := &bind.MetaData{ - ABI: string(abiBytes), - Bin: string(binBytes), - } - abi, err := metadata.GetAbi() - if err != nil { - return common.Address{}, err - } - bin := common.FromHex(metadata.Bin) - client, err := evm.GetClient(rpcURL) - if err != nil { - return common.Address{}, err - } - defer client.Close() - txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) - if err != nil { - return common.Address{}, err - } - address, tx, _, err := bind.DeployContract( - txOpts, - *abi, - bin, - client, - teleporterTokenDestinationSettings, - tokenName, - tokenSymbol, - tokenDecimals, - ) - if err != nil { - return common.Address{}, err - } - if _, success, err := evm.WaitForTransaction(client, tx); err != nil { - return common.Address{}, err - } else if !success { - return common.Address{}, fmt.Errorf("failed receipt status deploying contract") - } - return address, nil -} - func CallDeployBridge(_ []string, flags DeployFlags) error { - if err := vm.CheckGitIsInstalled(); err != nil { - return err - } - if !foundryIsInstalled() { - return installFoundry() - } network, err := networkoptions.GetNetworkFromCmdLineFlags( app, "On what Network do you want to deploy the Teleporter bridge?", @@ -320,321 +67,115 @@ func CallDeployBridge(_ []string, flags DeployFlags) error { if err != nil { return err } - bridgeSrcDir := utils.ExpandHome("~/Workspace/projects/teleporter-token-bridge/") - wrappedNativeTokenAddress, err := deployWrappedNativeToken( - bridgeSrcDir, - network.BlockchainEndpoint("2FZA3PDpQvYy6uevt34xr7Sv4RczKe3827PWPqAymfqXhJkkGL"), - "6e6cb03f2f64e298b28e56bc53a051257bff62be978b6df010fce46a8fdde2cb", - "TOK", - ) - if err != nil { - return err - } - teleporterRegistryAddress := common.HexToAddress("0xbD9e8eC38E43d34CAB4194881B9BF39d639D7Bd3") - teleporterManagerAddress := common.HexToAddress("0x13D42261c6970023fBD486A24AB57c7c8e5DfcB9") - nativeTokenSourceAddress, err := deployNativeTokenSource( - bridgeSrcDir, - network.BlockchainEndpoint("2FZA3PDpQvYy6uevt34xr7Sv4RczKe3827PWPqAymfqXhJkkGL"), - "6e6cb03f2f64e298b28e56bc53a051257bff62be978b6df010fce46a8fdde2cb", - teleporterRegistryAddress, - teleporterManagerAddress, - wrappedNativeTokenAddress, - ) - if err != nil { - return err - } - fmt.Println("HASTA ACA LLEGO") - teleporterRegistryAddress = common.HexToAddress("0x17aB05351fC94a1a67Bf3f56DdbB941aE6c63E25") - teleporterManagerAddress = common.HexToAddress("0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC") - sourceBlockchainID, err := ids.FromString("2FZA3PDpQvYy6uevt34xr7Sv4RczKe3827PWPqAymfqXhJkkGL") - if err != nil { - return err - } - teleporterTokenDestinationSettings := TeleporterTokenDestinationSettings{ - TeleporterRegistryAddress: teleporterRegistryAddress, - TeleporterManager: teleporterManagerAddress, - SourceBlockchainID: sourceBlockchainID, - TokenSourceAddress: nativeTokenSourceAddress, - } - erc20DestinationAddress, err := deployERC20Destination( - bridgeSrcDir, - network.BlockchainEndpoint("C"), - "56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027", - teleporterTokenDestinationSettings, - "Wrapped Token", - "WTOK", - 18, - ) - if err != nil { - return err - } - fmt.Println(wrappedNativeTokenAddress) - fmt.Println(nativeTokenSourceAddress) - fmt.Println(erc20DestinationAddress) - return nil - // install bridge src dependencies - cmd := exec.Command( - "git", - "submodule", - "update", - "--init", - "--recursive", - ) - cmd.Dir = bridgeSrcDir - out, err := cmd.CombinedOutput() - if err != nil { - ux.Logger.PrintToUser(string(out)) - return err - } - // build teleporter contracts bytecode + abi - cmd = exec.Command( - forgePath, - "build", - "--extra-output-files", - "abi", - "bin", - ) - cmd.Dir = filepath.Join(bridgeSrcDir, "contracts") - out, err = cmd.CombinedOutput() - if err != nil { - ux.Logger.PrintToUser(string(out)) - return err - } - return nil - if !cmdflags.EnsureMutuallyExclusive([]bool{flags.SubnetName != "", flags.BlockchainID != "", flags.CChain}) { - return fmt.Errorf("--subnet, --blockchain-id and --cchain are mutually exclusive flags") - } - if !cmdflags.EnsureMutuallyExclusive([]bool{flags.PrivateKey != "", flags.KeyName != "", flags.GenesisKey}) { - return fmt.Errorf("--private-key, --key and --genesis-key are mutually exclusive flags") - } - if !flags.DeployMessenger && !flags.DeployRegistry { - return fmt.Errorf("you should set at least one of --deploy-messenger/--deploy-registry to true") - } - if flags.SubnetName == "" && flags.BlockchainID == "" && !flags.CChain { - // fill flags based on user prompts - blockchainIDOptions := []string{ - "Get Blockchain ID from an existing subnet (deployed with avalanche subnet deploy)", - "Use C-Chain Blockchain ID", - "Custom", - } - blockchainIDOption, err := app.Prompt.CaptureList("Which Blockchain ID would you like to deploy Teleporter to?", blockchainIDOptions) - if err != nil { - return err - } - switch blockchainIDOption { - case blockchainIDOptions[0]: - subnetNames, err := app.GetSubnetNames() - if err != nil { - return err - } - flags.SubnetName, err = app.Prompt.CaptureList( - "Choose a Subnet", - subnetNames, - ) - if err != nil { - return err - } - case blockchainIDOptions[1]: - flags.CChain = true - default: - flags.BlockchainID, err = app.Prompt.CaptureString("Blockchain ID/Alias") - if err != nil { - return err - } - } - } - - var ( - blockchainID string - teleporterSubnetDesc string - privateKey = flags.PrivateKey - teleporterVersion string - ) - switch { - case flags.SubnetName != "": - teleporterSubnetDesc = flags.SubnetName - sc, err := app.LoadSidecar(flags.SubnetName) - if err != nil { - return fmt.Errorf("failed to load sidecar: %w", err) - } - if b, _, err := subnetcmd.HasSubnetEVMGenesis(flags.SubnetName); err != nil { - return err - } else if !b { - return fmt.Errorf("only Subnet-EVM based vms can be used for teleporter") - } - if sc.Networks[network.Name()].BlockchainID == ids.Empty { - return fmt.Errorf("subnet has not been deployed to %s", network.Name()) - } - blockchainID = sc.Networks[network.Name()].BlockchainID.String() - if sc.TeleporterVersion != "" { - teleporterVersion = sc.TeleporterVersion - } - if sc.TeleporterKey != "" { - k, err := app.GetKey(sc.TeleporterKey, network, true) - if err != nil { - return err - } - privateKey = k.PrivKeyHex() - } - case flags.BlockchainID != "": - teleporterSubnetDesc = flags.BlockchainID - blockchainID = flags.BlockchainID - case flags.CChain: - teleporterSubnetDesc = cChainName - blockchainID = cChainAlias - } - var chainID ids.ID - if flags.CChain || !network.StandardPublicEndpoint() { - chainID, err = utils.GetChainID(network.Endpoint, blockchainID) + switch network.Kind { + case models.Local: + ux.Logger.PrintToUser("To be defined") + return nil + case models.Devnet: + ux.Logger.PrintToUser("To be defined") + return nil + case models.Fuji: + subnetNames, err := app.GetSubnetNames() if err != nil { return err } - } else { - chainID, err = ids.FromString(blockchainID) - if err != nil { - return err - } - } - createChainTx, err := utils.GetBlockchainTx(network.Endpoint, chainID) - if err != nil { - return err - } - if !utils.ByteSliceIsSubnetEvmGenesis(createChainTx.GenesisData) { - return fmt.Errorf("teleporter can only be deployed to Subnet-EVM based vms") - } - if flags.KeyName != "" { - k, err := app.GetKey(flags.KeyName, network, false) + subnetOptions := utils.Map(subnetNames, func(s string) string { return "Subnet " + s }) + prompt := "Where is the Token origin?" + cChainOption := "C-Chain" + notListedOption := "My blockchain isn't listed" + subnetOptions = append(append([]string{cChainOption}, subnetOptions...), notListedOption) + subnetOption, err := app.Prompt.CaptureListWithSize( + prompt, + subnetOptions, + 11, + ) if err != nil { return err } - privateKey = k.PrivKeyHex() - } - _, genesisAddress, genesisPrivateKey, err := subnet.GetSubnetAirdropKeyInfo(app, network, flags.SubnetName, createChainTx.GenesisData) - if err != nil { - return err - } - if flags.GenesisKey { - privateKey = genesisPrivateKey - } - if privateKey == "" { - cliKeyOpt := "Get private key from an existing stored key (created from avalanche key create or avalanche key import)" - customKeyOpt := "Custom" - genesisKeyOpt := fmt.Sprintf("Use the private key of the Genesis Aidrop address %s", genesisAddress) - keyOptions := []string{cliKeyOpt, customKeyOpt} - if genesisPrivateKey != "" { - keyOptions = []string{genesisKeyOpt, cliKeyOpt, customKeyOpt} - } - keyOption, err := app.Prompt.CaptureList("Which private key do you want to use to pay fees?", keyOptions) - if err != nil { - return err + if subnetOption == notListedOption { + ux.Logger.PrintToUser("Please import the subnet first, using the `avalanche subnet import` command suite") + return nil } - switch keyOption { - case cliKeyOpt: - keyName, err := prompts.CaptureKeyName(app.Prompt, "pay fees", app.GetKeyDir(), true) + tokenSymbol := "AVAX" + if subnetOption != cChainOption { + subnetName := strings.TrimPrefix(subnetOption, "Subnet ") + sc, err := app.LoadSidecar(subnetName) if err != nil { return err } - k, err := app.GetKey(keyName, network, false) - if err != nil { - return err - } - privateKey = k.PrivKeyHex() - case customKeyOpt: - privateKey, err = app.Prompt.CaptureString("Private Key") + tokenSymbol = sc.TokenSymbol + } + prompt = "What kind of token do you want to bridge?" + popularOption := "A popular token (e.g. AVAX, USDC, WAVAX, ...)" + existingOriginOption := "A token with an existing Origin Bridge" + nativeOption := "The native token " + tokenSymbol + erc20Option := "An ERC-20 token" + explainOption := "Explain the difference" + popularTokens := getPopularTokens(network, subnetOption) + options := []string{popularOption, existingOriginOption, nativeOption, erc20Option, explainOption} + if len(popularTokens) == 0 { + options = []string{existingOriginOption, nativeOption, erc20Option, explainOption} + } + for { + option, err := app.Prompt.CaptureList( + prompt, + options, + ) if err != nil { return err } - case genesisKeyOpt: - privateKey = genesisPrivateKey - } - } - if flags.TeleporterVersion != "" && flags.TeleporterVersion != "latest" { - teleporterVersion = flags.TeleporterVersion - } else if teleporterVersion == "" { - teleporterInfo, err := teleporter.GetInfo(app) - if err != nil { - return err - } - teleporterVersion = teleporterInfo.Version - } - // deploy to subnet - rpcURL := network.BlockchainEndpoint(blockchainID) - if flags.RPCURL != "" { - rpcURL = flags.RPCURL - } - td := teleporter.Deployer{} - alreadyDeployed, teleporterMessengerAddress, teleporterRegistryAddressStr, err := td.Deploy( - app.GetTeleporterBinDir(), - teleporterVersion, - teleporterSubnetDesc, - rpcURL, - privateKey, - flags.DeployMessenger, - flags.DeployRegistry, - ) - if err != nil { - return err - } - if flags.SubnetName != "" && !alreadyDeployed { - // update sidecar - sc, err := app.LoadSidecar(flags.SubnetName) - if err != nil { - return fmt.Errorf("failed to load sidecar: %w", err) - } - sc.TeleporterReady = true - sc.TeleporterVersion = teleporterVersion - networkInfo := sc.Networks[network.Name()] - if teleporterMessengerAddress != "" { - networkInfo.TeleporterMessengerAddress = teleporterMessengerAddress - } - if teleporterRegistryAddressStr != "" { - networkInfo.TeleporterRegistryAddress = teleporterRegistryAddressStr - } - sc.Networks[network.Name()] = networkInfo - if err := app.UpdateSidecar(&sc); err != nil { - return err - } - } - // automatic deploy to cchain for local/devnet - if !flags.CChain && (network.Kind == models.Local || network.Kind == models.Devnet) { - ewoq, err := app.GetKey("ewoq", network, false) - if err != nil { - return err - } - alreadyDeployed, teleporterMessengerAddress, teleporterRegistryAddressStr, err := td.Deploy( - app.GetTeleporterBinDir(), - teleporterVersion, - cChainName, - network.BlockchainEndpoint(cChainAlias), - ewoq.PrivKeyHex(), - flags.DeployMessenger, - flags.DeployRegistry, - ) - if err != nil { - return err - } - if !alreadyDeployed { - if network.Kind == models.Local { - if err := subnet.WriteExtraLocalNetworkData(app, teleporterMessengerAddress, teleporterRegistryAddressStr); err != nil { + switch option { + case popularOption: + _, err = app.Prompt.CaptureList( + "Choose Token", + popularTokens, + ) + if err != nil { return err } - } - if network.ClusterName != "" { - clusterConfig, err := app.GetClusterConfig(network.ClusterName) + case existingOriginOption: + _, err = app.Prompt.CaptureAddress( + "Enter the address of the Origin Bridge", + ) if err != nil { return err } - if teleporterMessengerAddress != "" { - clusterConfig.ExtraNetworkData.CChainTeleporterMessengerAddress = teleporterMessengerAddress - } - if teleporterRegistryAddressStr != "" { - clusterConfig.ExtraNetworkData.CChainTeleporterRegistryAddress = teleporterRegistryAddressStr - } - if err := app.SetClusterConfig(network.ClusterName, clusterConfig); err != nil { + case erc20Option: + _, err = app.Prompt.CaptureAddress( + "Enter the address of the ERC-20 Token", + ) + if err != nil { return err } + case explainOption: + ux.Logger.PrintToUser("The difference is...") + ux.Logger.PrintToUser("") + continue } + break + } + prompt = "Where should the token be bridged as an ERC-20?" + subnetOptions = utils.Filter(subnetOptions, func(s string) bool { return s != subnetOption }) + subnetOption, err = app.Prompt.CaptureListWithSize( + prompt, + subnetOptions, + 11, + ) + if err != nil { + return err + } + if subnetOption == notListedOption { + ux.Logger.PrintToUser("Please import the subnet first, using the `avalanche subnet import` command suite") + return nil } } return nil } + +func getPopularTokens(network models.Network, subnetOption string) []string { + if network.Kind == models.Fuji && subnetOption == "C-Chain" { + return []string{"AVAX", "USDC", "WAVAX"} + } else { + return []string{} + } +} From d37e5b94f38c157b18b8ce4ada1b90d52661e656 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Thu, 23 May 2024 12:40:29 -0400 Subject: [PATCH 12/87] add popular token info list --- cmd/contractcmd/deployBridge.go | 46 ++++++++++++++++++++++---- cmd/contractcmd/popularTokensInfo.json | 19 +++++++++++ 2 files changed, 59 insertions(+), 6 deletions(-) create mode 100644 cmd/contractcmd/popularTokensInfo.json diff --git a/cmd/contractcmd/deployBridge.go b/cmd/contractcmd/deployBridge.go index c2a108b50..3d5bad0bd 100644 --- a/cmd/contractcmd/deployBridge.go +++ b/cmd/contractcmd/deployBridge.go @@ -3,6 +3,9 @@ package contractcmd import ( + _ "embed" + "encoding/json" + "fmt" "strings" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" @@ -111,9 +114,18 @@ func CallDeployBridge(_ []string, flags DeployFlags) error { nativeOption := "The native token " + tokenSymbol erc20Option := "An ERC-20 token" explainOption := "Explain the difference" - popularTokens := getPopularTokens(network, subnetOption) + popularTokensInfo, err := getPopularTokensInfo(network, subnetOption) + if err != nil { + return err + } + popularTokensDesc := utils.Map( + popularTokensInfo, + func(i PopularTokenInfo) string { + return i.Desc() + }, + ) options := []string{popularOption, existingOriginOption, nativeOption, erc20Option, explainOption} - if len(popularTokens) == 0 { + if len(popularTokensDesc) == 0 { options = []string{existingOriginOption, nativeOption, erc20Option, explainOption} } for { @@ -128,7 +140,7 @@ func CallDeployBridge(_ []string, flags DeployFlags) error { case popularOption: _, err = app.Prompt.CaptureList( "Choose Token", - popularTokens, + popularTokensDesc, ) if err != nil { return err @@ -172,10 +184,32 @@ func CallDeployBridge(_ []string, flags DeployFlags) error { return nil } -func getPopularTokens(network models.Network, subnetOption string) []string { +type PopularTokenInfo struct { + TokenName string + TokenContractAddress string + BridgeHubAddress string +} + +//go:embed popularTokensInfo.json +var popularTokensInfoByteSlice []byte + +var popularTokensInfo map[string][]PopularTokenInfo + +func (i PopularTokenInfo) Desc() string { + if i.TokenContractAddress == "" { + return i.TokenName + } else { + return fmt.Sprintf("%s | Token address %s | Hub bridge address %s", i.TokenName, i.TokenContractAddress, i.BridgeHubAddress) + } +} + +func getPopularTokensInfo(network models.Network, subnetOption string) ([]PopularTokenInfo, error) { + if err := json.Unmarshal(popularTokensInfoByteSlice, &popularTokensInfo); err != nil { + return nil, fmt.Errorf("unabled to get popular tokens info from file: %w", err) + } if network.Kind == models.Fuji && subnetOption == "C-Chain" { - return []string{"AVAX", "USDC", "WAVAX"} + return popularTokensInfo[models.Fuji.String()], nil } else { - return []string{} + return nil, nil } } diff --git a/cmd/contractcmd/popularTokensInfo.json b/cmd/contractcmd/popularTokensInfo.json new file mode 100644 index 000000000..b8dcbb82b --- /dev/null +++ b/cmd/contractcmd/popularTokensInfo.json @@ -0,0 +1,19 @@ +{ + "Fuji": [ + { + "TokenName": "AVAX", + "TokenContractAddress": "", + "BridgeHubAddress": "" + }, + { + "TokenName": "USDC", + "TokenContractAddress": "0x5425890298aed601595a70AB815c96711a31Bc65", + "BridgeHubAddress": "0x5425890298aed601595a70AB815c96711a31Bc65" + }, + { + "TokenName": "WAVAX", + "TokenContractAddress": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c", + "BridgeHubAddress": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c" + } + ] +} \ No newline at end of file From 04bd4ebb44f0d95832fb03f8915bb375a930cb59 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Thu, 23 May 2024 12:43:03 -0400 Subject: [PATCH 13/87] move to new file --- cmd/contractcmd/deployBridge.go | 34 +---------------------- cmd/contractcmd/popularTokensInfo.go | 41 ++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 33 deletions(-) create mode 100644 cmd/contractcmd/popularTokensInfo.go diff --git a/cmd/contractcmd/deployBridge.go b/cmd/contractcmd/deployBridge.go index 3d5bad0bd..79c38801e 100644 --- a/cmd/contractcmd/deployBridge.go +++ b/cmd/contractcmd/deployBridge.go @@ -4,8 +4,6 @@ package contractcmd import ( _ "embed" - "encoding/json" - "fmt" "strings" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" @@ -114,7 +112,7 @@ func CallDeployBridge(_ []string, flags DeployFlags) error { nativeOption := "The native token " + tokenSymbol erc20Option := "An ERC-20 token" explainOption := "Explain the difference" - popularTokensInfo, err := getPopularTokensInfo(network, subnetOption) + popularTokensInfo, err := GetPopularTokensInfo(network, subnetOption) if err != nil { return err } @@ -183,33 +181,3 @@ func CallDeployBridge(_ []string, flags DeployFlags) error { } return nil } - -type PopularTokenInfo struct { - TokenName string - TokenContractAddress string - BridgeHubAddress string -} - -//go:embed popularTokensInfo.json -var popularTokensInfoByteSlice []byte - -var popularTokensInfo map[string][]PopularTokenInfo - -func (i PopularTokenInfo) Desc() string { - if i.TokenContractAddress == "" { - return i.TokenName - } else { - return fmt.Sprintf("%s | Token address %s | Hub bridge address %s", i.TokenName, i.TokenContractAddress, i.BridgeHubAddress) - } -} - -func getPopularTokensInfo(network models.Network, subnetOption string) ([]PopularTokenInfo, error) { - if err := json.Unmarshal(popularTokensInfoByteSlice, &popularTokensInfo); err != nil { - return nil, fmt.Errorf("unabled to get popular tokens info from file: %w", err) - } - if network.Kind == models.Fuji && subnetOption == "C-Chain" { - return popularTokensInfo[models.Fuji.String()], nil - } else { - return nil, nil - } -} diff --git a/cmd/contractcmd/popularTokensInfo.go b/cmd/contractcmd/popularTokensInfo.go new file mode 100644 index 000000000..886e31a34 --- /dev/null +++ b/cmd/contractcmd/popularTokensInfo.go @@ -0,0 +1,41 @@ +// Copyright (C) 2022, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +package contractcmd + +import ( + _ "embed" + "encoding/json" + "fmt" + + "github.com/ava-labs/avalanche-cli/pkg/models" +) + +type PopularTokenInfo struct { + TokenName string + TokenContractAddress string + BridgeHubAddress string +} + +//go:embed popularTokensInfo.json +var popularTokensInfoByteSlice []byte + +var popularTokensInfo map[string][]PopularTokenInfo + +func (i PopularTokenInfo) Desc() string { + if i.TokenContractAddress == "" { + return i.TokenName + } else { + return fmt.Sprintf("%s | Token address %s | Hub bridge address %s", i.TokenName, i.TokenContractAddress, i.BridgeHubAddress) + } +} + +func GetPopularTokensInfo(network models.Network, subnetOption string) ([]PopularTokenInfo, error) { + if err := json.Unmarshal(popularTokensInfoByteSlice, &popularTokensInfo); err != nil { + return nil, fmt.Errorf("unabled to get popular tokens info from file: %w", err) + } + if network.Kind == models.Fuji && subnetOption == "C-Chain" { + return popularTokensInfo[models.Fuji.String()], nil + } else { + return nil, nil + } +} From c836def618070e8a983a29321a3c42bb22f6b9fc Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Fri, 24 May 2024 07:16:54 -0400 Subject: [PATCH 14/87] add blockchain alias to popular tokens json --- cmd/contractcmd/popularTokensInfo.go | 8 +++--- cmd/contractcmd/popularTokensInfo.json | 37 ++++++++++++++------------ 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/cmd/contractcmd/popularTokensInfo.go b/cmd/contractcmd/popularTokensInfo.go index 886e31a34..b5e179c66 100644 --- a/cmd/contractcmd/popularTokensInfo.go +++ b/cmd/contractcmd/popularTokensInfo.go @@ -19,7 +19,7 @@ type PopularTokenInfo struct { //go:embed popularTokensInfo.json var popularTokensInfoByteSlice []byte -var popularTokensInfo map[string][]PopularTokenInfo +var popularTokensInfo map[string]map[string][]PopularTokenInfo func (i PopularTokenInfo) Desc() string { if i.TokenContractAddress == "" { @@ -29,12 +29,12 @@ func (i PopularTokenInfo) Desc() string { } } -func GetPopularTokensInfo(network models.Network, subnetOption string) ([]PopularTokenInfo, error) { +func GetPopularTokensInfo(network models.Network, blockchainAlias string) ([]PopularTokenInfo, error) { if err := json.Unmarshal(popularTokensInfoByteSlice, &popularTokensInfo); err != nil { return nil, fmt.Errorf("unabled to get popular tokens info from file: %w", err) } - if network.Kind == models.Fuji && subnetOption == "C-Chain" { - return popularTokensInfo[models.Fuji.String()], nil + if network.Kind == models.Fuji { + return popularTokensInfo[models.Fuji.String()][blockchainAlias], nil } else { return nil, nil } diff --git a/cmd/contractcmd/popularTokensInfo.json b/cmd/contractcmd/popularTokensInfo.json index b8dcbb82b..44241e99d 100644 --- a/cmd/contractcmd/popularTokensInfo.json +++ b/cmd/contractcmd/popularTokensInfo.json @@ -1,19 +1,22 @@ { - "Fuji": [ - { - "TokenName": "AVAX", - "TokenContractAddress": "", - "BridgeHubAddress": "" - }, - { - "TokenName": "USDC", - "TokenContractAddress": "0x5425890298aed601595a70AB815c96711a31Bc65", - "BridgeHubAddress": "0x5425890298aed601595a70AB815c96711a31Bc65" - }, - { - "TokenName": "WAVAX", - "TokenContractAddress": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c", - "BridgeHubAddress": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c" - } + "Fuji": { + "C-Chain": [ + { + "TokenName": "AVAX", + "TokenContractAddress": "", + "BridgeHubAddress": "" + }, + { + "TokenName": "USDC", + "TokenContractAddress": "0x5425890298aed601595a70AB815c96711a31Bc65", + "BridgeHubAddress": "0x5425890298aed601595a70AB815c96711a31Bc65" + }, + { + "TokenName": "WAVAX", + "TokenContractAddress": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c", + "BridgeHubAddress": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c" + } ] -} \ No newline at end of file + } +} + From 64c1eac99f2839a46846ca4bb189924f163798d3 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Fri, 24 May 2024 07:24:02 -0400 Subject: [PATCH 15/87] start using teleporter bridge deploy --- cmd/contractcmd/contract.go | 26 ---------------- cmd/root.go | 4 --- .../deploy.go => teleportercmd/bridge.go} | 14 ++++----- .../bridgeDeploy.go} | 30 +++++++++---------- .../popularTokensInfo.go | 2 +- .../popularTokensInfo.json | 0 cmd/teleportercmd/teleporter.go | 2 ++ 7 files changed, 25 insertions(+), 53 deletions(-) delete mode 100644 cmd/contractcmd/contract.go rename cmd/{contractcmd/deploy.go => teleportercmd/bridge.go} (51%) rename cmd/{contractcmd/deployBridge.go => teleportercmd/bridgeDeploy.go} (86%) rename cmd/{contractcmd => teleportercmd}/popularTokensInfo.go (98%) rename cmd/{contractcmd => teleportercmd}/popularTokensInfo.json (100%) diff --git a/cmd/contractcmd/contract.go b/cmd/contractcmd/contract.go deleted file mode 100644 index 52f866299..000000000 --- a/cmd/contractcmd/contract.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (C) 2022, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. -package contractcmd - -import ( - "github.com/ava-labs/avalanche-cli/pkg/application" - "github.com/ava-labs/avalanche-cli/pkg/cobrautils" - "github.com/spf13/cobra" -) - -var app *application.Avalanche - -// avalanche contract -func NewCmd(injectedApp *application.Avalanche) *cobra.Command { - cmd := &cobra.Command{ - Use: "contract", - Short: "Interact with smart contracts", - Long: `The contract command suite provides a collection of tools for interacting -with Smart Contracts.`, - RunE: cobrautils.CommandSuiteUsage, - } - app = injectedApp - // contract deploy - cmd.AddCommand(newDeployCmd()) - return cmd -} diff --git a/cmd/root.go b/cmd/root.go index 76e1cb466..7c157fba4 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -18,7 +18,6 @@ import ( "github.com/ava-labs/avalanche-cli/cmd/configcmd" "github.com/ava-labs/avalanche-cli/cmd/backendcmd" - "github.com/ava-labs/avalanche-cli/cmd/contractcmd" "github.com/ava-labs/avalanche-cli/cmd/keycmd" "github.com/ava-labs/avalanche-cli/cmd/networkcmd" "github.com/ava-labs/avalanche-cli/cmd/subnetcmd" @@ -99,9 +98,6 @@ in with avalanche subnet create myNewSubnet.`, // add teleporter command rootCmd.AddCommand(teleportercmd.NewCmd(app)) - // add contract command - rootCmd.AddCommand(contractcmd.NewCmd(app)) - cobrautils.ConfigureRootCmd(rootCmd) return rootCmd diff --git a/cmd/contractcmd/deploy.go b/cmd/teleportercmd/bridge.go similarity index 51% rename from cmd/contractcmd/deploy.go rename to cmd/teleportercmd/bridge.go index 2b5c0376a..b5b8f1511 100644 --- a/cmd/contractcmd/deploy.go +++ b/cmd/teleportercmd/bridge.go @@ -1,21 +1,21 @@ // Copyright (C) 2022, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package contractcmd +package teleportercmd import ( "github.com/ava-labs/avalanche-cli/pkg/cobrautils" "github.com/spf13/cobra" ) -// avalanche contract deploy -func newDeployCmd() *cobra.Command { +// avalanche teleporter bridge +func newBridgeCmd() *cobra.Command { cmd := &cobra.Command{ - Use: "deploy", - Short: "Deploy smart contracts", - Long: `The deploy command suite provides deploy flows for different Smart Contracts.`, + Use: "bridge", + Short: "Manage Teleporter Bridges", + Long: `The bridge command suite provides tools to deploy and manage Teleporter Bridges.`, RunE: cobrautils.CommandSuiteUsage, } // contract deploy - cmd.AddCommand(newDeployBridgeCmd()) + cmd.AddCommand(newBridgeDeployCmd()) return cmd } diff --git a/cmd/contractcmd/deployBridge.go b/cmd/teleportercmd/bridgeDeploy.go similarity index 86% rename from cmd/contractcmd/deployBridge.go rename to cmd/teleportercmd/bridgeDeploy.go index 79c38801e..066d50ff0 100644 --- a/cmd/contractcmd/deployBridge.go +++ b/cmd/teleportercmd/bridgeDeploy.go @@ -1,6 +1,6 @@ // Copyright (C) 2022, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package contractcmd +package teleportercmd import ( _ "embed" @@ -15,7 +15,7 @@ import ( "github.com/spf13/cobra" ) -type DeployFlags struct { +type BridgeDeployFlags struct { Network networkoptions.NetworkFlags SubnetName string BlockchainID string @@ -30,39 +30,39 @@ type DeployFlags struct { } var ( - deployBridgeSupportedNetworkOptions = []networkoptions.NetworkOption{ + bridgeDeploySupportedNetworkOptions = []networkoptions.NetworkOption{ networkoptions.Local, networkoptions.Devnet, networkoptions.Fuji, } - deployFlags DeployFlags + bridgeDeployFlags BridgeDeployFlags ) -// avalanche contract deploy bridge -func newDeployBridgeCmd() *cobra.Command { +// avalanche teleporter bridge deploy +func newBridgeDeployCmd() *cobra.Command { cmd := &cobra.Command{ - Use: "bridge", - Short: "Deploys Tokeb Bridge into a given Network and Subnets", - Long: "Deploys Tokeb Bridge into a given Network and Subnets", - RunE: deployBridge, + Use: "deploy", + Short: "Deploys Token Bridge into a given Network and Subnets", + Long: "Deploys Token Bridge into a given Network and Subnets", + RunE: bridgeDeploy, Args: cobrautils.ExactArgs(0), } - networkoptions.AddNetworkFlagsToCmd(cmd, &deployFlags.Network, true, deployBridgeSupportedNetworkOptions) + networkoptions.AddNetworkFlagsToCmd(cmd, &deployFlags.Network, true, bridgeDeploySupportedNetworkOptions) return cmd } -func deployBridge(_ *cobra.Command, args []string) error { - return CallDeployBridge(args, deployFlags) +func bridgeDeploy(_ *cobra.Command, args []string) error { + return CallBridgeDeploy(args, deployFlags) } -func CallDeployBridge(_ []string, flags DeployFlags) error { +func CallBridgeDeploy(_ []string, flags DeployFlags) error { network, err := networkoptions.GetNetworkFromCmdLineFlags( app, "On what Network do you want to deploy the Teleporter bridge?", flags.Network, true, false, - deployBridgeSupportedNetworkOptions, + bridgeDeploySupportedNetworkOptions, "", ) if err != nil { diff --git a/cmd/contractcmd/popularTokensInfo.go b/cmd/teleportercmd/popularTokensInfo.go similarity index 98% rename from cmd/contractcmd/popularTokensInfo.go rename to cmd/teleportercmd/popularTokensInfo.go index b5e179c66..90fb0c0e2 100644 --- a/cmd/contractcmd/popularTokensInfo.go +++ b/cmd/teleportercmd/popularTokensInfo.go @@ -1,6 +1,6 @@ // Copyright (C) 2022, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package contractcmd +package teleportercmd import ( _ "embed" diff --git a/cmd/contractcmd/popularTokensInfo.json b/cmd/teleportercmd/popularTokensInfo.json similarity index 100% rename from cmd/contractcmd/popularTokensInfo.json rename to cmd/teleportercmd/popularTokensInfo.json diff --git a/cmd/teleportercmd/teleporter.go b/cmd/teleportercmd/teleporter.go index 2724f0767..b17f49fcd 100644 --- a/cmd/teleportercmd/teleporter.go +++ b/cmd/teleportercmd/teleporter.go @@ -26,5 +26,7 @@ with Teleporter-Enabled Subnets.`, cmd.AddCommand(newDeployCmd()) // teleporter relayer cmd.AddCommand(newRelayerCmd()) + // teleporter bridge + cmd.AddCommand(newBridgeCmd()) return cmd } From bfdc9ffc87ea099ceff1405c9353fdd552883062 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Fri, 24 May 2024 10:22:55 -0400 Subject: [PATCH 16/87] adddress suggestions --- cmd/teleportercmd/{ => bridgecmd}/bridge.go | 10 ++-- .../{bridgeDeploy.go => bridgecmd/deploy.go} | 49 +++++++++++++------ .../{ => bridgecmd}/popularTokensInfo.go | 2 +- .../{ => bridgecmd}/popularTokensInfo.json | 0 cmd/teleportercmd/teleporter.go | 3 +- 5 files changed, 44 insertions(+), 20 deletions(-) rename cmd/teleportercmd/{ => bridgecmd}/bridge.go (68%) rename cmd/teleportercmd/{bridgeDeploy.go => bridgecmd/deploy.go} (75%) rename cmd/teleportercmd/{ => bridgecmd}/popularTokensInfo.go (98%) rename cmd/teleportercmd/{ => bridgecmd}/popularTokensInfo.json (100%) diff --git a/cmd/teleportercmd/bridge.go b/cmd/teleportercmd/bridgecmd/bridge.go similarity index 68% rename from cmd/teleportercmd/bridge.go rename to cmd/teleportercmd/bridgecmd/bridge.go index b5b8f1511..40d3de0a5 100644 --- a/cmd/teleportercmd/bridge.go +++ b/cmd/teleportercmd/bridgecmd/bridge.go @@ -1,21 +1,25 @@ // Copyright (C) 2022, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package teleportercmd +package bridgecmd import ( + "github.com/ava-labs/avalanche-cli/pkg/application" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" "github.com/spf13/cobra" ) +var app *application.Avalanche + // avalanche teleporter bridge -func newBridgeCmd() *cobra.Command { +func NewCmd(injectedApp *application.Avalanche) *cobra.Command { cmd := &cobra.Command{ Use: "bridge", Short: "Manage Teleporter Bridges", Long: `The bridge command suite provides tools to deploy and manage Teleporter Bridges.`, RunE: cobrautils.CommandSuiteUsage, } + app = injectedApp // contract deploy - cmd.AddCommand(newBridgeDeployCmd()) + cmd.AddCommand(newDeployCmd()) return cmd } diff --git a/cmd/teleportercmd/bridgeDeploy.go b/cmd/teleportercmd/bridgecmd/deploy.go similarity index 75% rename from cmd/teleportercmd/bridgeDeploy.go rename to cmd/teleportercmd/bridgecmd/deploy.go index 066d50ff0..03c8727c8 100644 --- a/cmd/teleportercmd/bridgeDeploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -1,6 +1,6 @@ // Copyright (C) 2022, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package teleportercmd +package bridgecmd import ( _ "embed" @@ -15,7 +15,7 @@ import ( "github.com/spf13/cobra" ) -type BridgeDeployFlags struct { +type DeployFlags struct { Network networkoptions.NetworkFlags SubnetName string BlockchainID string @@ -30,39 +30,39 @@ type BridgeDeployFlags struct { } var ( - bridgeDeploySupportedNetworkOptions = []networkoptions.NetworkOption{ + deploySupportedNetworkOptions = []networkoptions.NetworkOption{ networkoptions.Local, networkoptions.Devnet, networkoptions.Fuji, } - bridgeDeployFlags BridgeDeployFlags + deployFlags DeployFlags ) // avalanche teleporter bridge deploy -func newBridgeDeployCmd() *cobra.Command { +func newDeployCmd() *cobra.Command { cmd := &cobra.Command{ Use: "deploy", Short: "Deploys Token Bridge into a given Network and Subnets", Long: "Deploys Token Bridge into a given Network and Subnets", - RunE: bridgeDeploy, + RunE: deploy, Args: cobrautils.ExactArgs(0), } - networkoptions.AddNetworkFlagsToCmd(cmd, &deployFlags.Network, true, bridgeDeploySupportedNetworkOptions) + networkoptions.AddNetworkFlagsToCmd(cmd, &deployFlags.Network, true, deploySupportedNetworkOptions) return cmd } -func bridgeDeploy(_ *cobra.Command, args []string) error { - return CallBridgeDeploy(args, deployFlags) +func deploy(_ *cobra.Command, args []string) error { + return CallDeploy(args, deployFlags) } -func CallBridgeDeploy(_ []string, flags DeployFlags) error { +func CallDeploy(_ []string, flags DeployFlags) error { network, err := networkoptions.GetNetworkFromCmdLineFlags( app, "On what Network do you want to deploy the Teleporter bridge?", flags.Network, true, false, - bridgeDeploySupportedNetworkOptions, + deploySupportedNetworkOptions, "", ) if err != nil { @@ -112,6 +112,7 @@ func CallBridgeDeploy(_ []string, flags DeployFlags) error { nativeOption := "The native token " + tokenSymbol erc20Option := "An ERC-20 token" explainOption := "Explain the difference" + goBackOption := "Go Back" popularTokensInfo, err := GetPopularTokensInfo(network, subnetOption) if err != nil { return err @@ -119,7 +120,7 @@ func CallBridgeDeploy(_ []string, flags DeployFlags) error { popularTokensDesc := utils.Map( popularTokensInfo, func(i PopularTokenInfo) string { - return i.Desc() + return i.Desc() + " (recommended)" }, ) options := []string{popularOption, existingOriginOption, nativeOption, erc20Option, explainOption} @@ -136,13 +137,18 @@ func CallBridgeDeploy(_ []string, flags DeployFlags) error { } switch option { case popularOption: - _, err = app.Prompt.CaptureList( + options := popularTokensDesc + options = append(options, goBackOption) + option, err := app.Prompt.CaptureList( "Choose Token", - popularTokensDesc, + options, ) if err != nil { return err } + if option == goBackOption { + continue + } case existingOriginOption: _, err = app.Prompt.CaptureAddress( "Enter the address of the Origin Bridge", @@ -151,12 +157,25 @@ func CallBridgeDeploy(_ []string, flags DeployFlags) error { return err } case erc20Option: - _, err = app.Prompt.CaptureAddress( + erc20TokenAddr, err := app.Prompt.CaptureAddress( "Enter the address of the ERC-20 Token", ) if err != nil { return err } + if p := utils.Find(popularTokensInfo, func(p PopularTokenInfo) bool { return p.TokenContractAddress == erc20TokenAddr.Hex() }); p != nil { + ux.Logger.PrintToUser("You have entered the address of %s, a popular token in the subnet.", p.TokenName) + deployANewHupOption := "Yes, I want to deploy a new Bridge Hub" + useTheExistingHubOption := "No, I want to use the existing official Bridge Hub" + options := []string{deployANewHupOption, useTheExistingHubOption} + _, err = app.Prompt.CaptureList( + "Are you sure you want to deploy a new Bridge Hub for it?", + options, + ) + if err != nil { + return err + } + } case explainOption: ux.Logger.PrintToUser("The difference is...") ux.Logger.PrintToUser("") diff --git a/cmd/teleportercmd/popularTokensInfo.go b/cmd/teleportercmd/bridgecmd/popularTokensInfo.go similarity index 98% rename from cmd/teleportercmd/popularTokensInfo.go rename to cmd/teleportercmd/bridgecmd/popularTokensInfo.go index 90fb0c0e2..a6a813f21 100644 --- a/cmd/teleportercmd/popularTokensInfo.go +++ b/cmd/teleportercmd/bridgecmd/popularTokensInfo.go @@ -1,6 +1,6 @@ // Copyright (C) 2022, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package teleportercmd +package bridgecmd import ( _ "embed" diff --git a/cmd/teleportercmd/popularTokensInfo.json b/cmd/teleportercmd/bridgecmd/popularTokensInfo.json similarity index 100% rename from cmd/teleportercmd/popularTokensInfo.json rename to cmd/teleportercmd/bridgecmd/popularTokensInfo.json diff --git a/cmd/teleportercmd/teleporter.go b/cmd/teleportercmd/teleporter.go index b17f49fcd..bb52a1756 100644 --- a/cmd/teleportercmd/teleporter.go +++ b/cmd/teleportercmd/teleporter.go @@ -3,6 +3,7 @@ package teleportercmd import ( + "github.com/ava-labs/avalanche-cli/cmd/teleportercmd/bridgecmd" "github.com/ava-labs/avalanche-cli/pkg/application" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" "github.com/spf13/cobra" @@ -27,6 +28,6 @@ with Teleporter-Enabled Subnets.`, // teleporter relayer cmd.AddCommand(newRelayerCmd()) // teleporter bridge - cmd.AddCommand(newBridgeCmd()) + cmd.AddCommand(bridgecmd.NewCmd(app)) return cmd } From 1e0651f64cff893d021b222d6215e4960e721ca0 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Fri, 24 May 2024 10:25:52 -0400 Subject: [PATCH 17/87] fix recommended --- cmd/teleportercmd/bridgecmd/deploy.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index 03c8727c8..5a6cafaa5 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -120,7 +120,11 @@ func CallDeploy(_ []string, flags DeployFlags) error { popularTokensDesc := utils.Map( popularTokensInfo, func(i PopularTokenInfo) string { - return i.Desc() + " (recommended)" + if i.TokenContractAddress == "" { + return i.Desc() + } else { + return i.Desc() + " (recommended)" + } }, ) options := []string{popularOption, existingOriginOption, nativeOption, erc20Option, explainOption} From 33dc80e7b5301f29878b7219ec3dcb45de1f2871 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Thu, 30 May 2024 16:42:35 -0400 Subject: [PATCH 18/87] update to latest esp --- cmd/teleportercmd/bridgecmd/deploy.go | 50 ++++++++++++------- .../bridgecmd/popularTokensInfo.go | 9 ++-- .../bridgecmd/popularTokensInfo.json | 2 +- 3 files changed, 38 insertions(+), 23 deletions(-) diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index 5a6cafaa5..0501e51c6 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -108,9 +108,8 @@ func CallDeploy(_ []string, flags DeployFlags) error { } prompt = "What kind of token do you want to bridge?" popularOption := "A popular token (e.g. AVAX, USDC, WAVAX, ...)" - existingOriginOption := "A token with an existing Origin Bridge" - nativeOption := "The native token " + tokenSymbol - erc20Option := "An ERC-20 token" + hubDeployedOption := "A token that already has a Hub deployed" + deployNewHubOption := "Deploy a new Hub for the token" explainOption := "Explain the difference" goBackOption := "Go Back" popularTokensInfo, err := GetPopularTokensInfo(network, subnetOption) @@ -120,16 +119,16 @@ func CallDeploy(_ []string, flags DeployFlags) error { popularTokensDesc := utils.Map( popularTokensInfo, func(i PopularTokenInfo) string { - if i.TokenContractAddress == "" { + if i.BridgeHubAddress == "" { return i.Desc() } else { return i.Desc() + " (recommended)" } }, ) - options := []string{popularOption, existingOriginOption, nativeOption, erc20Option, explainOption} + options := []string{popularOption, hubDeployedOption, deployNewHubOption, explainOption} if len(popularTokensDesc) == 0 { - options = []string{existingOriginOption, nativeOption, erc20Option, explainOption} + options = []string{hubDeployedOption, deployNewHubOption, explainOption} } for { option, err := app.Prompt.CaptureList( @@ -153,32 +152,45 @@ func CallDeploy(_ []string, flags DeployFlags) error { if option == goBackOption { continue } - case existingOriginOption: + case hubDeployedOption: _, err = app.Prompt.CaptureAddress( - "Enter the address of the Origin Bridge", + "Enter the address of the Hub", ) if err != nil { return err } - case erc20Option: - erc20TokenAddr, err := app.Prompt.CaptureAddress( - "Enter the address of the ERC-20 Token", + case deployNewHubOption: + nativeOption := "The native token " + tokenSymbol + erc20Option := "An ERC-20 token" + options := []string{nativeOption, erc20Option} + option, err := app.Prompt.CaptureList( + "What kind of token do you want to deploy the Hub for?", + options, ) if err != nil { return err } - if p := utils.Find(popularTokensInfo, func(p PopularTokenInfo) bool { return p.TokenContractAddress == erc20TokenAddr.Hex() }); p != nil { - ux.Logger.PrintToUser("You have entered the address of %s, a popular token in the subnet.", p.TokenName) - deployANewHupOption := "Yes, I want to deploy a new Bridge Hub" - useTheExistingHubOption := "No, I want to use the existing official Bridge Hub" - options := []string{deployANewHupOption, useTheExistingHubOption} - _, err = app.Prompt.CaptureList( - "Are you sure you want to deploy a new Bridge Hub for it?", - options, + switch option { + case erc20Option: + erc20TokenAddr, err := app.Prompt.CaptureAddress( + "Enter the address of the ERC-20 Token", ) if err != nil { return err } + if p := utils.Find(popularTokensInfo, func(p PopularTokenInfo) bool { return p.TokenContractAddress == erc20TokenAddr.Hex() }); p != nil { + ux.Logger.PrintToUser("You have entered the address of %s, a popular token in the subnet.", p.TokenName) + deployANewHupOption := "Yes, I want to deploy a new Bridge Hub" + useTheExistingHubOption := "No, I want to use the existing official Bridge Hub" + options := []string{deployANewHupOption, useTheExistingHubOption} + _, err = app.Prompt.CaptureList( + "Are you sure you want to deploy a new Bridge Hub for it?", + options, + ) + if err != nil { + return err + } + } } case explainOption: ux.Logger.PrintToUser("The difference is...") diff --git a/cmd/teleportercmd/bridgecmd/popularTokensInfo.go b/cmd/teleportercmd/bridgecmd/popularTokensInfo.go index a6a813f21..0e12d76ce 100644 --- a/cmd/teleportercmd/bridgecmd/popularTokensInfo.go +++ b/cmd/teleportercmd/bridgecmd/popularTokensInfo.go @@ -22,10 +22,13 @@ var popularTokensInfoByteSlice []byte var popularTokensInfo map[string]map[string][]PopularTokenInfo func (i PopularTokenInfo) Desc() string { - if i.TokenContractAddress == "" { + switch { + case i.TokenContractAddress != "" && i.BridgeHubAddress != "": + return fmt.Sprintf("%s | Token address %s | Hub address %s", i.TokenName, i.TokenContractAddress, i.BridgeHubAddress) + case i.BridgeHubAddress != "": + return fmt.Sprintf("%s | Hub address %s", i.TokenName, i.BridgeHubAddress) + default: return i.TokenName - } else { - return fmt.Sprintf("%s | Token address %s | Hub bridge address %s", i.TokenName, i.TokenContractAddress, i.BridgeHubAddress) } } diff --git a/cmd/teleportercmd/bridgecmd/popularTokensInfo.json b/cmd/teleportercmd/bridgecmd/popularTokensInfo.json index 44241e99d..dd6e7f818 100644 --- a/cmd/teleportercmd/bridgecmd/popularTokensInfo.json +++ b/cmd/teleportercmd/bridgecmd/popularTokensInfo.json @@ -4,7 +4,7 @@ { "TokenName": "AVAX", "TokenContractAddress": "", - "BridgeHubAddress": "" + "BridgeHubAddress": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c" }, { "TokenName": "USDC", From 109a0c6632f4dd1dfc57a5cd11f137241fa7afa4 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Sat, 8 Jun 2024 14:26:47 -0300 Subject: [PATCH 19/87] start obtaining erc20 token balances --- cmd/keycmd/list.go | 24 +++- go.mod | 1 + go.sum | 327 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 350 insertions(+), 2 deletions(-) diff --git a/cmd/keycmd/list.go b/cmd/keycmd/list.go index 55c103d00..dcc977fcb 100644 --- a/cmd/keycmd/list.go +++ b/cmd/keycmd/list.go @@ -21,6 +21,8 @@ import ( "github.com/ava-labs/avalanchego/vms/platformvm" "github.com/ava-labs/coreth/ethclient" "github.com/ethereum/go-ethereum/common" + goethereumethclient "github.com/ethereum/go-ethereum/ethclient" + "github.com/liyue201/erc20-go/erc20" "github.com/olekukonko/tablewriter" "github.com/spf13/cobra" ) @@ -444,7 +446,7 @@ func getEvmBasedChainAddrInfo( kind string, name string, ) (addressInfo, error) { - cChainBalance, err := getCChainBalanceStr(cClients[network], cChainAddr) + cChainBalance, err := getCChainBalanceStr(network, cClients[network], cChainAddr) if err != nil { // just ignore local network errors if network.Kind != models.Local { @@ -480,7 +482,25 @@ func printAddrInfos(addrInfos []addressInfo) { table.Render() } -func getCChainBalanceStr(cClient ethclient.Client, addrStr string) (string, error) { +func getCChainBalanceStr(network models.Network, cClient ethclient.Client, addrStr string) (string, error) { + goEthereumClient, err := goethereumethclient.Dial(network.BlockchainEndpoint("C")) + if err != nil { + return "", err + } + token, err := erc20.NewGGToken(common.HexToAddress("0x5DB9A7629912EBF95876228C24A848de0bfB43A9"), goEthereumClient) + if err != nil { + return "", err + } + name, err := token.Name(nil) + if err != nil { + return "", err + } + fmt.Println(name) + bal, err := token.BalanceOf(nil, common.HexToAddress(addrStr)) + fmt.Println(bal) + if err != nil { + return "", err + } addr := common.HexToAddress(addrStr) ctx, cancel := utils.GetAPIContext() balance, err := cClient.BalanceAt(ctx, addr, nil) diff --git a/go.mod b/go.mod index c037c2be6..4e91062e9 100644 --- a/go.mod +++ b/go.mod @@ -151,6 +151,7 @@ require ( github.com/kr/fs v0.1.0 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect + github.com/liyue201/erc20-go v0.0.0-20210521034206-b2824246def0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect diff --git a/go.sum b/go.sum index dd8fe0e0c..bf6d7b5a2 100644 --- a/go.sum +++ b/go.sum @@ -1,18 +1,52 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= cloud.google.com/go/auth v0.4.1 h1:Z7YNIhlWRtrnKlZke7z3GMqzvuYzdc2z98F9D1NV5Hg= cloud.google.com/go/auth v0.4.1/go.mod h1:QVBuVEKpCn4Zp58hzRGvL0tjRGU0YqdRTdCHM1IHnro= cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4= cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigtable v1.2.0/go.mod h1:JcVAOl45lrTmQfLj7T6TxyMzIN/3FGGcFm+2xVAli2o= cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= +github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= +github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= +github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= +github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= @@ -25,17 +59,25 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78= github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/VictoriaMetrics/fastcache v1.5.7/go.mod h1:ptDBkNMQI4RtmVo8VS/XwRY6RoTu1dAWCbrk+6WsEM8= github.com/VictoriaMetrics/fastcache v1.10.0 h1:5hDJnLsKLpnUEToub7ETuRu8RCkb40woBZAUiKonXzY= github.com/VictoriaMetrics/fastcache v1.10.0/go.mod h1:tjiYeEfYXCqacuvYw/7UoDIeJaNxq6132xHICNP77w8= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= +github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= @@ -55,12 +97,16 @@ github.com/ava-labs/subnet-evm v0.6.4 h1:iOz21dlwU/gTN7ZbD9lVeG9rIUt7MVWu1gnZlek github.com/ava-labs/subnet-evm v0.6.4/go.mod h1:kv8NzG+N6hB4brfOE4a7laQNebNgru1sRcMS1OzXy+M= github.com/ava-labs/teleporter v1.0.0 h1:io209qZh3SDpwLre0oStMzOFRcPvOrmMQuLq5OFvzJo= github.com/ava-labs/teleporter v1.0.0/go.mod h1:4Wyz/5sZDHMaaLegh2ULyrAOWnyaBk6upTmbwSrVSMs= +github.com/aws/aws-sdk-go-v2 v1.2.0/go.mod h1:zEQs02YRBw1DjK0PoJv3ygDYOFTre1ejlJWl8FwAuQo= github.com/aws/aws-sdk-go-v2 v1.27.0 h1:7bZWKoXhzI+mMR/HjdMx8ZCC5+6fY0lS5tr0bbgiLlo= github.com/aws/aws-sdk-go-v2 v1.27.0/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM= +github.com/aws/aws-sdk-go-v2/config v1.1.1/go.mod h1:0XsVy9lBI/BCXm+2Tuvt39YmdHwS5unDQmxZOYe8F5Y= github.com/aws/aws-sdk-go-v2/config v1.27.15 h1:uNnGLZ+DutuNEkuPh6fwqK7LpEiPmzb7MIMA1mNWEUc= github.com/aws/aws-sdk-go-v2/config v1.27.15/go.mod h1:7j7Kxx9/7kTmL7z4LlhwQe63MYEE5vkVV6nWg4ZAI8M= +github.com/aws/aws-sdk-go-v2/credentials v1.1.1/go.mod h1:mM2iIjwl7LULWtS6JCACyInboHirisUUdkBPoTHMOUo= github.com/aws/aws-sdk-go-v2/credentials v1.17.15 h1:YDexlvDRCA8ems2T5IP1xkMtOZ1uLJOCJdTr0igs5zo= github.com/aws/aws-sdk-go-v2/credentials v1.17.15/go.mod h1:vxHggqW6hFNaeNC0WyXS3VdyjcV0a4KMUY4dKJ96buU= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2/go.mod h1:3hGg3PpiEjHnrkrlasTfxFqUsZ2GCk/fMUn4CbKgSkM= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.3 h1:dQLK4TjtnlRGb0czOht2CevZ5l6RSyRWAnKeGd7VAFE= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.3/go.mod h1:TL79f2P6+8Q7dTsILpiVST+AL9lkF6PPGI167Ny0Cjw= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.7 h1:lf/8VTF2cM+N4SLzaYJERKEWAXq8MOMpZfU6wEPWsPk= @@ -73,23 +119,32 @@ github.com/aws/aws-sdk-go-v2/service/ec2 v1.161.3 h1:l0mvKOGm25yo/Fy+Y/08Cm4aTA4 github.com/aws/aws-sdk-go-v2/service/ec2 v1.161.3/go.mod h1:iJ2sQeUTkjNp3nL7kE/Bav0xXYhtiRCRP5ZXk4jFhCQ= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1xUsUr3I8cHps0G+XM3WWU16lP6yG8qu1GAZAs= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2/go.mod h1:5CsjAbs3NlGQyZNFACh+zztPDI7fU6eW9QsxjfnuBKg= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2/go.mod h1:45MfaXZ0cNbeuT0KQ1XJylq8A6+OpVV2E5kvY/Kq+u8= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.9 h1:Wx0rlZoEJR7JwlSZcHnEa7CNjrSIyVxMFWGAaXy4fJY= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.9/go.mod h1:aVMHdE0aHO3v+f/iw01fmXV/5DbfQ3Bi9nN7nd9bE9Y= github.com/aws/aws-sdk-go-v2/service/kms v1.31.0 h1:yl7wcqbisxPzknJVfWTLnK83McUvXba+pz2+tPbIUmQ= github.com/aws/aws-sdk-go-v2/service/kms v1.31.0/go.mod h1:2snWQJQUKsbN66vAawJuOGX7dr37pfOq9hb0tZDGIqQ= +github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1/go.mod h1:rLiOUrPLW/Er5kRcQ7NkwbjlijluLsrIbu/iyl35RO4= +github.com/aws/aws-sdk-go-v2/service/sso v1.1.1/go.mod h1:SuZJxklHxLAXgLTc1iFXbEWkXs7QRTQpCLGaKIprQW0= github.com/aws/aws-sdk-go-v2/service/sso v1.20.8 h1:Kv1hwNG6jHC/sxMTe5saMjH6t6ZLkgfvVxyEjfWL1ks= github.com/aws/aws-sdk-go-v2/service/sso v1.20.8/go.mod h1:c1qtZUWtygI6ZdvKppzCSXsDOq5I4luJPZ0Ud3juFCA= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.2 h1:nWBZ1xHCF+A7vv9sDzJOq4NWIdzFYm0kH7Pr4OjHYsQ= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.2/go.mod h1:9lmoVDVLz/yUZwLaQ676TK02fhCu4+PgRSmMaKR1ozk= +github.com/aws/aws-sdk-go-v2/service/sts v1.1.1/go.mod h1:Wi0EBZwiz/K44YliU0EKxqTCJGUfYTWXrrBwkq736bM= github.com/aws/aws-sdk-go-v2/service/sts v1.28.9 h1:Qp6Boy0cGDloOE3zI6XhNLNZgjNS8YmiFQFHe71SaW0= github.com/aws/aws-sdk-go-v2/service/sts v1.28.9/go.mod h1:0Aqn1MnEuitqfsCNyKsdKLhDUOr4txD/g19EfiUqgws= +github.com/aws/smithy-go v1.1.0/go.mod h1:EzMw8dbp/YJL4A5/sbhGddag+NPT7q084agLbB9LgIw= github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q= github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bits-and-blooms/bitset v1.7.0 h1:YjAGVd3XmtK9ktAbX8Zg2g2PwLIMjGREZJHlV4j7NEo= github.com/bits-and-blooms/bitset v1.7.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= +github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= +github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btcd v0.23.0 h1:V2/ZgjfDFIygAX3ZapeigkVBoVUtOJKSwrhZdlpSvaA= @@ -115,6 +170,7 @@ github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= github.com/cavaliergopher/grab/v3 v3.0.1 h1:4z7TkBfmPjmLAAmkkAZNX/6QJ1nNFdv3SdIHXju0Fr4= github.com/cavaliergopher/grab/v3 v3.0.1/go.mod h1:1U/KNnD+Ft6JJiYoYBAimKH2XrYptb8Kl3DFGmsjpq4= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= @@ -122,6 +178,8 @@ github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyY github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -143,6 +201,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= +github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304= github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= @@ -160,8 +219,10 @@ github.com/cockroachdb/pebble v0.0.0-20230906160148-46873a6a7a06/go.mod h1:bynZ3 github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= +github.com/consensys/bavard v0.1.8-0.20210406032232-f3452dc9b572/go.mod h1:Bpd0/3mZuaj6Sj+PqrmIquiOKy397AKGThQPaGzNXAQ= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1:815PAHg3wvysy0SyIqanF8gZ0Y1wjk/hrDHD/iT88+Q= github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -178,11 +239,13 @@ github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= @@ -192,18 +255,26 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v26.1.2+incompatible h1:UVX5ZOrrfTGZZYEP+ZDq3Xn9PdHNXaSYMFPDumMqG2k= github.com/docker/docker v26.1.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 h1:qwcF+vdFrvPSEUDSX5RVoRccG8a5DhOdWdQ4zN62zzo= github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= @@ -217,9 +288,11 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/ethereum/c-kzg-4844 v0.3.1 h1:sR65+68+WdnMKxseNWxSJuAv2tsUrihTpVBTfM/U5Zg= github.com/ethereum/c-kzg-4844 v0.3.1/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= +github.com/ethereum/go-ethereum v1.10.3/go.mod h1:99onQmSd1GRGOziyGldI41YQb7EESX3Q4H41IfJgIQQ= github.com/ethereum/go-ethereum v1.13.2 h1:g9mCpfPWqCA1OL4e6C98PeVttb0HadfBRuKTGvMnOvw= github.com/ethereum/go-ethereum v1.13.2/go.mod h1:gkQ5Ygi64ZBh9M/4iXY1R8WqoNCx1Ey0CkYn2BD4/fw= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= @@ -227,6 +300,7 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -235,6 +309,7 @@ github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmV github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= @@ -245,6 +320,8 @@ github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/ github.com/gliderlabs/ssh v0.3.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE= github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8= +github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= +github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= github.com/go-cmd/cmd v1.4.1 h1:JUcEIE84v8DSy02XTZpUDeGKExk2oW3DA10hTjbQwmc= github.com/go-cmd/cmd v1.4.1/go.mod h1:tbBenttXtZU4c5djS1o7PWL5pd2xAr5sIqH1kGdNiRc= @@ -259,16 +336,25 @@ github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMj github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys= github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= +github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= @@ -279,20 +365,29 @@ github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -310,37 +405,54 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3-0.20201103224600-674baa8c7fc3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg= github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.12.4 h1:9gWcmF85Wvq4ryPFvGFaOgPIs1AQX0d0bcbGw4Z96qg= github.com/googleapis/gax-go/v2 v2.12.4/go.mod h1:KYEYLorsnIGDi/rPC8b5TdlB9kbKoFubselGIoBMCwI= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -351,6 +463,7 @@ github.com/gorilla/rpc v1.2.0/go.mod h1:V4h9r+4sF5HnzqbwIez0fKSpANP0zlYd3qR7p36j github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 h1:RtRsiaGvWxcwd8y3BiRZxsylPT8hLWZ5SPcfI+3IDNk= @@ -358,6 +471,8 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0/go.mod h1:TzP6duP4Py2pHLVPPQp4 github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= @@ -366,18 +481,30 @@ github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZ github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= +github.com/holiman/uint256 v1.1.1/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= github.com/holiman/uint256 v1.2.3 h1:K8UWO1HUJpRMXBxbmaY1Y8IAMZC/RsKB+ArEnnK4l5o= github.com/holiman/uint256 v1.2.3/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huin/goupnp v1.0.1-0.20210310174557-0ca763054c88/go.mod h1:nNs7wvRfN1eKaMknBydLNQU6146XQim8t4h+q90biWo= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= +github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/influxdata/flux v0.65.1/go.mod h1:J754/zds0vvpfwuq7Gc2wRdVwEodfpCFM7mYlOw2LqY= +github.com/influxdata/influxdb v1.8.3/go.mod h1:JugdFhsvvI8gadxOI6noqNeeBHvWNTbfYGtiAn+2jhI= +github.com/influxdata/influxql v1.1.1-0.20200828144457-65d3ef77d385/go.mod h1:gHp9y86a/pxhjJ+zMjNXiQAA197Xk9wLxaz+fGG+kWk= +github.com/influxdata/line-protocol v0.0.0-20180522152040-32c6aa80de5e/go.mod h1:4kt73NQhadE3daL3WhR5EJ/J2ocX0PZzwxQ0gXJ7oFE= +github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19ybifQhZoQNF5D8= +github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE= +github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= +github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= @@ -385,10 +512,12 @@ github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0Gqw github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= github.com/jackpal/gateway v1.0.6 h1:/MJORKvJEwNVldtGVJC2p2cwCnsSoLn3hl3zxmZT7tk= github.com/jackpal/gateway v1.0.6/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= +github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= @@ -398,8 +527,15 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfC github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= +github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA= github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= @@ -409,16 +545,23 @@ github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7 github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg= +github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= @@ -434,16 +577,25 @@ github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awS github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/liyue201/erc20-go v0.0.0-20210521034206-b2824246def0 h1:fqN427q9SuX3CJcjjE8Tvvf6qUhzYHwKGfmeIcY1Iks= +github.com/liyue201/erc20-go v0.0.0-20210521034206-b2824246def0/go.mod h1:ElgqWkb5LUBLeFYpAA4gsBBRMlkktFeW4FkfYXsak3k= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= @@ -452,9 +604,13 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= github.com/melbahja/goph v1.4.0 h1:z0PgDbBFe66lRYl3v5dGb9aFgPy0kotuQ37QOwSQFqs= github.com/melbahja/goph v1.4.0/go.mod h1:uG+VfK2Dlhk+O32zFrRlc3kYKTlV6+BtvPWd/kK7U68= @@ -476,6 +632,10 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= +github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= @@ -485,6 +645,7 @@ github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJ github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/okteto/remote v0.0.0-20210428052247-99de42c04148 h1:urr6T7QLPi0DFHFCJvX1JFLu8QgGRD8MFaQBv1UC7sM= github.com/okteto/remote v0.0.0-20210428052247-99de42c04148/go.mod h1:aRwo2ZLFsZWAFnIQGdk7ReXeMNk0+n0nDANPZK3Kmm8= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= @@ -508,15 +669,23 @@ github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAl github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.0.3-0.20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/otiai10/copy v1.11.0 h1:OKBD80J/mLBrwnzXqGtFCzprFSGioo30JcmR4APsNwc= github.com/otiai10/copy v1.11.0/go.mod h1:rSaLseMUsZFFbsFGc7wCJnnkTAvdc5L6VWxPE4308Ww= github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks= github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= +github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE= github.com/pborman/ansi v1.0.0 h1:OqjHMhvlSuCCV5JT07yqPuJPQzQl+WXsiZ14gZsqOrQ= github.com/pborman/ansi v1.0.0/go.mod h1:SgWzwMAx1X/Ez7i90VqF8LRiQtx52pWDiQP+x3iGnzw= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= +github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= +github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pires/go-proxyproto v0.6.2 h1:KAZ7UteSOt6urjme6ZldyFm4wDe/z0ZUP0Yv0Dos0d8= @@ -524,6 +693,7 @@ github.com/pires/go-proxyproto v0.6.2/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9G github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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= @@ -531,20 +701,34 @@ github.com/pkg/sftp v1.12.0/go.mod h1:fUqqXB5vEgVCZ131L+9say31RAri6aF6KDViawhxKK github.com/pkg/sftp v1.13.5/go.mod h1:wHDZ0IZX6JcBYRK1TH9bcVq8G7TLpVHYIGJRFnmPfxg= github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo= github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk= +github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ= 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/posthog/posthog-go v0.0.0-20221221115252-24dfed35d71a h1:Ey0XWvrg6u6hyIn1Kd/jCCmL+bMv9El81tvuGBbxZGg= github.com/posthog/posthog-go v0.0.0-20221221115252-24dfed35d71a/go.mod h1:oa2sAs9tGai3VldabTV0eWejt/O4/OOD7azP8GaikqU= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= +github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= @@ -564,12 +748,16 @@ github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWR github.com/sanity-io/litter v1.5.1 h1:dwnrSypP6q56o3lFxTU+t2fwQ9A+U5qrXVO4Qg9KwVU= github.com/sanity-io/litter v1.5.1/go.mod h1:5Z71SvaYy5kcGtyglXOC9rrUi3c1E8CamFWjQsazTh0= github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= +github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= @@ -579,12 +767,14 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1 github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= @@ -595,15 +785,18 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -621,17 +814,22 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a h1:1ur3QoCqvE5fl+nylMaIr9PVV1w343YRDtsy+Rwu7XI= github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/thepudds/fzgen v0.4.2 h1:HlEHl5hk2/cqEomf2uK5SA/FeJc12s/vIHmOG+FbACw= github.com/thepudds/fzgen v0.4.2/go.mod h1:kHCWdsv5tdnt32NIHYDdgq083m6bMtaY0M+ipiO9xWE= +github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= +github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= +github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= @@ -639,6 +837,7 @@ github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVM github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= @@ -647,11 +846,13 @@ github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBn github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= +github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= @@ -671,6 +872,9 @@ github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= @@ -691,19 +895,26 @@ go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -718,13 +929,34 @@ golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58 golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20231127185646-65229373498e h1:Gvh4YaCaXNs6dKTlfgismwWZKyjVZXwOPfIyUaqU3No= golang.org/x/exp v0.0.0-20231127185646-65229373498e/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= +golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -737,13 +969,20 @@ golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -751,6 +990,7 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= @@ -766,13 +1006,19 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo= golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -780,13 +1026,22 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -794,6 +1049,8 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -802,9 +1059,12 @@ golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -838,8 +1098,10 @@ golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= @@ -849,22 +1111,44 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= @@ -876,15 +1160,43 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= gonum.org/v1/gonum v0.11.0 h1:f1IJhK4Km5tBJmaiJXtk/PkL4cdVX6J+tGiM187uT5E= gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= +gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.181.0 h1:rPdjwnWgiPPOJx3IcSAQ2III5aX5tCer6wMpa/xmZi4= google.golang.org/api v0.181.0/go.mod h1:MnQ+M0CFsfUwA5beZ+g/vCBCPXvtmZwRz2qzZk8ih1k= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200108215221-bd8f9a0ef82f/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= google.golang.org/genproto/googleapis/api v0.0.0-20240506185236-b8a5c65736ae h1:AH34z6WAGVNkllnKs5raNq3yRq93VnjBG6rpfub/jYk= @@ -893,8 +1205,11 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 h1: google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= @@ -913,6 +1228,7 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -928,12 +1244,16 @@ gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= +gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -944,11 +1264,18 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= From 1563c68cee912bd38be621d51c60b7dcef3b3107 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Sat, 8 Jun 2024 19:59:11 -0300 Subject: [PATCH 20/87] add key list for erc20 tokens --- cmd/keycmd/create.go | 4 +- cmd/keycmd/list.go | 173 ++++++++++++++++++++++++++++--------------- 2 files changed, 116 insertions(+), 61 deletions(-) diff --git a/cmd/keycmd/create.go b/cmd/keycmd/create.go index 0c2e869a8..15963ddba 100644 --- a/cmd/keycmd/create.go +++ b/cmd/keycmd/create.go @@ -57,11 +57,11 @@ func createKey(_ *cobra.Command, args []string) error { pchain := true cchain := true xchain := true - pClients, xClients, cClients, evmClients, err := getClients(networks, pchain, cchain, xchain, "") + clients, err := getClients(networks, pchain, cchain, xchain, "") if err != nil { return err } - addrInfos, err := getStoredKeyInfo(pClients, xClients, cClients, evmClients, networks, keyName) + addrInfos, err := getStoredKeyInfo(clients, networks, keyName) if err != nil { return err } diff --git a/cmd/keycmd/list.go b/cmd/keycmd/list.go index dcc977fcb..c67605f2a 100644 --- a/cmd/keycmd/list.go +++ b/cmd/keycmd/list.go @@ -50,6 +50,8 @@ var ( ledgerIndices []uint subnetName string keys []string + tokenAddresses []string + subnetToken string ) // avalanche subnet list @@ -120,14 +122,26 @@ keys or for the ledger addresses associated to certain indices.`, "pxc", "short way to specify which chains to show information about (p=show p-chain, x=show x-chain, c=show c-chain). defaults to pxc", ) + cmd.Flags().StringSliceVar( + &tokenAddresses, + "tokens", + []string{}, + "provide balance information for the given token contract addresses (Evm only)", + ) return cmd } +type Clients struct { + x map[models.Network]avm.Client + p map[models.Network]platformvm.Client + c map[models.Network]ethclient.Client + evm map[models.Network]ethclient.Client + cGeth map[models.Network]*goethereumethclient.Client + evmGeth map[models.Network]*goethereumethclient.Client +} + func getClients(networks []models.Network, pchain bool, cchain bool, xchain bool, subnetName string) ( - map[models.Network]platformvm.Client, - map[models.Network]avm.Client, - map[models.Network]ethclient.Client, - map[models.Network]ethclient.Client, + *Clients, error, ) { var err error @@ -135,6 +149,8 @@ func getClients(networks []models.Network, pchain bool, cchain bool, xchain bool pClients := map[models.Network]platformvm.Client{} cClients := map[models.Network]ethclient.Client{} evmClients := map[models.Network]ethclient.Client{} + cGethClients := map[models.Network]*goethereumethclient.Client{} + evmGethClients := map[models.Network]*goethereumethclient.Client{} for _, network := range networks { if pchain { pClients[network] = platformvm.NewClient(network.Endpoint) @@ -145,40 +161,61 @@ func getClients(networks []models.Network, pchain bool, cchain bool, xchain bool if cchain { cClients[network], err = ethclient.Dial(network.CChainEndpoint()) if err != nil { - return nil, nil, nil, nil, err + return nil, err + } + if len(tokenAddresses) != 0 { + cGethClients[network], err = goethereumethclient.Dial(network.CChainEndpoint()) + if err != nil { + return nil, err + } } } if subnetName != "" { _, err = subnetcmd.ValidateSubnetNameAndGetChains([]string{subnetName}) if err != nil { - return nil, nil, nil, nil, err + return nil, err } b, _, err := subnetcmd.HasSubnetEVMGenesis(subnetName) if err != nil { - return nil, nil, nil, nil, err + return nil, err } if b { sc, err := app.LoadSidecar(subnetName) if err != nil { - return nil, nil, nil, nil, err + return nil, err } + subnetToken = sc.TokenSymbol chainID := sc.Networks[network.Name()].BlockchainID if chainID != ids.Empty { evmClients[network], err = ethclient.Dial(network.BlockchainEndpoint(chainID.String())) if err != nil { - return nil, nil, nil, nil, err + return nil, err + } + if len(tokenAddresses) != 0 { + evmGethClients[network], err = goethereumethclient.Dial(network.BlockchainEndpoint(chainID.String())) + if err != nil { + return nil, err + } } } } } } - return pClients, xClients, cClients, evmClients, nil + return &Clients{ + p: pClients, + x: xClients, + c: cClients, + evm: evmClients, + cGeth: cGethClients, + evmGeth: evmGethClients, + }, nil } type addressInfo struct { kind string name string chain string + token string address string balance string network string @@ -233,7 +270,7 @@ func listKeys(*cobra.Command, []string) error { cchain = false xchain = false } - pClients, xClients, cClients, evmClients, err := getClients(networks, pchain, cchain, xchain, subnetName) + clients, err := getClients(networks, pchain, cchain, xchain, subnetName) if err != nil { return err } @@ -242,12 +279,12 @@ func listKeys(*cobra.Command, []string) error { for _, index := range ledgerIndices { ledgerIndicesU32 = append(ledgerIndicesU32, uint32(index)) } - addrInfos, err = getLedgerIndicesInfo(pClients, ledgerIndicesU32, networks) + addrInfos, err = getLedgerIndicesInfo(clients.p, ledgerIndicesU32, networks) if err != nil { return err } } else { - addrInfos, err = getStoredKeysInfo(pClients, xClients, cClients, evmClients, networks) + addrInfos, err = getStoredKeysInfo(clients, networks) if err != nil { return err } @@ -257,10 +294,7 @@ func listKeys(*cobra.Command, []string) error { } func getStoredKeysInfo( - pClients map[models.Network]platformvm.Client, - xClients map[models.Network]avm.Client, - cClients map[models.Network]ethclient.Client, - evmClients map[models.Network]ethclient.Client, + clients *Clients, networks []models.Network, ) ([]addressInfo, error) { keyNames, err := utils.GetKeyNames(app.GetKeyDir(), true) @@ -272,7 +306,7 @@ func getStoredKeysInfo( } addrInfos := []addressInfo{} for _, keyName := range keyNames { - keyAddrInfos, err := getStoredKeyInfo(pClients, xClients, cClients, evmClients, networks, keyName) + keyAddrInfos, err := getStoredKeyInfo(clients, networks, keyName) if err != nil { return nil, err } @@ -282,10 +316,7 @@ func getStoredKeysInfo( } func getStoredKeyInfo( - pClients map[models.Network]platformvm.Client, - xClients map[models.Network]avm.Client, - cClients map[models.Network]ethclient.Client, - evmClients map[models.Network]ethclient.Client, + clients *Clients, networks []models.Network, keyName string, ) ([]addressInfo, error) { @@ -295,36 +326,36 @@ func getStoredKeyInfo( if err != nil { return nil, err } - if _, ok := evmClients[network]; ok { + if _, ok := clients.evm[network]; ok { evmAddr := sk.C() - addrInfo, err := getEvmBasedChainAddrInfo(subnetName, evmClients, network, evmAddr, "stored", keyName) + addrInfo, err := getEvmBasedChainAddrInfo(subnetName, subnetToken, clients.evm, clients.evmGeth, network, evmAddr, "stored", keyName) if err != nil { return nil, err } - addrInfos = append(addrInfos, addrInfo) + addrInfos = append(addrInfos, addrInfo...) } - if _, ok := cClients[network]; ok { + if _, ok := clients.c[network]; ok { cChainAddr := sk.C() - addrInfo, err := getEvmBasedChainAddrInfo("C-Chain", cClients, network, cChainAddr, "stored", keyName) + addrInfo, err := getEvmBasedChainAddrInfo("C-Chain", "AVAX", clients.c, clients.cGeth, network, cChainAddr, "stored", keyName) if err != nil { return nil, err } - addrInfos = append(addrInfos, addrInfo) + addrInfos = append(addrInfos, addrInfo...) } - if _, ok := pClients[network]; ok { + if _, ok := clients.p[network]; ok { pChainAddrs := sk.P() for _, pChainAddr := range pChainAddrs { - addrInfo, err := getPChainAddrInfo(pClients, network, pChainAddr, "stored", keyName) + addrInfo, err := getPChainAddrInfo(clients.p, network, pChainAddr, "stored", keyName) if err != nil { return nil, err } addrInfos = append(addrInfos, addrInfo) } } - if _, ok := xClients[network]; ok { + if _, ok := clients.x[network]; ok { xChainAddrs := sk.X() for _, xChainAddr := range xChainAddrs { - addrInfo, err := getXChainAddrInfo(xClients, network, xChainAddr, "stored", keyName) + addrInfo, err := getXChainAddrInfo(clients.x, network, xChainAddr, "stored", keyName) if err != nil { return nil, err } @@ -407,7 +438,8 @@ func getPChainAddrInfo( return addressInfo{ kind: kind, name: name, - chain: "P-Chain (Bech32 format)", + chain: "P-Chain", + token: "AVAX", address: pChainAddr, balance: balance, network: network.Name(), @@ -431,7 +463,8 @@ func getXChainAddrInfo( return addressInfo{ kind: kind, name: name, - chain: "X-Chain (Bech32 format)", + chain: "X-Chain", + token: "AVAX", address: xChainAddr, balance: balance, network: network.Name(), @@ -440,41 +473,77 @@ func getXChainAddrInfo( func getEvmBasedChainAddrInfo( chainName string, + chainToken string, cClients map[models.Network]ethclient.Client, + cGethClients map[models.Network]*goethereumethclient.Client, network models.Network, cChainAddr string, kind string, name string, -) (addressInfo, error) { +) ([]addressInfo, error) { cChainBalance, err := getCChainBalanceStr(network, cClients[network], cChainAddr) if err != nil { // just ignore local network errors if network.Kind != models.Local { - return addressInfo{}, err + return nil, err } } - return addressInfo{ + info := addressInfo{ kind: kind, name: name, - chain: fmt.Sprintf("%s (Ethereum hex format)", chainName), + chain: fmt.Sprintf("%s", chainName), + token: chainToken, address: cChainAddr, balance: cChainBalance, network: network.Name(), - }, nil + } + addressInfos := []addressInfo{info} + if cGethClients != nil && cGethClients[network] != nil { + for _, tokenAddress := range tokenAddresses { + token, err := erc20.NewGGToken(common.HexToAddress(tokenAddress), cGethClients[network]) + if err == nil { + // just ignore contract address access errors as those may depend on network + tokenName, err := token.Name(nil) + if err != nil { + return addressInfos, err + } + balance, err := token.BalanceOf(nil, common.HexToAddress(cChainAddr)) + if err != nil { + return addressInfos, err + } + formattedBalance, err := formatCChainBalance(balance) + if err != nil { + return addressInfos, err + } + info := addressInfo{ + kind: kind, + name: name, + chain: fmt.Sprintf("%s", chainName), + token: tokenName, + address: cChainAddr, + balance: formattedBalance, + network: network.Name(), + } + addressInfos = append(addressInfos, info) + } + } + } + return addressInfos, nil } func printAddrInfos(addrInfos []addressInfo) { - header := []string{"Kind", "Name", "Chain", "Address", "Balance", "Network"} + header := []string{"Kind", "Name", "Chain", "Address", "Token", "Balance", "Network"} table := tablewriter.NewWriter(os.Stdout) table.SetHeader(header) table.SetRowLine(true) - table.SetAutoMergeCellsByColumnIndex([]int{0, 1, 2}) + table.SetAutoMergeCellsByColumnIndex([]int{0, 1, 2, 3}) for _, addrInfo := range addrInfos { table.Append([]string{ addrInfo.kind, addrInfo.name, addrInfo.chain, addrInfo.address, + addrInfo.token, addrInfo.balance, addrInfo.network, }) @@ -483,24 +552,6 @@ func printAddrInfos(addrInfos []addressInfo) { } func getCChainBalanceStr(network models.Network, cClient ethclient.Client, addrStr string) (string, error) { - goEthereumClient, err := goethereumethclient.Dial(network.BlockchainEndpoint("C")) - if err != nil { - return "", err - } - token, err := erc20.NewGGToken(common.HexToAddress("0x5DB9A7629912EBF95876228C24A848de0bfB43A9"), goEthereumClient) - if err != nil { - return "", err - } - name, err := token.Name(nil) - if err != nil { - return "", err - } - fmt.Println(name) - bal, err := token.BalanceOf(nil, common.HexToAddress(addrStr)) - fmt.Println(bal) - if err != nil { - return "", err - } addr := common.HexToAddress(addrStr) ctx, cancel := utils.GetAPIContext() balance, err := cClient.BalanceAt(ctx, addr, nil) @@ -508,6 +559,10 @@ func getCChainBalanceStr(network models.Network, cClient ethclient.Client, addrS if err != nil { return "", err } + return formatCChainBalance(balance) +} + +func formatCChainBalance(balance *big.Int) (string, error) { // convert to nAvax balance = balance.Div(balance, big.NewInt(int64(units.Avax))) if balance.Cmp(big.NewInt(0)) == 0 { From e1b50058d3a6b795995a8614bea8e8dadda07405 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Sat, 8 Jun 2024 20:18:43 -0300 Subject: [PATCH 21/87] enable local network and filter inputs subnets by network --- cmd/teleportercmd/bridgecmd/deploy.go | 237 ++++++++++++++------------ 1 file changed, 124 insertions(+), 113 deletions(-) diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index 0501e51c6..85d365dff 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -11,6 +11,7 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/networkoptions" "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" + "github.com/ava-labs/avalanchego/ids" "github.com/spf13/cobra" ) @@ -68,151 +69,161 @@ func CallDeploy(_ []string, flags DeployFlags) error { if err != nil { return err } - switch network.Kind { - case models.Local: - ux.Logger.PrintToUser("To be defined") - return nil - case models.Devnet: - ux.Logger.PrintToUser("To be defined") + subnetNames, err := app.GetSubnetNames() + if err != nil { + return err + } + subnetNames, err = filterSubnetsByNetwork(network, subnetNames) + if err != nil { + return err + } + subnetOptions := utils.Map(subnetNames, func(s string) string { return "Subnet " + s }) + prompt := "Where is the Token origin?" + cChainOption := "C-Chain" + notListedOption := "My blockchain isn't listed" + subnetOptions = append(append([]string{cChainOption}, subnetOptions...), notListedOption) + subnetOption, err := app.Prompt.CaptureListWithSize( + prompt, + subnetOptions, + 11, + ) + if err != nil { + return err + } + if subnetOption == notListedOption { + ux.Logger.PrintToUser("Please import the subnet first, using the `avalanche subnet import` command suite") return nil - case models.Fuji: - subnetNames, err := app.GetSubnetNames() + } + return nil + tokenSymbol := "AVAX" + if subnetOption != cChainOption { + subnetName := strings.TrimPrefix(subnetOption, "Subnet ") + sc, err := app.LoadSidecar(subnetName) if err != nil { return err } - subnetOptions := utils.Map(subnetNames, func(s string) string { return "Subnet " + s }) - prompt := "Where is the Token origin?" - cChainOption := "C-Chain" - notListedOption := "My blockchain isn't listed" - subnetOptions = append(append([]string{cChainOption}, subnetOptions...), notListedOption) - subnetOption, err := app.Prompt.CaptureListWithSize( + tokenSymbol = sc.TokenSymbol + } + prompt = "What kind of token do you want to bridge?" + popularOption := "A popular token (e.g. AVAX, USDC, WAVAX, ...)" + hubDeployedOption := "A token that already has a Hub deployed" + deployNewHubOption := "Deploy a new Hub for the token" + explainOption := "Explain the difference" + goBackOption := "Go Back" + popularTokensInfo, err := GetPopularTokensInfo(network, subnetOption) + if err != nil { + return err + } + popularTokensDesc := utils.Map( + popularTokensInfo, + func(i PopularTokenInfo) string { + if i.BridgeHubAddress == "" { + return i.Desc() + } else { + return i.Desc() + " (recommended)" + } + }, + ) + options := []string{popularOption, hubDeployedOption, deployNewHubOption, explainOption} + if len(popularTokensDesc) == 0 { + options = []string{hubDeployedOption, deployNewHubOption, explainOption} + } + for { + option, err := app.Prompt.CaptureList( prompt, - subnetOptions, - 11, + options, ) if err != nil { return err } - if subnetOption == notListedOption { - ux.Logger.PrintToUser("Please import the subnet first, using the `avalanche subnet import` command suite") - return nil - } - tokenSymbol := "AVAX" - if subnetOption != cChainOption { - subnetName := strings.TrimPrefix(subnetOption, "Subnet ") - sc, err := app.LoadSidecar(subnetName) + switch option { + case popularOption: + options := popularTokensDesc + options = append(options, goBackOption) + option, err := app.Prompt.CaptureList( + "Choose Token", + options, + ) if err != nil { return err } - tokenSymbol = sc.TokenSymbol - } - prompt = "What kind of token do you want to bridge?" - popularOption := "A popular token (e.g. AVAX, USDC, WAVAX, ...)" - hubDeployedOption := "A token that already has a Hub deployed" - deployNewHubOption := "Deploy a new Hub for the token" - explainOption := "Explain the difference" - goBackOption := "Go Back" - popularTokensInfo, err := GetPopularTokensInfo(network, subnetOption) - if err != nil { - return err - } - popularTokensDesc := utils.Map( - popularTokensInfo, - func(i PopularTokenInfo) string { - if i.BridgeHubAddress == "" { - return i.Desc() - } else { - return i.Desc() + " (recommended)" - } - }, - ) - options := []string{popularOption, hubDeployedOption, deployNewHubOption, explainOption} - if len(popularTokensDesc) == 0 { - options = []string{hubDeployedOption, deployNewHubOption, explainOption} - } - for { + if option == goBackOption { + continue + } + case hubDeployedOption: + _, err = app.Prompt.CaptureAddress( + "Enter the address of the Hub", + ) + if err != nil { + return err + } + case deployNewHubOption: + nativeOption := "The native token " + tokenSymbol + erc20Option := "An ERC-20 token" + options := []string{nativeOption, erc20Option} option, err := app.Prompt.CaptureList( - prompt, + "What kind of token do you want to deploy the Hub for?", options, ) if err != nil { return err } switch option { - case popularOption: - options := popularTokensDesc - options = append(options, goBackOption) - option, err := app.Prompt.CaptureList( - "Choose Token", - options, - ) - if err != nil { - return err - } - if option == goBackOption { - continue - } - case hubDeployedOption: - _, err = app.Prompt.CaptureAddress( - "Enter the address of the Hub", - ) - if err != nil { - return err - } - case deployNewHubOption: - nativeOption := "The native token " + tokenSymbol - erc20Option := "An ERC-20 token" - options := []string{nativeOption, erc20Option} - option, err := app.Prompt.CaptureList( - "What kind of token do you want to deploy the Hub for?", - options, + case erc20Option: + erc20TokenAddr, err := app.Prompt.CaptureAddress( + "Enter the address of the ERC-20 Token", ) if err != nil { return err } - switch option { - case erc20Option: - erc20TokenAddr, err := app.Prompt.CaptureAddress( - "Enter the address of the ERC-20 Token", + if p := utils.Find(popularTokensInfo, func(p PopularTokenInfo) bool { return p.TokenContractAddress == erc20TokenAddr.Hex() }); p != nil { + ux.Logger.PrintToUser("You have entered the address of %s, a popular token in the subnet.", p.TokenName) + deployANewHupOption := "Yes, I want to deploy a new Bridge Hub" + useTheExistingHubOption := "No, I want to use the existing official Bridge Hub" + options := []string{deployANewHupOption, useTheExistingHubOption} + _, err = app.Prompt.CaptureList( + "Are you sure you want to deploy a new Bridge Hub for it?", + options, ) if err != nil { return err } - if p := utils.Find(popularTokensInfo, func(p PopularTokenInfo) bool { return p.TokenContractAddress == erc20TokenAddr.Hex() }); p != nil { - ux.Logger.PrintToUser("You have entered the address of %s, a popular token in the subnet.", p.TokenName) - deployANewHupOption := "Yes, I want to deploy a new Bridge Hub" - useTheExistingHubOption := "No, I want to use the existing official Bridge Hub" - options := []string{deployANewHupOption, useTheExistingHubOption} - _, err = app.Prompt.CaptureList( - "Are you sure you want to deploy a new Bridge Hub for it?", - options, - ) - if err != nil { - return err - } - } } - case explainOption: - ux.Logger.PrintToUser("The difference is...") - ux.Logger.PrintToUser("") - continue } - break + case explainOption: + ux.Logger.PrintToUser("The difference is...") + ux.Logger.PrintToUser("") + continue } - prompt = "Where should the token be bridged as an ERC-20?" - subnetOptions = utils.Filter(subnetOptions, func(s string) bool { return s != subnetOption }) - subnetOption, err = app.Prompt.CaptureListWithSize( - prompt, - subnetOptions, - 11, - ) + break + } + prompt = "Where should the token be bridged as an ERC-20?" + subnetOptions = utils.Filter(subnetOptions, func(s string) bool { return s != subnetOption }) + subnetOption, err = app.Prompt.CaptureListWithSize( + prompt, + subnetOptions, + 11, + ) + if err != nil { + return err + } + if subnetOption == notListedOption { + ux.Logger.PrintToUser("Please import the subnet first, using the `avalanche subnet import` command suite") + return nil + } + return nil +} + +func filterSubnetsByNetwork(network models.Network, subnetNames []string) ([]string, error) { + filtered := []string{} + for _, subnetName := range subnetNames { + sc, err := app.LoadSidecar(subnetName) if err != nil { - return err + return nil, err } - if subnetOption == notListedOption { - ux.Logger.PrintToUser("Please import the subnet first, using the `avalanche subnet import` command suite") - return nil + if sc.Networks[network.Name()].BlockchainID != ids.Empty { + filtered = append(filtered, subnetName) } } - return nil + return filtered, nil } From a7f1ea0e4f168886f07b118493da23e6fa3c954c Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Sat, 8 Jun 2024 20:55:48 -0300 Subject: [PATCH 22/87] refactor obtaining chain info into a separate function --- cmd/teleportercmd/bridgecmd/deploy.go | 114 ++++++++++++++++---------- 1 file changed, 71 insertions(+), 43 deletions(-) diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index 85d365dff..b5251be98 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -16,11 +16,16 @@ import ( "github.com/spf13/cobra" ) +type ChainFlags struct { + SubnetName string + BlockchainID string + CChain bool +} + type DeployFlags struct { Network networkoptions.NetworkFlags - SubnetName string - BlockchainID string - CChain bool + hubFlags ChainFlags + spokeFlags ChainFlags PrivateKey string KeyName string GenesisKey bool @@ -49,6 +54,9 @@ func newDeployCmd() *cobra.Command { Args: cobrautils.ExactArgs(0), } networkoptions.AddNetworkFlagsToCmd(cmd, &deployFlags.Network, true, deploySupportedNetworkOptions) + cmd.Flags().StringVar(&deployFlags.hubFlags.SubnetName, "hub-subnet", "", "use the given CLI subnet as the Bridge Hub's Chain") + cmd.Flags().StringVar(&deployFlags.hubFlags.BlockchainID, "hub-blockchain-id", "", "use the given blockchain ID/Alias as the Bridge Hub's Chain") + cmd.Flags().BoolVar(&deployFlags.hubFlags.CChain, "hub-at-c-chain", false, "use C-Chain as the Bridge Hub's Chain") return cmd } @@ -69,48 +77,33 @@ func CallDeploy(_ []string, flags DeployFlags) error { if err != nil { return err } - subnetNames, err := app.GetSubnetNames() - if err != nil { - return err - } - subnetNames, err = filterSubnetsByNetwork(network, subnetNames) - if err != nil { - return err - } - subnetOptions := utils.Map(subnetNames, func(s string) string { return "Subnet " + s }) - prompt := "Where is the Token origin?" - cChainOption := "C-Chain" - notListedOption := "My blockchain isn't listed" - subnetOptions = append(append([]string{cChainOption}, subnetOptions...), notListedOption) - subnetOption, err := app.Prompt.CaptureListWithSize( - prompt, - subnetOptions, - 11, - ) - if err != nil { - return err - } - if subnetOption == notListedOption { - ux.Logger.PrintToUser("Please import the subnet first, using the `avalanche subnet import` command suite") - return nil + if flags.hubFlags.SubnetName == "" { + prompt := "Where is the Token origin?" + if cancel, err := promptChain(prompt, network, false, "", &flags.hubFlags); err != nil { + return err + } else if cancel { + return nil + } } - return nil tokenSymbol := "AVAX" - if subnetOption != cChainOption { - subnetName := strings.TrimPrefix(subnetOption, "Subnet ") - sc, err := app.LoadSidecar(subnetName) + if !flags.hubFlags.CChain { + sc, err := app.LoadSidecar(flags.hubFlags.SubnetName) if err != nil { return err } tokenSymbol = sc.TokenSymbol } - prompt = "What kind of token do you want to bridge?" + prompt := "What kind of token do you want to bridge?" popularOption := "A popular token (e.g. AVAX, USDC, WAVAX, ...)" hubDeployedOption := "A token that already has a Hub deployed" deployNewHubOption := "Deploy a new Hub for the token" explainOption := "Explain the difference" goBackOption := "Go Back" - popularTokensInfo, err := GetPopularTokensInfo(network, subnetOption) + hubChain := "C-Chain" + if !flags.hubFlags.CChain { + hubChain = flags.hubFlags.SubnetName + } + popularTokensInfo, err := GetPopularTokensInfo(network, hubChain) if err != nil { return err } @@ -198,17 +191,9 @@ func CallDeploy(_ []string, flags DeployFlags) error { break } prompt = "Where should the token be bridged as an ERC-20?" - subnetOptions = utils.Filter(subnetOptions, func(s string) bool { return s != subnetOption }) - subnetOption, err = app.Prompt.CaptureListWithSize( - prompt, - subnetOptions, - 11, - ) - if err != nil { + if cancel, err := promptChain(prompt, network, flags.hubFlags.CChain, flags.hubFlags.SubnetName, &flags.spokeFlags); err != nil { return err - } - if subnetOption == notListedOption { - ux.Logger.PrintToUser("Please import the subnet first, using the `avalanche subnet import` command suite") + } else if cancel { return nil } return nil @@ -227,3 +212,46 @@ func filterSubnetsByNetwork(network models.Network, subnetNames []string) ([]str } return filtered, nil } + +func promptChain( + prompt string, + network models.Network, + avoidCChain bool, + avoidSubnet string, + chainFlags *ChainFlags, +) (bool, error) { + subnetNames, err := app.GetSubnetNames() + if err != nil { + return false, err + } + subnetNames, err = filterSubnetsByNetwork(network, subnetNames) + if err != nil { + return false, err + } + cChainOption := "C-Chain" + notListedOption := "My blockchain isn't listed" + subnetOptions := []string{} + if !avoidCChain { + subnetOptions = append(subnetOptions, cChainOption) + } + subnetOptions = append(subnetOptions, utils.Map(subnetNames, func(s string) string { return "Subnet " + s })...) + subnetOptions = append(subnetOptions, notListedOption) + subnetOption, err := app.Prompt.CaptureListWithSize( + prompt, + subnetOptions, + 11, + ) + if err != nil { + return false, err + } + if subnetOption == notListedOption { + ux.Logger.PrintToUser("Please import the subnet first, using the `avalanche subnet import` command suite") + return true, nil + } + if subnetOption == cChainOption { + chainFlags.CChain = true + } else { + chainFlags.SubnetName = strings.TrimPrefix(subnetOption, "Subnet ") + } + return false, nil +} From c9aecfc7d88e9542baae5bccf170cd8cfad141c8 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Sat, 8 Jun 2024 21:00:55 -0300 Subject: [PATCH 23/87] use flags for hub chain def --- cmd/teleportercmd/bridgecmd/deploy.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index b5251be98..c270336a7 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -4,6 +4,7 @@ package bridgecmd import ( _ "embed" + "fmt" "strings" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" @@ -56,7 +57,7 @@ func newDeployCmd() *cobra.Command { networkoptions.AddNetworkFlagsToCmd(cmd, &deployFlags.Network, true, deploySupportedNetworkOptions) cmd.Flags().StringVar(&deployFlags.hubFlags.SubnetName, "hub-subnet", "", "use the given CLI subnet as the Bridge Hub's Chain") cmd.Flags().StringVar(&deployFlags.hubFlags.BlockchainID, "hub-blockchain-id", "", "use the given blockchain ID/Alias as the Bridge Hub's Chain") - cmd.Flags().BoolVar(&deployFlags.hubFlags.CChain, "hub-at-c-chain", false, "use C-Chain as the Bridge Hub's Chain") + cmd.Flags().BoolVar(&deployFlags.hubFlags.CChain, "c-chain-hub", false, "use C-Chain as the Bridge Hub's Chain") return cmd } @@ -77,7 +78,7 @@ func CallDeploy(_ []string, flags DeployFlags) error { if err != nil { return err } - if flags.hubFlags.SubnetName == "" { + if flags.hubFlags.SubnetName == "" && !flags.hubFlags.CChain { prompt := "Where is the Token origin?" if cancel, err := promptChain(prompt, network, false, "", &flags.hubFlags); err != nil { return err @@ -85,6 +86,8 @@ func CallDeploy(_ []string, flags DeployFlags) error { return nil } } + fmt.Println(flags.hubFlags) + return nil tokenSymbol := "AVAX" if !flags.hubFlags.CChain { sc, err := app.LoadSidecar(flags.hubFlags.SubnetName) @@ -228,6 +231,7 @@ func promptChain( if err != nil { return false, err } + subnetNames = utils.RemoveFromSlice(subnetNames, avoidSubnet) cChainOption := "C-Chain" notListedOption := "My blockchain isn't listed" subnetOptions := []string{} From 78b523c53de020117c306c06477f9370fe3ff52e Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Sat, 8 Jun 2024 21:19:18 -0300 Subject: [PATCH 24/87] add flags for the different hub options --- cmd/teleportercmd/bridgecmd/deploy.go | 35 +++++++++++++++++---------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index c270336a7..c00a62dde 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -23,9 +23,16 @@ type ChainFlags struct { CChain bool } +type HubFlags struct { + chainFlags ChainFlags + hubAddress string + native bool + erc20Address string +} + type DeployFlags struct { Network networkoptions.NetworkFlags - hubFlags ChainFlags + hubFlags HubFlags spokeFlags ChainFlags PrivateKey string KeyName string @@ -55,9 +62,12 @@ func newDeployCmd() *cobra.Command { Args: cobrautils.ExactArgs(0), } networkoptions.AddNetworkFlagsToCmd(cmd, &deployFlags.Network, true, deploySupportedNetworkOptions) - cmd.Flags().StringVar(&deployFlags.hubFlags.SubnetName, "hub-subnet", "", "use the given CLI subnet as the Bridge Hub's Chain") - cmd.Flags().StringVar(&deployFlags.hubFlags.BlockchainID, "hub-blockchain-id", "", "use the given blockchain ID/Alias as the Bridge Hub's Chain") - cmd.Flags().BoolVar(&deployFlags.hubFlags.CChain, "c-chain-hub", false, "use C-Chain as the Bridge Hub's Chain") + cmd.Flags().StringVar(&deployFlags.hubFlags.chainFlags.SubnetName, "hub-subnet", "", "use the given CLI subnet as the Bridge Hub's Chain") + cmd.Flags().StringVar(&deployFlags.hubFlags.chainFlags.BlockchainID, "hub-blockchain-id", "", "use the given blockchain ID/Alias as the Bridge Hub's Chain") + cmd.Flags().BoolVar(&deployFlags.hubFlags.chainFlags.CChain, "c-chain-hub", false, "use C-Chain as the Bridge Hub's Chain") + cmd.Flags().BoolVar(&deployFlags.hubFlags.native, "deploy-native-hub", false, "deploy a Bridge Hub for the Chain's Native Token") + cmd.Flags().StringVar(&deployFlags.hubFlags.erc20Address, "deploy-erc20-hub", "", "deploy a Bridge Hub for the Chain's ERC20 Token") + cmd.Flags().StringVar(&deployFlags.hubFlags.hubAddress, "use-hub", "", "use the given Bridge Hub Address") return cmd } @@ -78,19 +88,18 @@ func CallDeploy(_ []string, flags DeployFlags) error { if err != nil { return err } - if flags.hubFlags.SubnetName == "" && !flags.hubFlags.CChain { + if flags.hubFlags.chainFlags.SubnetName == "" && !flags.hubFlags.chainFlags.CChain { prompt := "Where is the Token origin?" - if cancel, err := promptChain(prompt, network, false, "", &flags.hubFlags); err != nil { + if cancel, err := promptChain(prompt, network, false, "", &flags.hubFlags.chainFlags); err != nil { return err } else if cancel { return nil } } - fmt.Println(flags.hubFlags) - return nil + fmt.Printf("%#v\n", flags.hubFlags) tokenSymbol := "AVAX" - if !flags.hubFlags.CChain { - sc, err := app.LoadSidecar(flags.hubFlags.SubnetName) + if !flags.hubFlags.chainFlags.CChain { + sc, err := app.LoadSidecar(flags.hubFlags.chainFlags.SubnetName) if err != nil { return err } @@ -103,8 +112,8 @@ func CallDeploy(_ []string, flags DeployFlags) error { explainOption := "Explain the difference" goBackOption := "Go Back" hubChain := "C-Chain" - if !flags.hubFlags.CChain { - hubChain = flags.hubFlags.SubnetName + if !flags.hubFlags.chainFlags.CChain { + hubChain = flags.hubFlags.chainFlags.SubnetName } popularTokensInfo, err := GetPopularTokensInfo(network, hubChain) if err != nil { @@ -194,7 +203,7 @@ func CallDeploy(_ []string, flags DeployFlags) error { break } prompt = "Where should the token be bridged as an ERC-20?" - if cancel, err := promptChain(prompt, network, flags.hubFlags.CChain, flags.hubFlags.SubnetName, &flags.spokeFlags); err != nil { + if cancel, err := promptChain(prompt, network, flags.hubFlags.chainFlags.CChain, flags.hubFlags.chainFlags.SubnetName, &flags.spokeFlags); err != nil { return err } else if cancel { return nil From 35d64e76174c34937b226f0c1ce9893d7cb8dde3 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Sat, 8 Jun 2024 21:42:57 -0300 Subject: [PATCH 25/87] validate and prompt hub options --- cmd/teleportercmd/bridgecmd/deploy.go | 184 ++++++++++++++------------ pkg/prompts/prompts.go | 2 +- pkg/prompts/validations.go | 2 +- 3 files changed, 103 insertions(+), 85 deletions(-) diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index c00a62dde..3ef845e01 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -10,6 +10,7 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/cobrautils" "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/networkoptions" + "github.com/ava-labs/avalanche-cli/pkg/prompts" "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" "github.com/ava-labs/avalanchego/ids" @@ -96,113 +97,130 @@ func CallDeploy(_ []string, flags DeployFlags) error { return nil } } - fmt.Printf("%#v\n", flags.hubFlags) - tokenSymbol := "AVAX" - if !flags.hubFlags.chainFlags.CChain { - sc, err := app.LoadSidecar(flags.hubFlags.chainFlags.SubnetName) + if flags.hubFlags.hubAddress == "" && flags.hubFlags.erc20Address == "" { + tokenSymbol := "AVAX" + if !flags.hubFlags.chainFlags.CChain { + sc, err := app.LoadSidecar(flags.hubFlags.chainFlags.SubnetName) + if err != nil { + return err + } + tokenSymbol = sc.TokenSymbol + } + prompt := "What kind of token do you want to bridge?" + popularOption := "A popular token (e.g. AVAX, USDC, WAVAX, ...)" + hubDeployedOption := "A token that already has a Hub deployed" + deployNewHubOption := "Deploy a new Hub for the token" + explainOption := "Explain the difference" + goBackOption := "Go Back" + hubChain := "C-Chain" + if !flags.hubFlags.chainFlags.CChain { + hubChain = flags.hubFlags.chainFlags.SubnetName + } + popularTokensInfo, err := GetPopularTokensInfo(network, hubChain) if err != nil { return err } - tokenSymbol = sc.TokenSymbol - } - prompt := "What kind of token do you want to bridge?" - popularOption := "A popular token (e.g. AVAX, USDC, WAVAX, ...)" - hubDeployedOption := "A token that already has a Hub deployed" - deployNewHubOption := "Deploy a new Hub for the token" - explainOption := "Explain the difference" - goBackOption := "Go Back" - hubChain := "C-Chain" - if !flags.hubFlags.chainFlags.CChain { - hubChain = flags.hubFlags.chainFlags.SubnetName - } - popularTokensInfo, err := GetPopularTokensInfo(network, hubChain) - if err != nil { - return err - } - popularTokensDesc := utils.Map( - popularTokensInfo, - func(i PopularTokenInfo) string { - if i.BridgeHubAddress == "" { - return i.Desc() - } else { - return i.Desc() + " (recommended)" - } - }, - ) - options := []string{popularOption, hubDeployedOption, deployNewHubOption, explainOption} - if len(popularTokensDesc) == 0 { - options = []string{hubDeployedOption, deployNewHubOption, explainOption} - } - for { - option, err := app.Prompt.CaptureList( - prompt, - options, + popularTokensDesc := utils.Map( + popularTokensInfo, + func(i PopularTokenInfo) string { + if i.BridgeHubAddress == "" { + return i.Desc() + } else { + return i.Desc() + " (recommended)" + } + }, ) - if err != nil { - return err + options := []string{popularOption, hubDeployedOption, deployNewHubOption, explainOption} + if len(popularTokensDesc) == 0 { + options = []string{hubDeployedOption, deployNewHubOption, explainOption} } - switch option { - case popularOption: - options := popularTokensDesc - options = append(options, goBackOption) - option, err := app.Prompt.CaptureList( - "Choose Token", - options, - ) - if err != nil { - return err - } - if option == goBackOption { - continue - } - case hubDeployedOption: - _, err = app.Prompt.CaptureAddress( - "Enter the address of the Hub", - ) - if err != nil { - return err - } - case deployNewHubOption: - nativeOption := "The native token " + tokenSymbol - erc20Option := "An ERC-20 token" - options := []string{nativeOption, erc20Option} + for { option, err := app.Prompt.CaptureList( - "What kind of token do you want to deploy the Hub for?", + prompt, options, ) if err != nil { return err } switch option { - case erc20Option: - erc20TokenAddr, err := app.Prompt.CaptureAddress( - "Enter the address of the ERC-20 Token", + case popularOption: + options := popularTokensDesc + options = append(options, goBackOption) + option, err := app.Prompt.CaptureList( + "Choose Token", + options, ) if err != nil { return err } - if p := utils.Find(popularTokensInfo, func(p PopularTokenInfo) bool { return p.TokenContractAddress == erc20TokenAddr.Hex() }); p != nil { - ux.Logger.PrintToUser("You have entered the address of %s, a popular token in the subnet.", p.TokenName) - deployANewHupOption := "Yes, I want to deploy a new Bridge Hub" - useTheExistingHubOption := "No, I want to use the existing official Bridge Hub" - options := []string{deployANewHupOption, useTheExistingHubOption} - _, err = app.Prompt.CaptureList( - "Are you sure you want to deploy a new Bridge Hub for it?", - options, + if option == goBackOption { + continue + } + case hubDeployedOption: + addr, err := app.Prompt.CaptureAddress( + "Enter the address of the Hub", + ) + if err != nil { + return err + } + flags.hubFlags.hubAddress = addr.Hex() + case deployNewHubOption: + nativeOption := "The native token " + tokenSymbol + erc20Option := "An ERC-20 token" + options := []string{nativeOption, erc20Option} + option, err := app.Prompt.CaptureList( + "What kind of token do you want to deploy the Hub for?", + options, + ) + if err != nil { + return err + } + switch option { + case nativeOption: + flags.hubFlags.native = true + case erc20Option: + erc20TokenAddr, err := app.Prompt.CaptureAddress( + "Enter the address of the ERC-20 Token", ) if err != nil { return err } + flags.hubFlags.erc20Address = erc20TokenAddr.Hex() + if p := utils.Find(popularTokensInfo, func(p PopularTokenInfo) bool { return p.TokenContractAddress == erc20TokenAddr.Hex() }); p != nil { + ux.Logger.PrintToUser("You have entered the address of %s, a popular token in the subnet.", p.TokenName) + deployANewHupOption := "Yes, I want to deploy a new Bridge Hub" + useTheExistingHubOption := "No, I want to use the existing official Bridge Hub" + options := []string{deployANewHupOption, useTheExistingHubOption} + _, err = app.Prompt.CaptureList( + "Are you sure you want to deploy a new Bridge Hub for it?", + options, + ) + if err != nil { + return err + } + } } + case explainOption: + ux.Logger.PrintToUser("The difference is...") + ux.Logger.PrintToUser("") + continue } - case explainOption: - ux.Logger.PrintToUser("The difference is...") - ux.Logger.PrintToUser("") - continue + break } - break } - prompt = "Where should the token be bridged as an ERC-20?" + if flags.hubFlags.hubAddress != "" { + if err := prompts.ValidateAddress(flags.hubFlags.hubAddress); err != nil { + return fmt.Errorf("failure validating %s: %w", flags.hubFlags.hubAddress, err) + } + } + if flags.hubFlags.erc20Address != "" { + if err := prompts.ValidateAddress(flags.hubFlags.erc20Address); err != nil { + return fmt.Errorf("failure validating %s: %w", flags.hubFlags.erc20Address, err) + } + } + fmt.Printf("%#v\n", flags.hubFlags) + return nil + prompt := "Where should the token be bridged as an ERC-20?" if cancel, err := promptChain(prompt, network, flags.hubFlags.chainFlags.CChain, flags.hubFlags.chainFlags.SubnetName, &flags.spokeFlags); err != nil { return err } else if cancel { diff --git a/pkg/prompts/prompts.go b/pkg/prompts/prompts.go index add64086b..86cf7ddaa 100644 --- a/pkg/prompts/prompts.go +++ b/pkg/prompts/prompts.go @@ -438,7 +438,7 @@ func (*realPrompter) CaptureXChainAddress(promptStr string, network models.Netwo func (*realPrompter) CaptureAddress(promptStr string) (common.Address, error) { prompt := promptui.Prompt{ Label: promptStr, - Validate: validateAddress, + Validate: ValidateAddress, } addressStr, err := prompt.Run() diff --git a/pkg/prompts/validations.go b/pkg/prompts/validations.go index c3bcc4d5b..eb671a8bd 100644 --- a/pkg/prompts/validations.go +++ b/pkg/prompts/validations.go @@ -87,7 +87,7 @@ func validateNodeID(input string) error { return err } -func validateAddress(input string) error { +func ValidateAddress(input string) error { if !common.IsHexAddress(input) { return errors.New("invalid address") } From 60f39f1d27d0a6f7afe8c51094b87c0c977c6b02 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Sat, 8 Jun 2024 21:44:27 -0300 Subject: [PATCH 26/87] nit --- cmd/teleportercmd/bridgecmd/deploy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index 3ef845e01..23993ae22 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -97,7 +97,7 @@ func CallDeploy(_ []string, flags DeployFlags) error { return nil } } - if flags.hubFlags.hubAddress == "" && flags.hubFlags.erc20Address == "" { + if flags.hubFlags.hubAddress == "" && flags.hubFlags.erc20Address == "" && !flags.hubFlags.native { tokenSymbol := "AVAX" if !flags.hubFlags.chainFlags.CChain { sc, err := app.LoadSidecar(flags.hubFlags.chainFlags.SubnetName) From f853595789c9b94940f3db0d42bf5225c94fa40a Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Sat, 8 Jun 2024 21:48:17 -0300 Subject: [PATCH 27/87] add validation for subnet name --- cmd/teleportercmd/bridgecmd/deploy.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index 23993ae22..65a2b5253 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -97,6 +97,11 @@ func CallDeploy(_ []string, flags DeployFlags) error { return nil } } + if flags.hubFlags.chainFlags.SubnetName != "" { + if err := validateSubnet(network, flags.hubFlags.chainFlags.SubnetName); err != nil { + return err + } + } if flags.hubFlags.hubAddress == "" && flags.hubFlags.erc20Address == "" && !flags.hubFlags.native { tokenSymbol := "AVAX" if !flags.hubFlags.chainFlags.CChain { @@ -243,6 +248,17 @@ func filterSubnetsByNetwork(network models.Network, subnetNames []string) ([]str return filtered, nil } +func validateSubnet(network models.Network, subnetName string) error { + sc, err := app.LoadSidecar(subnetName) + if err != nil { + return err + } + if sc.Networks[network.Name()].BlockchainID == ids.Empty { + return fmt.Errorf("subnet %s not deployed into %s", subnetName, network.Name()) + } + return nil +} + func promptChain( prompt string, network models.Network, From 6c6575b988dd7d2b7be21d6dd1814833bcf46590 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Sat, 8 Jun 2024 21:52:29 -0300 Subject: [PATCH 28/87] nits --- cmd/teleportercmd/bridgecmd/popularTokensInfo.go | 6 +----- cmd/teleportercmd/bridgecmd/popularTokensInfo.json | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/cmd/teleportercmd/bridgecmd/popularTokensInfo.go b/cmd/teleportercmd/bridgecmd/popularTokensInfo.go index 0e12d76ce..520c3971f 100644 --- a/cmd/teleportercmd/bridgecmd/popularTokensInfo.go +++ b/cmd/teleportercmd/bridgecmd/popularTokensInfo.go @@ -36,9 +36,5 @@ func GetPopularTokensInfo(network models.Network, blockchainAlias string) ([]Pop if err := json.Unmarshal(popularTokensInfoByteSlice, &popularTokensInfo); err != nil { return nil, fmt.Errorf("unabled to get popular tokens info from file: %w", err) } - if network.Kind == models.Fuji { - return popularTokensInfo[models.Fuji.String()][blockchainAlias], nil - } else { - return nil, nil - } + return popularTokensInfo[network.Kind.String()][blockchainAlias], nil } diff --git a/cmd/teleportercmd/bridgecmd/popularTokensInfo.json b/cmd/teleportercmd/bridgecmd/popularTokensInfo.json index dd6e7f818..8fd1c3c26 100644 --- a/cmd/teleportercmd/bridgecmd/popularTokensInfo.json +++ b/cmd/teleportercmd/bridgecmd/popularTokensInfo.json @@ -19,4 +19,3 @@ ] } } - From 6960aa6b7eaf13f9b75d7039f75bc5a6a46b36ed Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Sat, 8 Jun 2024 22:10:39 -0300 Subject: [PATCH 29/87] validate erc20 token --- cmd/keycmd/list.go | 2 +- cmd/teleportercmd/bridgecmd/deploy.go | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/cmd/keycmd/list.go b/cmd/keycmd/list.go index c67605f2a..bb414be42 100644 --- a/cmd/keycmd/list.go +++ b/cmd/keycmd/list.go @@ -536,7 +536,7 @@ func printAddrInfos(addrInfos []addressInfo) { table := tablewriter.NewWriter(os.Stdout) table.SetHeader(header) table.SetRowLine(true) - table.SetAutoMergeCellsByColumnIndex([]int{0, 1, 2, 3}) + table.SetAutoMergeCellsByColumnIndex([]int{0, 1, 2}) for _, addrInfo := range addrInfos { table.Append([]string{ addrInfo.kind, diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index 65a2b5253..cdd45e5d4 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -14,6 +14,9 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" "github.com/ava-labs/avalanchego/ids" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/liyue201/erc20-go/erc20" "github.com/spf13/cobra" ) @@ -222,6 +225,26 @@ func CallDeploy(_ []string, flags DeployFlags) error { if err := prompts.ValidateAddress(flags.hubFlags.erc20Address); err != nil { return fmt.Errorf("failure validating %s: %w", flags.hubFlags.erc20Address, err) } + hubEndpoint := network.CChainEndpoint() + if flags.hubFlags.chainFlags.SubnetName != "" { + sc, err := app.LoadSidecar(flags.hubFlags.chainFlags.SubnetName) + if err != nil { + return err + } + blockchainID := sc.Networks[network.Name()].BlockchainID + hubEndpoint = network.BlockchainEndpoint(blockchainID.String()) + } + client, err := ethclient.Dial(hubEndpoint) + if err != nil { + return err + } + token, err := erc20.NewGGToken(common.HexToAddress(flags.hubFlags.erc20Address), client) + if err != nil { + return err + } + if _, err := token.Name(nil); err != nil { + return err + } } fmt.Printf("%#v\n", flags.hubFlags) return nil From 479e824a7b87a2c425bee71dafc2fa0144aa7287 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Sat, 8 Jun 2024 22:23:06 -0300 Subject: [PATCH 30/87] start adding helpers for deploy --- cmd/teleportercmd/bridgecmd/helpers.go | 160 +++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 cmd/teleportercmd/bridgecmd/helpers.go diff --git a/cmd/teleportercmd/bridgecmd/helpers.go b/cmd/teleportercmd/bridgecmd/helpers.go new file mode 100644 index 000000000..57f309d77 --- /dev/null +++ b/cmd/teleportercmd/bridgecmd/helpers.go @@ -0,0 +1,160 @@ +// Copyright (C) 2022, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +package bridgecmd + +import ( + _ "embed" + "fmt" + "os" + "path/filepath" + + "github.com/ava-labs/avalanche-cli/pkg/evm" + "github.com/ava-labs/avalanche-cli/pkg/utils" + "github.com/ava-labs/subnet-evm/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" +) + +func deployERC20Hub( + srcDir string, + rpcURL string, + prefundedPrivateKey string, + teleporterRegistryAddress common.Address, + teleporterManagerAddress common.Address, + wrappedNativeTokenAddress common.Address, +) (common.Address, error) { + srcDir = utils.ExpandHome(srcDir) + abiPath := filepath.Join(srcDir, "contracts/out/ERC20Source.sol/ERC20Source.abi.json") + binPath := filepath.Join(srcDir, "contracts/out/ERC20Source.sol/ERC20Source.bin") + abiBytes, err := os.ReadFile(abiPath) + if err != nil { + return common.Address{}, err + } + binBytes, err := os.ReadFile(binPath) + if err != nil { + return common.Address{}, err + } + metadata := &bind.MetaData{ + ABI: string(abiBytes), + Bin: string(binBytes), + } + abi, err := metadata.GetAbi() + if err != nil { + return common.Address{}, err + } + bin := common.FromHex(metadata.Bin) + client, err := evm.GetClient(rpcURL) + if err != nil { + return common.Address{}, err + } + defer client.Close() + txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) + if err != nil { + return common.Address{}, err + } + address, tx, _, err := bind.DeployContract(txOpts, *abi, bin, client, teleporterRegistryAddress, teleporterManagerAddress, wrappedNativeTokenAddress) + if err != nil { + return common.Address{}, err + } + if _, success, err := evm.WaitForTransaction(client, tx); err != nil { + return common.Address{}, err + } else if !success { + return common.Address{}, fmt.Errorf("failed receipt status deploying contract") + } + return address, nil +} + +func deployNativeHub( + srcDir string, + rpcURL string, + prefundedPrivateKey string, + teleporterRegistryAddress common.Address, + teleporterManagerAddress common.Address, + wrappedNativeTokenAddress common.Address, +) (common.Address, error) { + srcDir = utils.ExpandHome(srcDir) + abiPath := filepath.Join(srcDir, "contracts/out/NativeTokenSource.sol/NativeTokenSource.abi.json") + binPath := filepath.Join(srcDir, "contracts/out/NativeTokenSource.sol/NativeTokenSource.bin") + abiBytes, err := os.ReadFile(abiPath) + if err != nil { + return common.Address{}, err + } + binBytes, err := os.ReadFile(binPath) + if err != nil { + return common.Address{}, err + } + metadata := &bind.MetaData{ + ABI: string(abiBytes), + Bin: string(binBytes), + } + abi, err := metadata.GetAbi() + if err != nil { + return common.Address{}, err + } + bin := common.FromHex(metadata.Bin) + client, err := evm.GetClient(rpcURL) + if err != nil { + return common.Address{}, err + } + defer client.Close() + txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) + if err != nil { + return common.Address{}, err + } + address, tx, _, err := bind.DeployContract(txOpts, *abi, bin, client, teleporterRegistryAddress, teleporterManagerAddress, wrappedNativeTokenAddress) + if err != nil { + return common.Address{}, err + } + if _, success, err := evm.WaitForTransaction(client, tx); err != nil { + return common.Address{}, err + } else if !success { + return common.Address{}, fmt.Errorf("failed receipt status deploying contract") + } + return address, nil +} + +func deployWrappedNativeToken( + srcDir string, + rpcURL string, + prefundedPrivateKey string, + tokenName string, +) (common.Address, error) { + srcDir = utils.ExpandHome(srcDir) + abiPath := filepath.Join(srcDir, "contracts/out/WrappedNativeToken.sol/WrappedNativeToken.abi.json") + binPath := filepath.Join(srcDir, "contracts/out/WrappedNativeToken.sol/WrappedNativeToken.bin") + abiBytes, err := os.ReadFile(abiPath) + if err != nil { + return common.Address{}, err + } + binBytes, err := os.ReadFile(binPath) + if err != nil { + return common.Address{}, err + } + metadata := &bind.MetaData{ + ABI: string(abiBytes), + Bin: string(binBytes), + } + abi, err := metadata.GetAbi() + if err != nil { + return common.Address{}, err + } + bin := common.FromHex(metadata.Bin) + client, err := evm.GetClient(rpcURL) + if err != nil { + return common.Address{}, err + } + defer client.Close() + txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) + if err != nil { + return common.Address{}, err + } + address, tx, _, err := bind.DeployContract(txOpts, *abi, bin, client, tokenName) + if err != nil { + return common.Address{}, err + } + if _, success, err := evm.WaitForTransaction(client, tx); err != nil { + return common.Address{}, err + } else if !success { + return common.Address{}, fmt.Errorf("failed receipt status deploying contract") + } + return address, nil +} From d8f58a7470e79e87a644f32100b8d1964b6a890a Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Sat, 8 Jun 2024 23:13:57 -0300 Subject: [PATCH 31/87] bridge hub deployed --- cmd/teleportercmd/bridgecmd/deploy.go | 23 ++++++++++++++++++++++- cmd/teleportercmd/bridgecmd/helpers.go | 18 ++++++++++++++---- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index cdd45e5d4..3f11e68d8 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -238,13 +238,34 @@ func CallDeploy(_ []string, flags DeployFlags) error { if err != nil { return err } - token, err := erc20.NewGGToken(common.HexToAddress(flags.hubFlags.erc20Address), client) + erc20TokenAddress := common.HexToAddress(flags.hubFlags.erc20Address) + token, err := erc20.NewGGToken(erc20TokenAddress, client) if err != nil { return err } if _, err := token.Name(nil); err != nil { return err } + decimals, err := token.Decimals(nil) + if err != nil { + return err + } + bridgeSrcDir := utils.ExpandHome("~/Workspace/projects/teleporter-token-bridge/") + teleporterRegistryAddress := common.HexToAddress("0x17aB05351fC94a1a67Bf3f56DdbB941aE6c63E25") + teleporterManagerAddress := common.HexToAddress("0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC") + hubAddress, err := deployERC20Hub( + bridgeSrcDir, + hubEndpoint, + "56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027", + teleporterRegistryAddress, + teleporterManagerAddress, + erc20TokenAddress, + decimals, + ) + if err != nil { + return err + } + fmt.Println(hubAddress) } fmt.Printf("%#v\n", flags.hubFlags) return nil diff --git a/cmd/teleportercmd/bridgecmd/helpers.go b/cmd/teleportercmd/bridgecmd/helpers.go index 57f309d77..950730ccd 100644 --- a/cmd/teleportercmd/bridgecmd/helpers.go +++ b/cmd/teleportercmd/bridgecmd/helpers.go @@ -20,11 +20,12 @@ func deployERC20Hub( prefundedPrivateKey string, teleporterRegistryAddress common.Address, teleporterManagerAddress common.Address, - wrappedNativeTokenAddress common.Address, + erc20TokenAddress common.Address, + erc20TokenDecimals uint8, ) (common.Address, error) { srcDir = utils.ExpandHome(srcDir) - abiPath := filepath.Join(srcDir, "contracts/out/ERC20Source.sol/ERC20Source.abi.json") - binPath := filepath.Join(srcDir, "contracts/out/ERC20Source.sol/ERC20Source.bin") + abiPath := filepath.Join(srcDir, "contracts/out/ERC20TokenHub.sol/ERC20TokenHub.abi.json") + binPath := filepath.Join(srcDir, "contracts/out/ERC20TokenHub.sol/ERC20TokenHub.bin") abiBytes, err := os.ReadFile(abiPath) if err != nil { return common.Address{}, err @@ -51,7 +52,16 @@ func deployERC20Hub( if err != nil { return common.Address{}, err } - address, tx, _, err := bind.DeployContract(txOpts, *abi, bin, client, teleporterRegistryAddress, teleporterManagerAddress, wrappedNativeTokenAddress) + address, tx, _, err := bind.DeployContract( + txOpts, + *abi, + bin, + client, + teleporterRegistryAddress, + teleporterManagerAddress, + erc20TokenAddress, + erc20TokenDecimals, + ) if err != nil { return common.Address{}, err } From e7a35aae604701684f8bf34ffc03af3e1487ff87 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Sat, 8 Jun 2024 23:36:54 -0300 Subject: [PATCH 32/87] erc20 hub deployed on local network c-chain --- cmd/teleportercmd/bridgecmd/deploy.go | 36 +++++++++++++++++++++++---- pkg/subnet/local.go | 1 + 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index 3f11e68d8..134056151 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -8,9 +8,11 @@ import ( "strings" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" + "github.com/ava-labs/avalanche-cli/pkg/key" "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/networkoptions" "github.com/ava-labs/avalanche-cli/pkg/prompts" + "github.com/ava-labs/avalanche-cli/pkg/subnet" "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" "github.com/ava-labs/avalanchego/ids" @@ -246,25 +248,49 @@ func CallDeploy(_ []string, flags DeployFlags) error { if _, err := token.Name(nil); err != nil { return err } + // TODO: find out if there are decimals options and why (academy) decimals, err := token.Decimals(nil) if err != nil { return err } bridgeSrcDir := utils.ExpandHome("~/Workspace/projects/teleporter-token-bridge/") - teleporterRegistryAddress := common.HexToAddress("0x17aB05351fC94a1a67Bf3f56DdbB941aE6c63E25") - teleporterManagerAddress := common.HexToAddress("0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC") + + // TODO: need registry address, manager address, private key for the hub chain (academy for fuji) + teleporterRegistryAddress := "" + teleporterManagerAddress := "" + privateKey := "" + + if network.Kind == models.Local { + if flags.hubFlags.chainFlags.CChain { + if b, extraLocalNetworkData, err := subnet.GetExtraLocalNetworkData(); err != nil { + return err + } else if b { + teleporterRegistryAddress = extraLocalNetworkData.CChainTeleporterRegistryAddress + } else { + return fmt.Errorf("could not find teleporter registry address on local network C-Chain") + } + k, err := key.LoadEwoq(network.ID) + if err != nil { + return err + } + teleporterManagerAddress = k.C() + privateKey = k.PrivKeyHex() + } + } + hubAddress, err := deployERC20Hub( bridgeSrcDir, hubEndpoint, - "56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027", - teleporterRegistryAddress, - teleporterManagerAddress, + privateKey, + common.HexToAddress(teleporterRegistryAddress), + common.HexToAddress(teleporterManagerAddress), erc20TokenAddress, decimals, ) if err != nil { return err } + fmt.Println(hubAddress) } fmt.Printf("%#v\n", flags.hubFlags) diff --git a/pkg/subnet/local.go b/pkg/subnet/local.go index eb9c9afb9..1251a043c 100644 --- a/pkg/subnet/local.go +++ b/pkg/subnet/local.go @@ -1175,6 +1175,7 @@ func GetExtraLocalNetworkData() (bool, ExtraLocalNetworkData, error) { return false, extraLocalNetworkData, err } extraLocalNetworkDataPath := filepath.Join(clusterInfo.GetRootDataDir(), constants.ExtraLocalNetworkDataFilename) + fmt.Println(extraLocalNetworkDataPath) if !utils.FileExists(extraLocalNetworkDataPath) { return false, extraLocalNetworkData, nil } From bb13f14e293e28fcca21a264d0b37823c15b3ebc Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Sat, 8 Jun 2024 23:40:46 -0300 Subject: [PATCH 33/87] nit --- cmd/teleportercmd/bridgecmd/deploy.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index 134056151..ca7b96c01 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -218,10 +218,12 @@ func CallDeploy(_ []string, flags DeployFlags) error { break } } + var hubAddress common.Address if flags.hubFlags.hubAddress != "" { if err := prompts.ValidateAddress(flags.hubFlags.hubAddress); err != nil { return fmt.Errorf("failure validating %s: %w", flags.hubFlags.hubAddress, err) } + hubAddress = common.HexToAddress(flags.hubFlags.hubAddress) } if flags.hubFlags.erc20Address != "" { if err := prompts.ValidateAddress(flags.hubFlags.erc20Address); err != nil { @@ -278,7 +280,7 @@ func CallDeploy(_ []string, flags DeployFlags) error { } } - hubAddress, err := deployERC20Hub( + hubAddress, err = deployERC20Hub( bridgeSrcDir, hubEndpoint, privateKey, @@ -290,9 +292,9 @@ func CallDeploy(_ []string, flags DeployFlags) error { if err != nil { return err } - - fmt.Println(hubAddress) } + + fmt.Println(hubAddress) fmt.Printf("%#v\n", flags.hubFlags) return nil prompt := "Where should the token be bridged as an ERC-20?" From 8af7be1444b06dedcd6202bcc7600c7c0b47325b Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Sun, 9 Jun 2024 00:11:23 -0300 Subject: [PATCH 34/87] nit --- cmd/teleportercmd/bridgecmd/deploy.go | 40 ++++++++++++--------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index ca7b96c01..a86fff1e9 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -24,9 +24,8 @@ import ( ) type ChainFlags struct { - SubnetName string - BlockchainID string - CChain bool + SubnetName string + CChain bool } type HubFlags struct { @@ -37,16 +36,9 @@ type HubFlags struct { } type DeployFlags struct { - Network networkoptions.NetworkFlags - hubFlags HubFlags - spokeFlags ChainFlags - PrivateKey string - KeyName string - GenesisKey bool - DeployMessenger bool - DeployRegistry bool - TeleporterVersion string - RPCURL string + Network networkoptions.NetworkFlags + hubFlags HubFlags + spokeFlags ChainFlags } var ( @@ -69,11 +61,12 @@ func newDeployCmd() *cobra.Command { } networkoptions.AddNetworkFlagsToCmd(cmd, &deployFlags.Network, true, deploySupportedNetworkOptions) cmd.Flags().StringVar(&deployFlags.hubFlags.chainFlags.SubnetName, "hub-subnet", "", "use the given CLI subnet as the Bridge Hub's Chain") - cmd.Flags().StringVar(&deployFlags.hubFlags.chainFlags.BlockchainID, "hub-blockchain-id", "", "use the given blockchain ID/Alias as the Bridge Hub's Chain") cmd.Flags().BoolVar(&deployFlags.hubFlags.chainFlags.CChain, "c-chain-hub", false, "use C-Chain as the Bridge Hub's Chain") cmd.Flags().BoolVar(&deployFlags.hubFlags.native, "deploy-native-hub", false, "deploy a Bridge Hub for the Chain's Native Token") cmd.Flags().StringVar(&deployFlags.hubFlags.erc20Address, "deploy-erc20-hub", "", "deploy a Bridge Hub for the Chain's ERC20 Token") cmd.Flags().StringVar(&deployFlags.hubFlags.hubAddress, "use-hub", "", "use the given Bridge Hub Address") + cmd.Flags().BoolVar(&deployFlags.spokeFlags.CChain, "c-chain-spoke", false, "use C-Chain as the Bridge Spoke's Chain") + cmd.Flags().StringVar(&deployFlags.spokeFlags.SubnetName, "spoke-subnet", "", "use the given CLI subnet as the Bridge Spoke's Chain") return cmd } @@ -218,6 +211,16 @@ func CallDeploy(_ []string, flags DeployFlags) error { break } } + + if !flags.spokeFlags.CChain && flags.spokeFlags.SubnetName == "" { + prompt := "Where should the token be bridged as an ERC-20?" + if cancel, err := promptChain(prompt, network, flags.hubFlags.chainFlags.CChain, flags.hubFlags.chainFlags.SubnetName, &flags.spokeFlags); err != nil { + return err + } else if cancel { + return nil + } + } + var hubAddress common.Address if flags.hubFlags.hubAddress != "" { if err := prompts.ValidateAddress(flags.hubFlags.hubAddress); err != nil { @@ -295,14 +298,7 @@ func CallDeploy(_ []string, flags DeployFlags) error { } fmt.Println(hubAddress) - fmt.Printf("%#v\n", flags.hubFlags) - return nil - prompt := "Where should the token be bridged as an ERC-20?" - if cancel, err := promptChain(prompt, network, flags.hubFlags.chainFlags.CChain, flags.hubFlags.chainFlags.SubnetName, &flags.spokeFlags); err != nil { - return err - } else if cancel { - return nil - } + return nil } From c1ab45cf3a27fa6c3c4626bcc99322c8c49f75cb Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Sun, 9 Jun 2024 08:08:24 -0300 Subject: [PATCH 35/87] if given hub, get erc20 address from hub, then token details from erc20 --- cmd/teleportercmd/bridgecmd/deploy.go | 180 +++++++++++-------------- cmd/teleportercmd/bridgecmd/helpers.go | 107 +++++++++++++++ 2 files changed, 186 insertions(+), 101 deletions(-) diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index a86fff1e9..f02cea457 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -5,8 +5,8 @@ package bridgecmd import ( _ "embed" "fmt" - "strings" + cmdflags "github.com/ava-labs/avalanche-cli/cmd/flags" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" "github.com/ava-labs/avalanche-cli/pkg/key" "github.com/ava-labs/avalanche-cli/pkg/models" @@ -15,7 +15,6 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/subnet" "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" - "github.com/ava-labs/avalanchego/ids" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" "github.com/liyue201/erc20-go/erc20" @@ -87,6 +86,13 @@ func CallDeploy(_ []string, flags DeployFlags) error { if err != nil { return err } + + // flags exclusiveness + if !cmdflags.EnsureMutuallyExclusive([]bool{flags.hubFlags.chainFlags.SubnetName != "", flags.hubFlags.chainFlags.CChain}) { + return fmt.Errorf("--hub-subnet and --c-chain-hub are mutually exclusive flags") + } + + // Hub Chain Prompts if flags.hubFlags.chainFlags.SubnetName == "" && !flags.hubFlags.chainFlags.CChain { prompt := "Where is the Token origin?" if cancel, err := promptChain(prompt, network, false, "", &flags.hubFlags.chainFlags); err != nil { @@ -95,19 +101,23 @@ func CallDeploy(_ []string, flags DeployFlags) error { return nil } } + + // Hub Chain Validations if flags.hubFlags.chainFlags.SubnetName != "" { if err := validateSubnet(network, flags.hubFlags.chainFlags.SubnetName); err != nil { return err } } + + // Hub Contract Prompts if flags.hubFlags.hubAddress == "" && flags.hubFlags.erc20Address == "" && !flags.hubFlags.native { - tokenSymbol := "AVAX" + nativeTokenSymbol := "AVAX" if !flags.hubFlags.chainFlags.CChain { sc, err := app.LoadSidecar(flags.hubFlags.chainFlags.SubnetName) if err != nil { return err } - tokenSymbol = sc.TokenSymbol + nativeTokenSymbol = sc.TokenSymbol } prompt := "What kind of token do you want to bridge?" popularOption := "A popular token (e.g. AVAX, USDC, WAVAX, ...)" @@ -168,7 +178,7 @@ func CallDeploy(_ []string, flags DeployFlags) error { } flags.hubFlags.hubAddress = addr.Hex() case deployNewHubOption: - nativeOption := "The native token " + tokenSymbol + nativeOption := "The native token " + nativeTokenSymbol erc20Option := "An ERC-20 token" options := []string{nativeOption, erc20Option} option, err := app.Prompt.CaptureList( @@ -212,6 +222,19 @@ func CallDeploy(_ []string, flags DeployFlags) error { } } + // Hub Contract Validations + if flags.hubFlags.hubAddress != "" { + if err := prompts.ValidateAddress(flags.hubFlags.hubAddress); err != nil { + return fmt.Errorf("failure validating %s: %w", flags.hubFlags.hubAddress, err) + } + } + if flags.hubFlags.erc20Address != "" { + if err := prompts.ValidateAddress(flags.hubFlags.erc20Address); err != nil { + return fmt.Errorf("failure validating %s: %w", flags.hubFlags.erc20Address, err) + } + } + + // Spoke Chain Prompts if !flags.spokeFlags.CChain && flags.spokeFlags.SubnetName == "" { prompt := "Where should the token be bridged as an ERC-20?" if cancel, err := promptChain(prompt, network, flags.hubFlags.chainFlags.CChain, flags.hubFlags.chainFlags.SubnetName, &flags.spokeFlags); err != nil { @@ -221,58 +244,80 @@ func CallDeploy(_ []string, flags DeployFlags) error { } } - var hubAddress common.Address - if flags.hubFlags.hubAddress != "" { - if err := prompts.ValidateAddress(flags.hubFlags.hubAddress); err != nil { - return fmt.Errorf("failure validating %s: %w", flags.hubFlags.hubAddress, err) + // Spoke Chain Validations + if flags.spokeFlags.SubnetName != "" { + if err := validateSubnet(network, flags.spokeFlags.SubnetName); err != nil { + return err + } + if flags.spokeFlags.SubnetName == flags.hubFlags.chainFlags.SubnetName { + return fmt.Errorf("trying to make a bridge were hub and spoke are on the same subnet") } - hubAddress = common.HexToAddress(flags.hubFlags.hubAddress) } - if flags.hubFlags.erc20Address != "" { - if err := prompts.ValidateAddress(flags.hubFlags.erc20Address); err != nil { - return fmt.Errorf("failure validating %s: %w", flags.hubFlags.erc20Address, err) + if flags.spokeFlags.CChain && flags.hubFlags.chainFlags.CChain { + return fmt.Errorf("trying to make a bridge were hub and spoke are on the same subnet") + } + + // Hub Deploy + bridgeSrcDir := utils.ExpandHome("~/Workspace/projects/teleporter-token-bridge/") + var ( + hubAddress common.Address + tokenDecimals uint8 + tokenName string + tokenSymbol string + erc20TokenAddress common.Address + ) + hubEndpoint := network.CChainEndpoint() + if flags.hubFlags.chainFlags.SubnetName != "" { + sc, err := app.LoadSidecar(flags.hubFlags.chainFlags.SubnetName) + if err != nil { + return err } - hubEndpoint := network.CChainEndpoint() - if flags.hubFlags.chainFlags.SubnetName != "" { - sc, err := app.LoadSidecar(flags.hubFlags.chainFlags.SubnetName) - if err != nil { - return err - } - blockchainID := sc.Networks[network.Name()].BlockchainID - hubEndpoint = network.BlockchainEndpoint(blockchainID.String()) + blockchainID := sc.Networks[network.Name()].BlockchainID + hubEndpoint = network.BlockchainEndpoint(blockchainID.String()) + } + if flags.hubFlags.hubAddress != "" { + hubAddress = common.HexToAddress(flags.hubFlags.hubAddress) + address, err := getHubERC20Address(bridgeSrcDir, hubEndpoint, hubAddress) + if err != nil { + return err } + flags.hubFlags.erc20Address = address.Hex() + } + if flags.hubFlags.erc20Address != "" { + erc20TokenAddress = common.HexToAddress(flags.hubFlags.erc20Address) client, err := ethclient.Dial(hubEndpoint) if err != nil { return err } - erc20TokenAddress := common.HexToAddress(flags.hubFlags.erc20Address) token, err := erc20.NewGGToken(erc20TokenAddress, client) if err != nil { return err } - if _, err := token.Name(nil); err != nil { + if tokenName, err = token.Name(nil); err != nil { + return err + } + if tokenSymbol, err = token.Symbol(nil); err != nil { return err } // TODO: find out if there are decimals options and why (academy) - decimals, err := token.Decimals(nil) + tokenDecimals, err = token.Decimals(nil) if err != nil { return err } - bridgeSrcDir := utils.ExpandHome("~/Workspace/projects/teleporter-token-bridge/") - + } + if flags.hubFlags.erc20Address != "" && flags.hubFlags.hubAddress == "" { // TODO: need registry address, manager address, private key for the hub chain (academy for fuji) teleporterRegistryAddress := "" teleporterManagerAddress := "" privateKey := "" - if network.Kind == models.Local { if flags.hubFlags.chainFlags.CChain { if b, extraLocalNetworkData, err := subnet.GetExtraLocalNetworkData(); err != nil { return err - } else if b { - teleporterRegistryAddress = extraLocalNetworkData.CChainTeleporterRegistryAddress - } else { + } else if !b { return fmt.Errorf("could not find teleporter registry address on local network C-Chain") + } else { + teleporterRegistryAddress = extraLocalNetworkData.CChainTeleporterRegistryAddress } k, err := key.LoadEwoq(network.ID) if err != nil { @@ -282,7 +327,6 @@ func CallDeploy(_ []string, flags DeployFlags) error { privateKey = k.PrivKeyHex() } } - hubAddress, err = deployERC20Hub( bridgeSrcDir, hubEndpoint, @@ -290,7 +334,7 @@ func CallDeploy(_ []string, flags DeployFlags) error { common.HexToAddress(teleporterRegistryAddress), common.HexToAddress(teleporterManagerAddress), erc20TokenAddress, - decimals, + tokenDecimals, ) if err != nil { return err @@ -298,75 +342,9 @@ func CallDeploy(_ []string, flags DeployFlags) error { } fmt.Println(hubAddress) + fmt.Println(tokenDecimals) + fmt.Println(tokenName) + fmt.Println(tokenSymbol) return nil } - -func filterSubnetsByNetwork(network models.Network, subnetNames []string) ([]string, error) { - filtered := []string{} - for _, subnetName := range subnetNames { - sc, err := app.LoadSidecar(subnetName) - if err != nil { - return nil, err - } - if sc.Networks[network.Name()].BlockchainID != ids.Empty { - filtered = append(filtered, subnetName) - } - } - return filtered, nil -} - -func validateSubnet(network models.Network, subnetName string) error { - sc, err := app.LoadSidecar(subnetName) - if err != nil { - return err - } - if sc.Networks[network.Name()].BlockchainID == ids.Empty { - return fmt.Errorf("subnet %s not deployed into %s", subnetName, network.Name()) - } - return nil -} - -func promptChain( - prompt string, - network models.Network, - avoidCChain bool, - avoidSubnet string, - chainFlags *ChainFlags, -) (bool, error) { - subnetNames, err := app.GetSubnetNames() - if err != nil { - return false, err - } - subnetNames, err = filterSubnetsByNetwork(network, subnetNames) - if err != nil { - return false, err - } - subnetNames = utils.RemoveFromSlice(subnetNames, avoidSubnet) - cChainOption := "C-Chain" - notListedOption := "My blockchain isn't listed" - subnetOptions := []string{} - if !avoidCChain { - subnetOptions = append(subnetOptions, cChainOption) - } - subnetOptions = append(subnetOptions, utils.Map(subnetNames, func(s string) string { return "Subnet " + s })...) - subnetOptions = append(subnetOptions, notListedOption) - subnetOption, err := app.Prompt.CaptureListWithSize( - prompt, - subnetOptions, - 11, - ) - if err != nil { - return false, err - } - if subnetOption == notListedOption { - ux.Logger.PrintToUser("Please import the subnet first, using the `avalanche subnet import` command suite") - return true, nil - } - if subnetOption == cChainOption { - chainFlags.CChain = true - } else { - chainFlags.SubnetName = strings.TrimPrefix(subnetOption, "Subnet ") - } - return false, nil -} diff --git a/cmd/teleportercmd/bridgecmd/helpers.go b/cmd/teleportercmd/bridgecmd/helpers.go index 950730ccd..994b227c4 100644 --- a/cmd/teleportercmd/bridgecmd/helpers.go +++ b/cmd/teleportercmd/bridgecmd/helpers.go @@ -7,13 +7,51 @@ import ( "fmt" "os" "path/filepath" + "strings" "github.com/ava-labs/avalanche-cli/pkg/evm" + "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/utils" + "github.com/ava-labs/avalanche-cli/pkg/ux" + "github.com/ava-labs/avalanchego/ids" + subnetevmabi "github.com/ava-labs/subnet-evm/accounts/abi" "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" ) +func getHubERC20Address( + srcDir string, + rpcURL string, + address common.Address, +) (common.Address, error) { + srcDir = utils.ExpandHome(srcDir) + abiPath := filepath.Join(srcDir, "contracts/out/ERC20TokenHub.sol/ERC20TokenHub.abi.json") + abiBytes, err := os.ReadFile(abiPath) + if err != nil { + return common.Address{}, err + } + metadata := &bind.MetaData{ + ABI: string(abiBytes), + } + abi, err := metadata.GetAbi() + if err != nil { + return common.Address{}, err + } + client, err := evm.GetClient(rpcURL) + if err != nil { + return common.Address{}, err + } + defer client.Close() + contract := bind.NewBoundContract(address, *abi, client, client, client) + var out []interface{} + err = contract.Call(&bind.CallOpts{}, &out, "token") + if err != nil { + return common.Address{}, err + } + out0 := *subnetevmabi.ConvertType(out[0], new(common.Address)).(*common.Address) + return out0, nil +} + func deployERC20Hub( srcDir string, rpcURL string, @@ -168,3 +206,72 @@ func deployWrappedNativeToken( } return address, nil } + +func filterSubnetsByNetwork(network models.Network, subnetNames []string) ([]string, error) { + filtered := []string{} + for _, subnetName := range subnetNames { + sc, err := app.LoadSidecar(subnetName) + if err != nil { + return nil, err + } + if sc.Networks[network.Name()].BlockchainID != ids.Empty { + filtered = append(filtered, subnetName) + } + } + return filtered, nil +} + +func validateSubnet(network models.Network, subnetName string) error { + sc, err := app.LoadSidecar(subnetName) + if err != nil { + return err + } + if sc.Networks[network.Name()].BlockchainID == ids.Empty { + return fmt.Errorf("subnet %s not deployed into %s", subnetName, network.Name()) + } + return nil +} + +func promptChain( + prompt string, + network models.Network, + avoidCChain bool, + avoidSubnet string, + chainFlags *ChainFlags, +) (bool, error) { + subnetNames, err := app.GetSubnetNames() + if err != nil { + return false, err + } + subnetNames, err = filterSubnetsByNetwork(network, subnetNames) + if err != nil { + return false, err + } + subnetNames = utils.RemoveFromSlice(subnetNames, avoidSubnet) + cChainOption := "C-Chain" + notListedOption := "My blockchain isn't listed" + subnetOptions := []string{} + if !avoidCChain { + subnetOptions = append(subnetOptions, cChainOption) + } + subnetOptions = append(subnetOptions, utils.Map(subnetNames, func(s string) string { return "Subnet " + s })...) + subnetOptions = append(subnetOptions, notListedOption) + subnetOption, err := app.Prompt.CaptureListWithSize( + prompt, + subnetOptions, + 11, + ) + if err != nil { + return false, err + } + if subnetOption == notListedOption { + ux.Logger.PrintToUser("Please import the subnet first, using the `avalanche subnet import` command suite") + return true, nil + } + if subnetOption == cChainOption { + chainFlags.CChain = true + } else { + chainFlags.SubnetName = strings.TrimPrefix(subnetOption, "Subnet ") + } + return false, nil +} From aaaf23ca0facec4b300cd4848ce0cd5e562e7b16 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Sun, 9 Jun 2024 08:59:26 -0300 Subject: [PATCH 36/87] ready to deploy spoke --- cmd/teleportercmd/bridgecmd/helpers.go | 78 ++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/cmd/teleportercmd/bridgecmd/helpers.go b/cmd/teleportercmd/bridgecmd/helpers.go index 994b227c4..c2d1278a4 100644 --- a/cmd/teleportercmd/bridgecmd/helpers.go +++ b/cmd/teleportercmd/bridgecmd/helpers.go @@ -52,6 +52,84 @@ func getHubERC20Address( return out0, nil } +type TokenSpokeSettings struct { + TeleporterRegistryAddress common.Address + TeleporterManager common.Address + TokenHubBlockchainID [32]byte + TokenHubAddress common.Address + TokenHubDecimals uint8 +} + +func deployERC20Spoke( + srcDir string, + rpcURL string, + prefundedPrivateKey string, + teleporterRegistryAddress common.Address, + teleporterManagerAddress common.Address, + tokenHubBlockchainID [32]byte, + tokenHubAddress common.Address, + tokenName string, + tokenSymbol string, + tokenDecimals uint8, +) (common.Address, error) { + srcDir = utils.ExpandHome(srcDir) + abiPath := filepath.Join(srcDir, "contracts/out/ERC20TokenSpoke.sol/ERC20TokenSpoke.abi.json") + binPath := filepath.Join(srcDir, "contracts/out/ERC20TokenSpoke.sol/ERC20TokenSpoke.bin") + abiBytes, err := os.ReadFile(abiPath) + if err != nil { + return common.Address{}, err + } + binBytes, err := os.ReadFile(binPath) + if err != nil { + return common.Address{}, err + } + metadata := &bind.MetaData{ + ABI: string(abiBytes), + Bin: string(binBytes), + } + abi, err := metadata.GetAbi() + if err != nil { + return common.Address{}, err + } + bin := common.FromHex(metadata.Bin) + client, err := evm.GetClient(rpcURL) + if err != nil { + return common.Address{}, err + } + defer client.Close() + txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) + if err != nil { + return common.Address{}, err + } + tokenSpokeSettings := TokenSpokeSettings{ + TeleporterRegistryAddress: teleporterRegistryAddress, + TeleporterManager: teleporterManagerAddress, + TokenHubBlockchainID: tokenHubBlockchainID, + TokenHubAddress: tokenHubAddress, + // TODO: user case for hub having diff decimals + TokenHubDecimals: tokenDecimals, + } + address, tx, _, err := bind.DeployContract( + txOpts, + *abi, + bin, + client, + tokenSpokeSettings, + tokenName, + tokenSymbol, + tokenDecimals, + ) + if err != nil { + return common.Address{}, err + } + if _, success, err := evm.WaitForTransaction(client, tx); err != nil { + return common.Address{}, err + } else if !success { + return common.Address{}, fmt.Errorf("failed receipt status deploying contract") + } + return address, nil +} + func deployERC20Hub( srcDir string, rpcURL string, From 807353b7c3888e498553f01deff1b234bee0dac9 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 10 Jun 2024 08:52:08 -0300 Subject: [PATCH 37/87] add spoke deploy --- .../addSubnetToRelayerService.go | 5 +- cmd/teleportercmd/bridgecmd/deploy.go | 78 +++++++++---------- cmd/teleportercmd/bridgecmd/helpers.go | 73 +++++++++++++++++ cmd/teleportercmd/helpers.go | 71 ----------------- cmd/teleportercmd/msg.go | 13 +++- 5 files changed, 125 insertions(+), 115 deletions(-) diff --git a/cmd/teleportercmd/addSubnetToRelayerService.go b/cmd/teleportercmd/addSubnetToRelayerService.go index 18ce04f74..63f5259ce 100644 --- a/cmd/teleportercmd/addSubnetToRelayerService.go +++ b/cmd/teleportercmd/addSubnetToRelayerService.go @@ -6,6 +6,7 @@ import ( "os" "path/filepath" + "github.com/ava-labs/avalanche-cli/cmd/teleportercmd/bridgecmd" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" "github.com/ava-labs/avalanche-cli/pkg/constants" "github.com/ava-labs/avalanche-cli/pkg/networkoptions" @@ -62,7 +63,7 @@ func CallAddSubnetToRelayerService(subnetName string, flags AddSubnetToRelayerSe return err } - subnetID, chainID, messengerAddress, registryAddress, _, err := getSubnetParams(network, "c-chain") + _, subnetID, chainID, messengerAddress, registryAddress, _, err := bridgecmd.GetSubnetParams(network, "", true) if err != nil { return err } @@ -94,7 +95,7 @@ func CallAddSubnetToRelayerService(subnetName string, flags AddSubnetToRelayerSe return err } - subnetID, chainID, messengerAddress, registryAddress, _, err = getSubnetParams(network, subnetName) + _, subnetID, chainID, messengerAddress, registryAddress, _, err = bridgecmd.GetSubnetParams(network, subnetName, false) if err != nil { return err } diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index f02cea457..31e2dd786 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -8,11 +8,8 @@ import ( cmdflags "github.com/ava-labs/avalanche-cli/cmd/flags" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" - "github.com/ava-labs/avalanche-cli/pkg/key" - "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/networkoptions" "github.com/ava-labs/avalanche-cli/pkg/prompts" - "github.com/ava-labs/avalanche-cli/pkg/subnet" "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" "github.com/ethereum/go-ethereum/common" @@ -91,6 +88,16 @@ func CallDeploy(_ []string, flags DeployFlags) error { if !cmdflags.EnsureMutuallyExclusive([]bool{flags.hubFlags.chainFlags.SubnetName != "", flags.hubFlags.chainFlags.CChain}) { return fmt.Errorf("--hub-subnet and --c-chain-hub are mutually exclusive flags") } + if !cmdflags.EnsureMutuallyExclusive([]bool{ + flags.hubFlags.hubAddress != "", + flags.hubFlags.erc20Address != "", + flags.hubFlags.native, + }) { + return fmt.Errorf("--deploy-native-hub, --deploy-erc20-hub, and --use-hub are mutually exclusive flags") + } + if !cmdflags.EnsureMutuallyExclusive([]bool{flags.spokeFlags.SubnetName != "", flags.spokeFlags.CChain}) { + return fmt.Errorf("--spoke-subnet and --c-chain-spoke are mutually exclusive flags") + } // Hub Chain Prompts if flags.hubFlags.chainFlags.SubnetName == "" && !flags.hubFlags.chainFlags.CChain { @@ -266,15 +273,9 @@ func CallDeploy(_ []string, flags DeployFlags) error { tokenSymbol string erc20TokenAddress common.Address ) - hubEndpoint := network.CChainEndpoint() - if flags.hubFlags.chainFlags.SubnetName != "" { - sc, err := app.LoadSidecar(flags.hubFlags.chainFlags.SubnetName) - if err != nil { - return err - } - blockchainID := sc.Networks[network.Name()].BlockchainID - hubEndpoint = network.BlockchainEndpoint(blockchainID.String()) - } + // TODO: need registry address, manager address, private key for the hub chain (academy for fuji) + hubEndpoint, _, hubBlockchainID, _, hubRegistryAddress, hubKey, err := + GetSubnetParams(network, flags.hubFlags.chainFlags.SubnetName, flags.hubFlags.chainFlags.CChain) if flags.hubFlags.hubAddress != "" { hubAddress = common.HexToAddress(flags.hubFlags.hubAddress) address, err := getHubERC20Address(bridgeSrcDir, hubEndpoint, hubAddress) @@ -306,33 +307,12 @@ func CallDeploy(_ []string, flags DeployFlags) error { } } if flags.hubFlags.erc20Address != "" && flags.hubFlags.hubAddress == "" { - // TODO: need registry address, manager address, private key for the hub chain (academy for fuji) - teleporterRegistryAddress := "" - teleporterManagerAddress := "" - privateKey := "" - if network.Kind == models.Local { - if flags.hubFlags.chainFlags.CChain { - if b, extraLocalNetworkData, err := subnet.GetExtraLocalNetworkData(); err != nil { - return err - } else if !b { - return fmt.Errorf("could not find teleporter registry address on local network C-Chain") - } else { - teleporterRegistryAddress = extraLocalNetworkData.CChainTeleporterRegistryAddress - } - k, err := key.LoadEwoq(network.ID) - if err != nil { - return err - } - teleporterManagerAddress = k.C() - privateKey = k.PrivKeyHex() - } - } hubAddress, err = deployERC20Hub( bridgeSrcDir, hubEndpoint, - privateKey, - common.HexToAddress(teleporterRegistryAddress), - common.HexToAddress(teleporterManagerAddress), + hubKey.PrivKeyHex(), + common.HexToAddress(hubRegistryAddress), + common.HexToAddress(hubKey.C()), erc20TokenAddress, tokenDecimals, ) @@ -341,10 +321,28 @@ func CallDeploy(_ []string, flags DeployFlags) error { } } - fmt.Println(hubAddress) - fmt.Println(tokenDecimals) - fmt.Println(tokenName) - fmt.Println(tokenSymbol) + // Spoke Deploy + spokeEndpoint, _, _, _, spokeRegistryAddress, spokeKey, err := + GetSubnetParams(network, flags.spokeFlags.SubnetName, flags.spokeFlags.CChain) + + spokeAddress, err := deployERC20Spoke( + bridgeSrcDir, + spokeEndpoint, + spokeKey.PrivKeyHex(), + common.HexToAddress(spokeRegistryAddress), + common.HexToAddress(spokeKey.C()), + hubBlockchainID, + hubAddress, + tokenName, + tokenSymbol, + tokenDecimals, + ) + if err != nil { + return err + } + + ux.Logger.PrintToUser("Spoke Deployed!") + ux.Logger.PrintToUser("Spoke Address: %s", spokeAddress) return nil } diff --git a/cmd/teleportercmd/bridgecmd/helpers.go b/cmd/teleportercmd/bridgecmd/helpers.go index c2d1278a4..e84ba7eae 100644 --- a/cmd/teleportercmd/bridgecmd/helpers.go +++ b/cmd/teleportercmd/bridgecmd/helpers.go @@ -10,7 +10,9 @@ import ( "strings" "github.com/ava-labs/avalanche-cli/pkg/evm" + "github.com/ava-labs/avalanche-cli/pkg/key" "github.com/ava-labs/avalanche-cli/pkg/models" + "github.com/ava-labs/avalanche-cli/pkg/subnet" "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" "github.com/ava-labs/avalanchego/ids" @@ -353,3 +355,74 @@ func promptChain( } return false, nil } + +func GetSubnetParams( + network models.Network, + subnetName string, + isCChain bool, +) (string, ids.ID, ids.ID, string, string, *key.SoftKey, error) { + var ( + subnetID ids.ID + chainID ids.ID + err error + teleporterMessengerAddress string + teleporterRegistryAddress string + k *key.SoftKey + endpoint string + ) + if isCChain { + subnetID = ids.Empty + chainID, err = utils.GetChainID(network.Endpoint, "C") + if err != nil { + return "", ids.Empty, ids.Empty, "", "", nil, err + } + if network.Kind == models.Local { + b, extraLocalNetworkData, err := subnet.GetExtraLocalNetworkData() + if err != nil { + return "", ids.Empty, ids.Empty, "", "", nil, err + } + if !b { + return "", ids.Empty, ids.Empty, "", "", nil, fmt.Errorf("no extra local network data available") + } + teleporterMessengerAddress = extraLocalNetworkData.CChainTeleporterMessengerAddress + teleporterRegistryAddress = extraLocalNetworkData.CChainTeleporterRegistryAddress + } else if network.ClusterName != "" { + clusterConfig, err := app.GetClusterConfig(network.ClusterName) + if err != nil { + return "", ids.Empty, ids.Empty, "", "", nil, err + } + teleporterMessengerAddress = clusterConfig.ExtraNetworkData.CChainTeleporterMessengerAddress + teleporterRegistryAddress = clusterConfig.ExtraNetworkData.CChainTeleporterRegistryAddress + } + k, err = key.LoadEwoq(network.ID) + if err != nil { + return "", ids.Empty, ids.Empty, "", "", nil, err + } + endpoint = network.CChainEndpoint() + } else { + sc, err := app.LoadSidecar(subnetName) + if err != nil { + return "", ids.Empty, ids.Empty, "", "", nil, err + } + if !sc.TeleporterReady { + return "", ids.Empty, ids.Empty, "", "", nil, fmt.Errorf("subnet %s is not enabled for teleporter", subnetName) + } + subnetID = sc.Networks[network.Name()].SubnetID + chainID = sc.Networks[network.Name()].BlockchainID + teleporterMessengerAddress = sc.Networks[network.Name()].TeleporterMessengerAddress + teleporterRegistryAddress = sc.Networks[network.Name()].TeleporterRegistryAddress + keyPath := app.GetKeyPath(sc.TeleporterKey) + k, err = key.LoadSoft(network.ID, keyPath) + if err != nil { + return "", ids.Empty, ids.Empty, "", "", nil, err + } + endpoint = network.BlockchainEndpoint(chainID.String()) + } + if chainID == ids.Empty { + return "", ids.Empty, ids.Empty, "", "", nil, fmt.Errorf("chainID for subnet %s not found on network %s", subnetName, network.Name()) + } + if teleporterMessengerAddress == "" { + return "", ids.Empty, ids.Empty, "", "", nil, fmt.Errorf("teleporter messenger address for subnet %s not found on network %s", subnetName, network.Name()) + } + return endpoint, subnetID, chainID, teleporterMessengerAddress, teleporterRegistryAddress, k, nil +} diff --git a/cmd/teleportercmd/helpers.go b/cmd/teleportercmd/helpers.go index 985d42420..5da74f259 100644 --- a/cmd/teleportercmd/helpers.go +++ b/cmd/teleportercmd/helpers.go @@ -3,80 +3,9 @@ package teleportercmd import ( - "fmt" "strings" - - "github.com/ava-labs/avalanche-cli/pkg/key" - "github.com/ava-labs/avalanche-cli/pkg/models" - "github.com/ava-labs/avalanche-cli/pkg/subnet" - "github.com/ava-labs/avalanche-cli/pkg/utils" - "github.com/ava-labs/avalanchego/ids" ) -func getSubnetParams(network models.Network, subnetName string) (ids.ID, ids.ID, string, string, *key.SoftKey, error) { - var ( - subnetID ids.ID - chainID ids.ID - err error - teleporterMessengerAddress string - teleporterRegistryAddress string - k *key.SoftKey - ) - if isCChain(subnetName) { - subnetID = ids.Empty - chainID, err = utils.GetChainID(network.Endpoint, "C") - if err != nil { - return ids.Empty, ids.Empty, "", "", nil, err - } - if network.Kind == models.Local { - b, extraLocalNetworkData, err := subnet.GetExtraLocalNetworkData() - if err != nil { - return ids.Empty, ids.Empty, "", "", nil, err - } - if !b { - return ids.Empty, ids.Empty, "", "", nil, fmt.Errorf("no extra local network data available") - } - teleporterMessengerAddress = extraLocalNetworkData.CChainTeleporterMessengerAddress - teleporterRegistryAddress = extraLocalNetworkData.CChainTeleporterRegistryAddress - } else if network.ClusterName != "" { - clusterConfig, err := app.GetClusterConfig(network.ClusterName) - if err != nil { - return ids.Empty, ids.Empty, "", "", nil, err - } - teleporterMessengerAddress = clusterConfig.ExtraNetworkData.CChainTeleporterMessengerAddress - teleporterRegistryAddress = clusterConfig.ExtraNetworkData.CChainTeleporterRegistryAddress - } - k, err = key.LoadEwoq(network.ID) - if err != nil { - return ids.Empty, ids.Empty, "", "", nil, err - } - } else { - sc, err := app.LoadSidecar(subnetName) - if err != nil { - return ids.Empty, ids.Empty, "", "", nil, err - } - if !sc.TeleporterReady { - return ids.Empty, ids.Empty, "", "", nil, fmt.Errorf("subnet %s is not enabled for teleporter", subnetName) - } - subnetID = sc.Networks[network.Name()].SubnetID - chainID = sc.Networks[network.Name()].BlockchainID - teleporterMessengerAddress = sc.Networks[network.Name()].TeleporterMessengerAddress - teleporterRegistryAddress = sc.Networks[network.Name()].TeleporterRegistryAddress - keyPath := app.GetKeyPath(sc.TeleporterKey) - k, err = key.LoadSoft(network.ID, keyPath) - if err != nil { - return ids.Empty, ids.Empty, "", "", nil, err - } - } - if chainID == ids.Empty { - return ids.Empty, ids.Empty, "", "", nil, fmt.Errorf("chainID for subnet %s not found on network %s", subnetName, network.Name()) - } - if teleporterMessengerAddress == "" { - return ids.Empty, ids.Empty, "", "", nil, fmt.Errorf("teleporter messenger address for subnet %s not found on network %s", subnetName, network.Name()) - } - return subnetID, chainID, teleporterMessengerAddress, teleporterRegistryAddress, k, nil -} - func isCChain(subnetName string) bool { return strings.ToLower(subnetName) == "c-chain" || strings.ToLower(subnetName) == "cchain" } diff --git a/cmd/teleportercmd/msg.go b/cmd/teleportercmd/msg.go index 81d516e5d..840977f0f 100644 --- a/cmd/teleportercmd/msg.go +++ b/cmd/teleportercmd/msg.go @@ -9,6 +9,7 @@ import ( "math/big" "time" + "github.com/ava-labs/avalanche-cli/cmd/teleportercmd/bridgecmd" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" "github.com/ava-labs/avalanche-cli/pkg/evm" "github.com/ava-labs/avalanche-cli/pkg/networkoptions" @@ -64,11 +65,19 @@ func msg(_ *cobra.Command, args []string) error { return err } - _, sourceChainID, sourceMessengerAddress, _, sourceKey, err := getSubnetParams(network, sourceSubnetName) + _, _, sourceChainID, sourceMessengerAddress, _, sourceKey, err := bridgecmd.GetSubnetParams( + network, + sourceSubnetName, + isCChain(sourceSubnetName), + ) if err != nil { return err } - _, destChainID, destMessengerAddress, _, _, err := getSubnetParams(network, destSubnetName) + _, _, destChainID, destMessengerAddress, _, _, err := bridgecmd.GetSubnetParams( + network, + destSubnetName, + isCChain(destSubnetName), + ) if err != nil { return err } From 45967476696487b54377e4d1794b8e92960df1e1 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 10 Jun 2024 08:55:44 -0300 Subject: [PATCH 38/87] nit --- cmd/teleportercmd/bridgecmd/deploy.go | 22 ++++++++++++++++++---- pkg/subnet/local.go | 1 - 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index 31e2dd786..6d6e38d8a 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -274,8 +274,14 @@ func CallDeploy(_ []string, flags DeployFlags) error { erc20TokenAddress common.Address ) // TODO: need registry address, manager address, private key for the hub chain (academy for fuji) - hubEndpoint, _, hubBlockchainID, _, hubRegistryAddress, hubKey, err := - GetSubnetParams(network, flags.hubFlags.chainFlags.SubnetName, flags.hubFlags.chainFlags.CChain) + hubEndpoint, _, hubBlockchainID, _, hubRegistryAddress, hubKey, err := GetSubnetParams( + network, + flags.hubFlags.chainFlags.SubnetName, + flags.hubFlags.chainFlags.CChain, + ) + if err != nil { + return err + } if flags.hubFlags.hubAddress != "" { hubAddress = common.HexToAddress(flags.hubFlags.hubAddress) address, err := getHubERC20Address(bridgeSrcDir, hubEndpoint, hubAddress) @@ -319,11 +325,19 @@ func CallDeploy(_ []string, flags DeployFlags) error { if err != nil { return err } + ux.Logger.PrintToUser("Hub Deployed!") + ux.Logger.PrintToUser("Hub Address: %s", hubAddress) } // Spoke Deploy - spokeEndpoint, _, _, _, spokeRegistryAddress, spokeKey, err := - GetSubnetParams(network, flags.spokeFlags.SubnetName, flags.spokeFlags.CChain) + spokeEndpoint, _, _, _, spokeRegistryAddress, spokeKey, err := GetSubnetParams( + network, + flags.spokeFlags.SubnetName, + flags.spokeFlags.CChain, + ) + if err != nil { + return err + } spokeAddress, err := deployERC20Spoke( bridgeSrcDir, diff --git a/pkg/subnet/local.go b/pkg/subnet/local.go index 1251a043c..eb9c9afb9 100644 --- a/pkg/subnet/local.go +++ b/pkg/subnet/local.go @@ -1175,7 +1175,6 @@ func GetExtraLocalNetworkData() (bool, ExtraLocalNetworkData, error) { return false, extraLocalNetworkData, err } extraLocalNetworkDataPath := filepath.Join(clusterInfo.GetRootDataDir(), constants.ExtraLocalNetworkDataFilename) - fmt.Println(extraLocalNetworkDataPath) if !utils.FileExists(extraLocalNetworkDataPath) { return false, extraLocalNetworkData, nil } From 9b025d171165c2f33c6432b582be1b7c00b5f7d2 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 10 Jun 2024 09:08:07 -0300 Subject: [PATCH 39/87] nits --- cmd/keycmd/list.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/keycmd/list.go b/cmd/keycmd/list.go index bb414be42..7094ea690 100644 --- a/cmd/keycmd/list.go +++ b/cmd/keycmd/list.go @@ -481,7 +481,7 @@ func getEvmBasedChainAddrInfo( kind string, name string, ) ([]addressInfo, error) { - cChainBalance, err := getCChainBalanceStr(network, cClients[network], cChainAddr) + cChainBalance, err := getCChainBalanceStr(cClients[network], cChainAddr) if err != nil { // just ignore local network errors if network.Kind != models.Local { @@ -491,7 +491,7 @@ func getEvmBasedChainAddrInfo( info := addressInfo{ kind: kind, name: name, - chain: fmt.Sprintf("%s", chainName), + chain: chainName, token: chainToken, address: cChainAddr, balance: cChainBalance, @@ -518,7 +518,7 @@ func getEvmBasedChainAddrInfo( info := addressInfo{ kind: kind, name: name, - chain: fmt.Sprintf("%s", chainName), + chain: chainName, token: tokenName, address: cChainAddr, balance: formattedBalance, @@ -551,7 +551,7 @@ func printAddrInfos(addrInfos []addressInfo) { table.Render() } -func getCChainBalanceStr(network models.Network, cClient ethclient.Client, addrStr string) (string, error) { +func getCChainBalanceStr(cClient ethclient.Client, addrStr string) (string, error) { addr := common.HexToAddress(addrStr) ctx, cancel := utils.GetAPIContext() balance, err := cClient.BalanceAt(ctx, addr, nil) From 68aefe064c9192b5c353c3824d13b9cab1b097af Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 10 Jun 2024 09:28:57 -0300 Subject: [PATCH 40/87] add registration --- cmd/teleportercmd/bridgecmd/deploy.go | 9 +++++ cmd/teleportercmd/bridgecmd/helpers.go | 50 ++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index 6d6e38d8a..87d67b4c8 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -355,6 +355,15 @@ func CallDeploy(_ []string, flags DeployFlags) error { return err } + if err := registerERC20Spoke( + bridgeSrcDir, + spokeEndpoint, + spokeKey.PrivKeyHex(), + spokeAddress, + ); err != nil { + return err + } + ux.Logger.PrintToUser("Spoke Deployed!") ux.Logger.PrintToUser("Spoke Address: %s", spokeAddress) diff --git a/cmd/teleportercmd/bridgecmd/helpers.go b/cmd/teleportercmd/bridgecmd/helpers.go index e84ba7eae..96517da67 100644 --- a/cmd/teleportercmd/bridgecmd/helpers.go +++ b/cmd/teleportercmd/bridgecmd/helpers.go @@ -5,6 +5,7 @@ package bridgecmd import ( _ "embed" "fmt" + "math/big" "os" "path/filepath" "strings" @@ -54,6 +55,55 @@ func getHubERC20Address( return out0, nil } +type TeleporterFeeInfo struct { + FeeTokenAddress common.Address + Amount *big.Int +} + +func registerERC20Spoke( + srcDir string, + rpcURL string, + prefundedPrivateKey string, + address common.Address, +) error { + srcDir = utils.ExpandHome(srcDir) + abiPath := filepath.Join(srcDir, "contracts/out/ERC20TokenSpoke.sol/ERC20TokenSpoke.abi.json") + abiBytes, err := os.ReadFile(abiPath) + if err != nil { + return err + } + metadata := &bind.MetaData{ + ABI: string(abiBytes), + } + abi, err := metadata.GetAbi() + if err != nil { + return err + } + client, err := evm.GetClient(rpcURL) + if err != nil { + return err + } + defer client.Close() + txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) + if err != nil { + return err + } + feeInfo := TeleporterFeeInfo{ + Amount: big.NewInt(0), + } + contract := bind.NewBoundContract(address, *abi, client, client, client) + tx, err := contract.Transact(txOpts, "registerWithHub", feeInfo) + if err != nil { + return err + } + if _, success, err := evm.WaitForTransaction(client, tx); err != nil { + return err + } else if !success { + return fmt.Errorf("failed receipt status deploying contract") + } + return nil +} + type TokenSpokeSettings struct { TeleporterRegistryAddress common.Address TeleporterManager common.Address From 30806b343809817311456ee19fc9ea9a006f86fd Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 10 Jun 2024 12:45:14 -0300 Subject: [PATCH 41/87] added hub deploy for native tokens --- cmd/teleportercmd/bridgecmd/deploy.go | 84 ++++++++++++++++++-------- cmd/teleportercmd/bridgecmd/helpers.go | 58 ++++++++++++++++-- 2 files changed, 111 insertions(+), 31 deletions(-) diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index 87d67b4c8..fa5eeafa6 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -13,8 +13,6 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/liyue201/erc20-go/erc20" "github.com/spf13/cobra" ) @@ -118,13 +116,12 @@ func CallDeploy(_ []string, flags DeployFlags) error { // Hub Contract Prompts if flags.hubFlags.hubAddress == "" && flags.hubFlags.erc20Address == "" && !flags.hubFlags.native { - nativeTokenSymbol := "AVAX" - if !flags.hubFlags.chainFlags.CChain { - sc, err := app.LoadSidecar(flags.hubFlags.chainFlags.SubnetName) - if err != nil { - return err - } - nativeTokenSymbol = sc.TokenSymbol + nativeTokenSymbol, err := getNativeTokenSymbol( + flags.hubFlags.chainFlags.SubnetName, + flags.hubFlags.chainFlags.CChain, + ) + if err != nil { + return err } prompt := "What kind of token do you want to bridge?" popularOption := "A popular token (e.g. AVAX, USDC, WAVAX, ...)" @@ -268,9 +265,9 @@ func CallDeploy(_ []string, flags DeployFlags) error { bridgeSrcDir := utils.ExpandHome("~/Workspace/projects/teleporter-token-bridge/") var ( hubAddress common.Address - tokenDecimals uint8 - tokenName string tokenSymbol string + tokenName string + tokenDecimals uint8 erc20TokenAddress common.Address ) // TODO: need registry address, manager address, private key for the hub chain (academy for fuji) @@ -284,49 +281,84 @@ func CallDeploy(_ []string, flags DeployFlags) error { } if flags.hubFlags.hubAddress != "" { hubAddress = common.HexToAddress(flags.hubFlags.hubAddress) - address, err := getHubERC20Address(bridgeSrcDir, hubEndpoint, hubAddress) + erc20TokenAddress, err = getHubERC20Address(bridgeSrcDir, hubEndpoint, hubAddress) + if err != nil { + return err + } + tokenSymbol, tokenName, tokenDecimals, err = getTokenParams( + hubEndpoint, + erc20TokenAddress.Hex(), + ) if err != nil { return err } - flags.hubFlags.erc20Address = address.Hex() } if flags.hubFlags.erc20Address != "" { erc20TokenAddress = common.HexToAddress(flags.hubFlags.erc20Address) - client, err := ethclient.Dial(hubEndpoint) + tokenSymbol, tokenName, tokenDecimals, err = getTokenParams( + hubEndpoint, + erc20TokenAddress.Hex(), + ) if err != nil { return err } - token, err := erc20.NewGGToken(erc20TokenAddress, client) + hubAddress, err = deployERC20Hub( + bridgeSrcDir, + hubEndpoint, + hubKey.PrivKeyHex(), + common.HexToAddress(hubRegistryAddress), + common.HexToAddress(hubKey.C()), + erc20TokenAddress, + tokenDecimals, + ) if err != nil { return err } - if tokenName, err = token.Name(nil); err != nil { + ux.Logger.PrintToUser("Hub Deployed to %s", hubEndpoint) + ux.Logger.PrintToUser("Hub Address: %s", hubAddress) + ux.Logger.PrintToUser("") + } + if flags.hubFlags.native { + nativeTokenSymbol, err := getNativeTokenSymbol( + flags.hubFlags.chainFlags.SubnetName, + flags.hubFlags.chainFlags.CChain, + ) + if err != nil { return err } - if tokenSymbol, err = token.Symbol(nil); err != nil { + wrappedNativeTokenAddress, err := deployWrappedNativeToken( + bridgeSrcDir, + hubEndpoint, + hubKey.PrivKeyHex(), + nativeTokenSymbol, + ) + if err != nil { return err } - // TODO: find out if there are decimals options and why (academy) - tokenDecimals, err = token.Decimals(nil) + tokenSymbol, tokenName, tokenDecimals, err = getTokenParams( + hubEndpoint, + wrappedNativeTokenAddress.Hex(), + ) if err != nil { return err } - } - if flags.hubFlags.erc20Address != "" && flags.hubFlags.hubAddress == "" { - hubAddress, err = deployERC20Hub( + ux.Logger.PrintToUser("Wrapped Native Token Deployed to %s", hubEndpoint) + ux.Logger.PrintToUser("%s Address: %s", tokenSymbol, wrappedNativeTokenAddress) + ux.Logger.PrintToUser("") + hubAddress, err = deployNativeHub( bridgeSrcDir, hubEndpoint, hubKey.PrivKeyHex(), common.HexToAddress(hubRegistryAddress), common.HexToAddress(hubKey.C()), - erc20TokenAddress, - tokenDecimals, + wrappedNativeTokenAddress, ) if err != nil { return err } - ux.Logger.PrintToUser("Hub Deployed!") + ux.Logger.PrintToUser("Hub Deployed to %s", hubEndpoint) ux.Logger.PrintToUser("Hub Address: %s", hubAddress) + ux.Logger.PrintToUser("") } // Spoke Deploy @@ -364,7 +396,7 @@ func CallDeploy(_ []string, flags DeployFlags) error { return err } - ux.Logger.PrintToUser("Spoke Deployed!") + ux.Logger.PrintToUser("Spoke Deployed to %s", spokeEndpoint) ux.Logger.PrintToUser("Spoke Address: %s", spokeAddress) return nil diff --git a/cmd/teleportercmd/bridgecmd/helpers.go b/cmd/teleportercmd/bridgecmd/helpers.go index 96517da67..af4f54b44 100644 --- a/cmd/teleportercmd/bridgecmd/helpers.go +++ b/cmd/teleportercmd/bridgecmd/helpers.go @@ -20,6 +20,8 @@ import ( subnetevmabi "github.com/ava-labs/subnet-evm/accounts/abi" "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/liyue201/erc20-go/erc20" ) func getHubERC20Address( @@ -250,8 +252,8 @@ func deployNativeHub( wrappedNativeTokenAddress common.Address, ) (common.Address, error) { srcDir = utils.ExpandHome(srcDir) - abiPath := filepath.Join(srcDir, "contracts/out/NativeTokenSource.sol/NativeTokenSource.abi.json") - binPath := filepath.Join(srcDir, "contracts/out/NativeTokenSource.sol/NativeTokenSource.bin") + abiPath := filepath.Join(srcDir, "contracts/out/NativeTokenHub.sol/NativeTokenHub.abi.json") + binPath := filepath.Join(srcDir, "contracts/out/NativeTokenHub.sol/NativeTokenHub.bin") abiBytes, err := os.ReadFile(abiPath) if err != nil { return common.Address{}, err @@ -278,7 +280,15 @@ func deployNativeHub( if err != nil { return common.Address{}, err } - address, tx, _, err := bind.DeployContract(txOpts, *abi, bin, client, teleporterRegistryAddress, teleporterManagerAddress, wrappedNativeTokenAddress) + address, tx, _, err := bind.DeployContract( + txOpts, + *abi, + bin, + client, + teleporterRegistryAddress, + teleporterManagerAddress, + wrappedNativeTokenAddress, + ) if err != nil { return common.Address{}, err } @@ -294,7 +304,7 @@ func deployWrappedNativeToken( srcDir string, rpcURL string, prefundedPrivateKey string, - tokenName string, + tokenSymbol string, ) (common.Address, error) { srcDir = utils.ExpandHome(srcDir) abiPath := filepath.Join(srcDir, "contracts/out/WrappedNativeToken.sol/WrappedNativeToken.abi.json") @@ -325,7 +335,7 @@ func deployWrappedNativeToken( if err != nil { return common.Address{}, err } - address, tx, _, err := bind.DeployContract(txOpts, *abi, bin, client, tokenName) + address, tx, _, err := bind.DeployContract(txOpts, *abi, bin, client, tokenSymbol) if err != nil { return common.Address{}, err } @@ -476,3 +486,41 @@ func GetSubnetParams( } return endpoint, subnetID, chainID, teleporterMessengerAddress, teleporterRegistryAddress, k, nil } + +func getNativeTokenSymbol(subnetName string, isCChain bool) (string, error) { + nativeTokenSymbol := "AVAX" + if !isCChain { + sc, err := app.LoadSidecar(subnetName) + if err != nil { + return "", err + } + nativeTokenSymbol = sc.TokenSymbol + } + return nativeTokenSymbol, nil +} + +func getTokenParams(endpoint string, tokenAddress string) (string, string, uint8, error) { + address := common.HexToAddress(tokenAddress) + client, err := ethclient.Dial(endpoint) + if err != nil { + return "", "", 0, err + } + token, err := erc20.NewGGToken(address, client) + if err != nil { + return "", "", 0, err + } + tokenName, err := token.Name(nil) + if err != nil { + return "", "", 0, err + } + tokenSymbol, err := token.Symbol(nil) + if err != nil { + return "", "", 0, err + } + // TODO: find out if there are decimals options and why (academy) + tokenDecimals, err := token.Decimals(nil) + if err != nil { + return "", "", 0, err + } + return tokenSymbol, tokenName, tokenDecimals, nil +} From 708603ccc5992d4245f230d00250f348866848df Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 10 Jun 2024 16:06:40 -0300 Subject: [PATCH 42/87] add contract indicator to key list --- cmd/keycmd/list.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/keycmd/list.go b/cmd/keycmd/list.go index 7094ea690..8dcf26659 100644 --- a/cmd/keycmd/list.go +++ b/cmd/keycmd/list.go @@ -501,12 +501,12 @@ func getEvmBasedChainAddrInfo( if cGethClients != nil && cGethClients[network] != nil { for _, tokenAddress := range tokenAddresses { token, err := erc20.NewGGToken(common.HexToAddress(tokenAddress), cGethClients[network]) + if err != nil { + return addressInfos, err + } + tokenName, err := token.Name(nil) if err == nil { // just ignore contract address access errors as those may depend on network - tokenName, err := token.Name(nil) - if err != nil { - return addressInfos, err - } balance, err := token.BalanceOf(nil, common.HexToAddress(cChainAddr)) if err != nil { return addressInfos, err @@ -519,7 +519,7 @@ func getEvmBasedChainAddrInfo( kind: kind, name: name, chain: chainName, - token: tokenName, + token: fmt.Sprintf("%s @%s..", tokenName, tokenAddress[:7]), address: cChainAddr, balance: formattedBalance, network: network.Name(), From ad86e26a5107b5efb0a1e93f770f5ee961370f25 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 10 Jun 2024 16:15:11 -0300 Subject: [PATCH 43/87] refactor into lib --- cmd/teleportercmd/bridgecmd/deploy.go | 19 +- cmd/teleportercmd/bridgecmd/helpers.go | 358 ------------------------ pkg/bridge/bridge.go | 368 +++++++++++++++++++++++++ 3 files changed, 378 insertions(+), 367 deletions(-) create mode 100644 pkg/bridge/bridge.go diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index fa5eeafa6..9db3955cd 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -7,6 +7,7 @@ import ( "fmt" cmdflags "github.com/ava-labs/avalanche-cli/cmd/flags" + "github.com/ava-labs/avalanche-cli/pkg/bridge" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" "github.com/ava-labs/avalanche-cli/pkg/networkoptions" "github.com/ava-labs/avalanche-cli/pkg/prompts" @@ -281,11 +282,11 @@ func CallDeploy(_ []string, flags DeployFlags) error { } if flags.hubFlags.hubAddress != "" { hubAddress = common.HexToAddress(flags.hubFlags.hubAddress) - erc20TokenAddress, err = getHubERC20Address(bridgeSrcDir, hubEndpoint, hubAddress) + erc20TokenAddress, err = bridge.GetHubERC20Address(bridgeSrcDir, hubEndpoint, hubAddress) if err != nil { return err } - tokenSymbol, tokenName, tokenDecimals, err = getTokenParams( + tokenSymbol, tokenName, tokenDecimals, err = bridge.GetTokenParams( hubEndpoint, erc20TokenAddress.Hex(), ) @@ -295,14 +296,14 @@ func CallDeploy(_ []string, flags DeployFlags) error { } if flags.hubFlags.erc20Address != "" { erc20TokenAddress = common.HexToAddress(flags.hubFlags.erc20Address) - tokenSymbol, tokenName, tokenDecimals, err = getTokenParams( + tokenSymbol, tokenName, tokenDecimals, err = bridge.GetTokenParams( hubEndpoint, erc20TokenAddress.Hex(), ) if err != nil { return err } - hubAddress, err = deployERC20Hub( + hubAddress, err = bridge.DeployERC20Hub( bridgeSrcDir, hubEndpoint, hubKey.PrivKeyHex(), @@ -326,7 +327,7 @@ func CallDeploy(_ []string, flags DeployFlags) error { if err != nil { return err } - wrappedNativeTokenAddress, err := deployWrappedNativeToken( + wrappedNativeTokenAddress, err := bridge.DeployWrappedNativeToken( bridgeSrcDir, hubEndpoint, hubKey.PrivKeyHex(), @@ -335,7 +336,7 @@ func CallDeploy(_ []string, flags DeployFlags) error { if err != nil { return err } - tokenSymbol, tokenName, tokenDecimals, err = getTokenParams( + tokenSymbol, tokenName, tokenDecimals, err = bridge.GetTokenParams( hubEndpoint, wrappedNativeTokenAddress.Hex(), ) @@ -345,7 +346,7 @@ func CallDeploy(_ []string, flags DeployFlags) error { ux.Logger.PrintToUser("Wrapped Native Token Deployed to %s", hubEndpoint) ux.Logger.PrintToUser("%s Address: %s", tokenSymbol, wrappedNativeTokenAddress) ux.Logger.PrintToUser("") - hubAddress, err = deployNativeHub( + hubAddress, err = bridge.DeployNativeHub( bridgeSrcDir, hubEndpoint, hubKey.PrivKeyHex(), @@ -371,7 +372,7 @@ func CallDeploy(_ []string, flags DeployFlags) error { return err } - spokeAddress, err := deployERC20Spoke( + spokeAddress, err := bridge.DeployERC20Spoke( bridgeSrcDir, spokeEndpoint, spokeKey.PrivKeyHex(), @@ -387,7 +388,7 @@ func CallDeploy(_ []string, flags DeployFlags) error { return err } - if err := registerERC20Spoke( + if err := bridge.RegisterERC20Spoke( bridgeSrcDir, spokeEndpoint, spokeKey.PrivKeyHex(), diff --git a/cmd/teleportercmd/bridgecmd/helpers.go b/cmd/teleportercmd/bridgecmd/helpers.go index af4f54b44..e36b0ab88 100644 --- a/cmd/teleportercmd/bridgecmd/helpers.go +++ b/cmd/teleportercmd/bridgecmd/helpers.go @@ -5,348 +5,16 @@ package bridgecmd import ( _ "embed" "fmt" - "math/big" - "os" - "path/filepath" "strings" - "github.com/ava-labs/avalanche-cli/pkg/evm" "github.com/ava-labs/avalanche-cli/pkg/key" "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/subnet" "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" "github.com/ava-labs/avalanchego/ids" - subnetevmabi "github.com/ava-labs/subnet-evm/accounts/abi" - "github.com/ava-labs/subnet-evm/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/liyue201/erc20-go/erc20" ) -func getHubERC20Address( - srcDir string, - rpcURL string, - address common.Address, -) (common.Address, error) { - srcDir = utils.ExpandHome(srcDir) - abiPath := filepath.Join(srcDir, "contracts/out/ERC20TokenHub.sol/ERC20TokenHub.abi.json") - abiBytes, err := os.ReadFile(abiPath) - if err != nil { - return common.Address{}, err - } - metadata := &bind.MetaData{ - ABI: string(abiBytes), - } - abi, err := metadata.GetAbi() - if err != nil { - return common.Address{}, err - } - client, err := evm.GetClient(rpcURL) - if err != nil { - return common.Address{}, err - } - defer client.Close() - contract := bind.NewBoundContract(address, *abi, client, client, client) - var out []interface{} - err = contract.Call(&bind.CallOpts{}, &out, "token") - if err != nil { - return common.Address{}, err - } - out0 := *subnetevmabi.ConvertType(out[0], new(common.Address)).(*common.Address) - return out0, nil -} - -type TeleporterFeeInfo struct { - FeeTokenAddress common.Address - Amount *big.Int -} - -func registerERC20Spoke( - srcDir string, - rpcURL string, - prefundedPrivateKey string, - address common.Address, -) error { - srcDir = utils.ExpandHome(srcDir) - abiPath := filepath.Join(srcDir, "contracts/out/ERC20TokenSpoke.sol/ERC20TokenSpoke.abi.json") - abiBytes, err := os.ReadFile(abiPath) - if err != nil { - return err - } - metadata := &bind.MetaData{ - ABI: string(abiBytes), - } - abi, err := metadata.GetAbi() - if err != nil { - return err - } - client, err := evm.GetClient(rpcURL) - if err != nil { - return err - } - defer client.Close() - txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) - if err != nil { - return err - } - feeInfo := TeleporterFeeInfo{ - Amount: big.NewInt(0), - } - contract := bind.NewBoundContract(address, *abi, client, client, client) - tx, err := contract.Transact(txOpts, "registerWithHub", feeInfo) - if err != nil { - return err - } - if _, success, err := evm.WaitForTransaction(client, tx); err != nil { - return err - } else if !success { - return fmt.Errorf("failed receipt status deploying contract") - } - return nil -} - -type TokenSpokeSettings struct { - TeleporterRegistryAddress common.Address - TeleporterManager common.Address - TokenHubBlockchainID [32]byte - TokenHubAddress common.Address - TokenHubDecimals uint8 -} - -func deployERC20Spoke( - srcDir string, - rpcURL string, - prefundedPrivateKey string, - teleporterRegistryAddress common.Address, - teleporterManagerAddress common.Address, - tokenHubBlockchainID [32]byte, - tokenHubAddress common.Address, - tokenName string, - tokenSymbol string, - tokenDecimals uint8, -) (common.Address, error) { - srcDir = utils.ExpandHome(srcDir) - abiPath := filepath.Join(srcDir, "contracts/out/ERC20TokenSpoke.sol/ERC20TokenSpoke.abi.json") - binPath := filepath.Join(srcDir, "contracts/out/ERC20TokenSpoke.sol/ERC20TokenSpoke.bin") - abiBytes, err := os.ReadFile(abiPath) - if err != nil { - return common.Address{}, err - } - binBytes, err := os.ReadFile(binPath) - if err != nil { - return common.Address{}, err - } - metadata := &bind.MetaData{ - ABI: string(abiBytes), - Bin: string(binBytes), - } - abi, err := metadata.GetAbi() - if err != nil { - return common.Address{}, err - } - bin := common.FromHex(metadata.Bin) - client, err := evm.GetClient(rpcURL) - if err != nil { - return common.Address{}, err - } - defer client.Close() - txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) - if err != nil { - return common.Address{}, err - } - tokenSpokeSettings := TokenSpokeSettings{ - TeleporterRegistryAddress: teleporterRegistryAddress, - TeleporterManager: teleporterManagerAddress, - TokenHubBlockchainID: tokenHubBlockchainID, - TokenHubAddress: tokenHubAddress, - // TODO: user case for hub having diff decimals - TokenHubDecimals: tokenDecimals, - } - address, tx, _, err := bind.DeployContract( - txOpts, - *abi, - bin, - client, - tokenSpokeSettings, - tokenName, - tokenSymbol, - tokenDecimals, - ) - if err != nil { - return common.Address{}, err - } - if _, success, err := evm.WaitForTransaction(client, tx); err != nil { - return common.Address{}, err - } else if !success { - return common.Address{}, fmt.Errorf("failed receipt status deploying contract") - } - return address, nil -} - -func deployERC20Hub( - srcDir string, - rpcURL string, - prefundedPrivateKey string, - teleporterRegistryAddress common.Address, - teleporterManagerAddress common.Address, - erc20TokenAddress common.Address, - erc20TokenDecimals uint8, -) (common.Address, error) { - srcDir = utils.ExpandHome(srcDir) - abiPath := filepath.Join(srcDir, "contracts/out/ERC20TokenHub.sol/ERC20TokenHub.abi.json") - binPath := filepath.Join(srcDir, "contracts/out/ERC20TokenHub.sol/ERC20TokenHub.bin") - abiBytes, err := os.ReadFile(abiPath) - if err != nil { - return common.Address{}, err - } - binBytes, err := os.ReadFile(binPath) - if err != nil { - return common.Address{}, err - } - metadata := &bind.MetaData{ - ABI: string(abiBytes), - Bin: string(binBytes), - } - abi, err := metadata.GetAbi() - if err != nil { - return common.Address{}, err - } - bin := common.FromHex(metadata.Bin) - client, err := evm.GetClient(rpcURL) - if err != nil { - return common.Address{}, err - } - defer client.Close() - txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) - if err != nil { - return common.Address{}, err - } - address, tx, _, err := bind.DeployContract( - txOpts, - *abi, - bin, - client, - teleporterRegistryAddress, - teleporterManagerAddress, - erc20TokenAddress, - erc20TokenDecimals, - ) - if err != nil { - return common.Address{}, err - } - if _, success, err := evm.WaitForTransaction(client, tx); err != nil { - return common.Address{}, err - } else if !success { - return common.Address{}, fmt.Errorf("failed receipt status deploying contract") - } - return address, nil -} - -func deployNativeHub( - srcDir string, - rpcURL string, - prefundedPrivateKey string, - teleporterRegistryAddress common.Address, - teleporterManagerAddress common.Address, - wrappedNativeTokenAddress common.Address, -) (common.Address, error) { - srcDir = utils.ExpandHome(srcDir) - abiPath := filepath.Join(srcDir, "contracts/out/NativeTokenHub.sol/NativeTokenHub.abi.json") - binPath := filepath.Join(srcDir, "contracts/out/NativeTokenHub.sol/NativeTokenHub.bin") - abiBytes, err := os.ReadFile(abiPath) - if err != nil { - return common.Address{}, err - } - binBytes, err := os.ReadFile(binPath) - if err != nil { - return common.Address{}, err - } - metadata := &bind.MetaData{ - ABI: string(abiBytes), - Bin: string(binBytes), - } - abi, err := metadata.GetAbi() - if err != nil { - return common.Address{}, err - } - bin := common.FromHex(metadata.Bin) - client, err := evm.GetClient(rpcURL) - if err != nil { - return common.Address{}, err - } - defer client.Close() - txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) - if err != nil { - return common.Address{}, err - } - address, tx, _, err := bind.DeployContract( - txOpts, - *abi, - bin, - client, - teleporterRegistryAddress, - teleporterManagerAddress, - wrappedNativeTokenAddress, - ) - if err != nil { - return common.Address{}, err - } - if _, success, err := evm.WaitForTransaction(client, tx); err != nil { - return common.Address{}, err - } else if !success { - return common.Address{}, fmt.Errorf("failed receipt status deploying contract") - } - return address, nil -} - -func deployWrappedNativeToken( - srcDir string, - rpcURL string, - prefundedPrivateKey string, - tokenSymbol string, -) (common.Address, error) { - srcDir = utils.ExpandHome(srcDir) - abiPath := filepath.Join(srcDir, "contracts/out/WrappedNativeToken.sol/WrappedNativeToken.abi.json") - binPath := filepath.Join(srcDir, "contracts/out/WrappedNativeToken.sol/WrappedNativeToken.bin") - abiBytes, err := os.ReadFile(abiPath) - if err != nil { - return common.Address{}, err - } - binBytes, err := os.ReadFile(binPath) - if err != nil { - return common.Address{}, err - } - metadata := &bind.MetaData{ - ABI: string(abiBytes), - Bin: string(binBytes), - } - abi, err := metadata.GetAbi() - if err != nil { - return common.Address{}, err - } - bin := common.FromHex(metadata.Bin) - client, err := evm.GetClient(rpcURL) - if err != nil { - return common.Address{}, err - } - defer client.Close() - txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) - if err != nil { - return common.Address{}, err - } - address, tx, _, err := bind.DeployContract(txOpts, *abi, bin, client, tokenSymbol) - if err != nil { - return common.Address{}, err - } - if _, success, err := evm.WaitForTransaction(client, tx); err != nil { - return common.Address{}, err - } else if !success { - return common.Address{}, fmt.Errorf("failed receipt status deploying contract") - } - return address, nil -} - func filterSubnetsByNetwork(network models.Network, subnetNames []string) ([]string, error) { filtered := []string{} for _, subnetName := range subnetNames { @@ -498,29 +166,3 @@ func getNativeTokenSymbol(subnetName string, isCChain bool) (string, error) { } return nativeTokenSymbol, nil } - -func getTokenParams(endpoint string, tokenAddress string) (string, string, uint8, error) { - address := common.HexToAddress(tokenAddress) - client, err := ethclient.Dial(endpoint) - if err != nil { - return "", "", 0, err - } - token, err := erc20.NewGGToken(address, client) - if err != nil { - return "", "", 0, err - } - tokenName, err := token.Name(nil) - if err != nil { - return "", "", 0, err - } - tokenSymbol, err := token.Symbol(nil) - if err != nil { - return "", "", 0, err - } - // TODO: find out if there are decimals options and why (academy) - tokenDecimals, err := token.Decimals(nil) - if err != nil { - return "", "", 0, err - } - return tokenSymbol, tokenName, tokenDecimals, nil -} diff --git a/pkg/bridge/bridge.go b/pkg/bridge/bridge.go new file mode 100644 index 000000000..512af156e --- /dev/null +++ b/pkg/bridge/bridge.go @@ -0,0 +1,368 @@ +// Copyright (C) 2022, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +package bridge + +import ( + _ "embed" + "fmt" + "math/big" + "os" + "path/filepath" + + "github.com/ava-labs/avalanche-cli/pkg/evm" + "github.com/ava-labs/avalanche-cli/pkg/utils" + subnetevmabi "github.com/ava-labs/subnet-evm/accounts/abi" + "github.com/ava-labs/subnet-evm/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/liyue201/erc20-go/erc20" +) + +func GetHubERC20Address( + srcDir string, + rpcURL string, + address common.Address, +) (common.Address, error) { + srcDir = utils.ExpandHome(srcDir) + abiPath := filepath.Join(srcDir, "contracts/out/ERC20TokenHub.sol/ERC20TokenHub.abi.json") + abiBytes, err := os.ReadFile(abiPath) + if err != nil { + return common.Address{}, err + } + metadata := &bind.MetaData{ + ABI: string(abiBytes), + } + abi, err := metadata.GetAbi() + if err != nil { + return common.Address{}, err + } + client, err := evm.GetClient(rpcURL) + if err != nil { + return common.Address{}, err + } + defer client.Close() + contract := bind.NewBoundContract(address, *abi, client, client, client) + var out []interface{} + err = contract.Call(&bind.CallOpts{}, &out, "token") + if err != nil { + return common.Address{}, err + } + out0 := *subnetevmabi.ConvertType(out[0], new(common.Address)).(*common.Address) + return out0, nil +} + +type TeleporterFeeInfo struct { + FeeTokenAddress common.Address + Amount *big.Int +} + +func RegisterERC20Spoke( + srcDir string, + rpcURL string, + prefundedPrivateKey string, + address common.Address, +) error { + srcDir = utils.ExpandHome(srcDir) + abiPath := filepath.Join(srcDir, "contracts/out/ERC20TokenSpoke.sol/ERC20TokenSpoke.abi.json") + abiBytes, err := os.ReadFile(abiPath) + if err != nil { + return err + } + metadata := &bind.MetaData{ + ABI: string(abiBytes), + } + abi, err := metadata.GetAbi() + if err != nil { + return err + } + client, err := evm.GetClient(rpcURL) + if err != nil { + return err + } + defer client.Close() + txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) + if err != nil { + return err + } + feeInfo := TeleporterFeeInfo{ + Amount: big.NewInt(0), + } + contract := bind.NewBoundContract(address, *abi, client, client, client) + tx, err := contract.Transact(txOpts, "registerWithHub", feeInfo) + if err != nil { + return err + } + if _, success, err := evm.WaitForTransaction(client, tx); err != nil { + return err + } else if !success { + return fmt.Errorf("failed receipt status deploying contract") + } + return nil +} + +type TokenSpokeSettings struct { + TeleporterRegistryAddress common.Address + TeleporterManager common.Address + TokenHubBlockchainID [32]byte + TokenHubAddress common.Address + TokenHubDecimals uint8 +} + +func DeployERC20Spoke( + srcDir string, + rpcURL string, + prefundedPrivateKey string, + teleporterRegistryAddress common.Address, + teleporterManagerAddress common.Address, + tokenHubBlockchainID [32]byte, + tokenHubAddress common.Address, + tokenName string, + tokenSymbol string, + tokenDecimals uint8, +) (common.Address, error) { + srcDir = utils.ExpandHome(srcDir) + abiPath := filepath.Join(srcDir, "contracts/out/ERC20TokenSpoke.sol/ERC20TokenSpoke.abi.json") + binPath := filepath.Join(srcDir, "contracts/out/ERC20TokenSpoke.sol/ERC20TokenSpoke.bin") + abiBytes, err := os.ReadFile(abiPath) + if err != nil { + return common.Address{}, err + } + binBytes, err := os.ReadFile(binPath) + if err != nil { + return common.Address{}, err + } + metadata := &bind.MetaData{ + ABI: string(abiBytes), + Bin: string(binBytes), + } + abi, err := metadata.GetAbi() + if err != nil { + return common.Address{}, err + } + bin := common.FromHex(metadata.Bin) + client, err := evm.GetClient(rpcURL) + if err != nil { + return common.Address{}, err + } + defer client.Close() + txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) + if err != nil { + return common.Address{}, err + } + tokenSpokeSettings := TokenSpokeSettings{ + TeleporterRegistryAddress: teleporterRegistryAddress, + TeleporterManager: teleporterManagerAddress, + TokenHubBlockchainID: tokenHubBlockchainID, + TokenHubAddress: tokenHubAddress, + // TODO: user case for hub having diff decimals + TokenHubDecimals: tokenDecimals, + } + address, tx, _, err := bind.DeployContract( + txOpts, + *abi, + bin, + client, + tokenSpokeSettings, + tokenName, + tokenSymbol, + tokenDecimals, + ) + if err != nil { + return common.Address{}, err + } + if _, success, err := evm.WaitForTransaction(client, tx); err != nil { + return common.Address{}, err + } else if !success { + return common.Address{}, fmt.Errorf("failed receipt status deploying contract") + } + return address, nil +} + +func DeployERC20Hub( + srcDir string, + rpcURL string, + prefundedPrivateKey string, + teleporterRegistryAddress common.Address, + teleporterManagerAddress common.Address, + erc20TokenAddress common.Address, + erc20TokenDecimals uint8, +) (common.Address, error) { + srcDir = utils.ExpandHome(srcDir) + abiPath := filepath.Join(srcDir, "contracts/out/ERC20TokenHub.sol/ERC20TokenHub.abi.json") + binPath := filepath.Join(srcDir, "contracts/out/ERC20TokenHub.sol/ERC20TokenHub.bin") + abiBytes, err := os.ReadFile(abiPath) + if err != nil { + return common.Address{}, err + } + binBytes, err := os.ReadFile(binPath) + if err != nil { + return common.Address{}, err + } + metadata := &bind.MetaData{ + ABI: string(abiBytes), + Bin: string(binBytes), + } + abi, err := metadata.GetAbi() + if err != nil { + return common.Address{}, err + } + bin := common.FromHex(metadata.Bin) + client, err := evm.GetClient(rpcURL) + if err != nil { + return common.Address{}, err + } + defer client.Close() + txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) + if err != nil { + return common.Address{}, err + } + address, tx, _, err := bind.DeployContract( + txOpts, + *abi, + bin, + client, + teleporterRegistryAddress, + teleporterManagerAddress, + erc20TokenAddress, + erc20TokenDecimals, + ) + if err != nil { + return common.Address{}, err + } + if _, success, err := evm.WaitForTransaction(client, tx); err != nil { + return common.Address{}, err + } else if !success { + return common.Address{}, fmt.Errorf("failed receipt status deploying contract") + } + return address, nil +} + +func DeployNativeHub( + srcDir string, + rpcURL string, + prefundedPrivateKey string, + teleporterRegistryAddress common.Address, + teleporterManagerAddress common.Address, + wrappedNativeTokenAddress common.Address, +) (common.Address, error) { + srcDir = utils.ExpandHome(srcDir) + abiPath := filepath.Join(srcDir, "contracts/out/NativeTokenHub.sol/NativeTokenHub.abi.json") + binPath := filepath.Join(srcDir, "contracts/out/NativeTokenHub.sol/NativeTokenHub.bin") + abiBytes, err := os.ReadFile(abiPath) + if err != nil { + return common.Address{}, err + } + binBytes, err := os.ReadFile(binPath) + if err != nil { + return common.Address{}, err + } + metadata := &bind.MetaData{ + ABI: string(abiBytes), + Bin: string(binBytes), + } + abi, err := metadata.GetAbi() + if err != nil { + return common.Address{}, err + } + bin := common.FromHex(metadata.Bin) + client, err := evm.GetClient(rpcURL) + if err != nil { + return common.Address{}, err + } + defer client.Close() + txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) + if err != nil { + return common.Address{}, err + } + address, tx, _, err := bind.DeployContract( + txOpts, + *abi, + bin, + client, + teleporterRegistryAddress, + teleporterManagerAddress, + wrappedNativeTokenAddress, + ) + if err != nil { + return common.Address{}, err + } + if _, success, err := evm.WaitForTransaction(client, tx); err != nil { + return common.Address{}, err + } else if !success { + return common.Address{}, fmt.Errorf("failed receipt status deploying contract") + } + return address, nil +} + +func DeployWrappedNativeToken( + srcDir string, + rpcURL string, + prefundedPrivateKey string, + tokenSymbol string, +) (common.Address, error) { + srcDir = utils.ExpandHome(srcDir) + abiPath := filepath.Join(srcDir, "contracts/out/WrappedNativeToken.sol/WrappedNativeToken.abi.json") + binPath := filepath.Join(srcDir, "contracts/out/WrappedNativeToken.sol/WrappedNativeToken.bin") + abiBytes, err := os.ReadFile(abiPath) + if err != nil { + return common.Address{}, err + } + binBytes, err := os.ReadFile(binPath) + if err != nil { + return common.Address{}, err + } + metadata := &bind.MetaData{ + ABI: string(abiBytes), + Bin: string(binBytes), + } + abi, err := metadata.GetAbi() + if err != nil { + return common.Address{}, err + } + bin := common.FromHex(metadata.Bin) + client, err := evm.GetClient(rpcURL) + if err != nil { + return common.Address{}, err + } + defer client.Close() + txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) + if err != nil { + return common.Address{}, err + } + address, tx, _, err := bind.DeployContract(txOpts, *abi, bin, client, tokenSymbol) + if err != nil { + return common.Address{}, err + } + if _, success, err := evm.WaitForTransaction(client, tx); err != nil { + return common.Address{}, err + } else if !success { + return common.Address{}, fmt.Errorf("failed receipt status deploying contract") + } + return address, nil +} + +func GetTokenParams(endpoint string, tokenAddress string) (string, string, uint8, error) { + address := common.HexToAddress(tokenAddress) + client, err := ethclient.Dial(endpoint) + if err != nil { + return "", "", 0, err + } + token, err := erc20.NewGGToken(address, client) + if err != nil { + return "", "", 0, err + } + tokenName, err := token.Name(nil) + if err != nil { + return "", "", 0, err + } + tokenSymbol, err := token.Symbol(nil) + if err != nil { + return "", "", 0, err + } + // TODO: find out if there are decimals options and why (academy) + tokenDecimals, err := token.Decimals(nil) + if err != nil { + return "", "", 0, err + } + return tokenSymbol, tokenName, tokenDecimals, nil +} From 3ba05129f00e79d0cd2edd8b6374687a66f20530 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 10 Jun 2024 16:18:17 -0300 Subject: [PATCH 44/87] add foundry install stuff --- pkg/bridge/foundry.go | 71 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 pkg/bridge/foundry.go diff --git a/pkg/bridge/foundry.go b/pkg/bridge/foundry.go new file mode 100644 index 000000000..da15e8d3a --- /dev/null +++ b/pkg/bridge/foundry.go @@ -0,0 +1,71 @@ +// Copyright (C) 2022, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +package bridge + +import ( + _ "embed" + "io" + "os/exec" + "strings" + + "github.com/ava-labs/avalanche-cli/pkg/utils" + "github.com/ava-labs/avalanche-cli/pkg/ux" +) + +var ( + foundryupPath = utils.ExpandHome("~/.foundry/bin/foundryup") + forgePath = utils.ExpandHome("~/.foundry/bin/forge") +) + +func foundryIsInstalled() bool { + return utils.IsExecutable(forgePath) +} + +func installFoundry() error { + ux.Logger.PrintToUser("Installing Foundry") + downloadCmd := exec.Command("curl", "-L", "https://foundry.paradigm.xyz") + installCmd := exec.Command("sh") + var downloadOutbuf, downloadErrbuf strings.Builder + downloadCmdStdoutPipe, err := downloadCmd.StdoutPipe() + if err != nil { + return err + } + downloadCmd.Stderr = &downloadErrbuf + installCmd.Stdin = io.TeeReader(downloadCmdStdoutPipe, &downloadOutbuf) + var installOutbuf, installErrbuf strings.Builder + installCmd.Stdout = &installOutbuf + installCmd.Stderr = &installErrbuf + if err := installCmd.Start(); err != nil { + return err + } + if err := downloadCmd.Run(); err != nil { + if downloadOutbuf.String() != "" { + ux.Logger.PrintToUser(strings.TrimSuffix(downloadOutbuf.String(), "\n")) + } + if downloadErrbuf.String() != "" { + ux.Logger.PrintToUser(strings.TrimSuffix(downloadErrbuf.String(), "\n")) + } + return err + } + if err := installCmd.Wait(); err != nil { + if installOutbuf.String() != "" { + ux.Logger.PrintToUser(strings.TrimSuffix(installOutbuf.String(), "\n")) + } + if installErrbuf.String() != "" { + ux.Logger.PrintToUser(strings.TrimSuffix(installErrbuf.String(), "\n")) + } + ux.Logger.PrintToUser("installation failed: %s", err.Error()) + return err + } + ux.Logger.PrintToUser(strings.TrimSuffix(installOutbuf.String(), "\n")) + out, err := exec.Command(foundryupPath).CombinedOutput() + ux.Logger.PrintToUser(string(out)) + if err != nil { + ux.Logger.PrintToUser("") + ux.Logger.PrintToUser("Foundry toolset is not available and couldn't automatically be installed. It is a necessary dependency for CLI to compile smart contracts.") + ux.Logger.PrintToUser("") + ux.Logger.PrintToUser("Please follow install instructions at https://book.getfoundry.sh/getting-started/installation and try again") + ux.Logger.PrintToUser("") + } + return err +} From 701ec760742988604121ced4589e339038696a89 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 10 Jun 2024 16:20:33 -0300 Subject: [PATCH 45/87] add foundry install to flow --- cmd/teleportercmd/bridgecmd/deploy.go | 3 +++ pkg/bridge/foundry.go | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index 9db3955cd..e741c3620 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -70,6 +70,9 @@ func deploy(_ *cobra.Command, args []string) error { } func CallDeploy(_ []string, flags DeployFlags) error { + if !bridge.FoundryIsInstalled() { + return bridge.InstallFoundry() + } network, err := networkoptions.GetNetworkFromCmdLineFlags( app, "On what Network do you want to deploy the Teleporter bridge?", diff --git a/pkg/bridge/foundry.go b/pkg/bridge/foundry.go index da15e8d3a..53739e441 100644 --- a/pkg/bridge/foundry.go +++ b/pkg/bridge/foundry.go @@ -17,11 +17,11 @@ var ( forgePath = utils.ExpandHome("~/.foundry/bin/forge") ) -func foundryIsInstalled() bool { +func FoundryIsInstalled() bool { return utils.IsExecutable(forgePath) } -func installFoundry() error { +func InstallFoundry() error { ux.Logger.PrintToUser("Installing Foundry") downloadCmd := exec.Command("curl", "-L", "https://foundry.paradigm.xyz") installCmd := exec.Command("sh") From c922c5dfdd720d716295fe66c0bb8456f15066b4 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 10 Jun 2024 17:00:52 -0300 Subject: [PATCH 46/87] add bridge contracts download --- cmd/teleportercmd/bridgecmd/deploy.go | 7 +++ pkg/bridge/build.go | 88 +++++++++++++++++++++++++++ pkg/constants/constants.go | 5 ++ 3 files changed, 100 insertions(+) create mode 100644 pkg/bridge/build.go diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index e741c3620..55fb97c7e 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -265,6 +265,13 @@ func CallDeploy(_ []string, flags DeployFlags) error { return fmt.Errorf("trying to make a bridge were hub and spoke are on the same subnet") } + // Setup Contracts + ux.Logger.PrintToUser("Downloading and Building Smart Contracts") + if err := bridge.DownloadRepo(app); err != nil { + return err + } + return nil + // Hub Deploy bridgeSrcDir := utils.ExpandHome("~/Workspace/projects/teleporter-token-bridge/") var ( diff --git a/pkg/bridge/build.go b/pkg/bridge/build.go new file mode 100644 index 000000000..1897cf447 --- /dev/null +++ b/pkg/bridge/build.go @@ -0,0 +1,88 @@ +// Copyright (C) 2022, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +package bridge + +import ( + _ "embed" + "fmt" + "os" + "os/exec" + "path/filepath" + + "github.com/ava-labs/avalanche-cli/pkg/application" + "github.com/ava-labs/avalanche-cli/pkg/constants" + "github.com/ava-labs/avalanche-cli/pkg/utils" + "github.com/ava-labs/avalanche-cli/pkg/vm" +) + +const ( + BridgeRepoDir = "teleporter-token-bridge" +) + +func RepoDir( + app *application.Avalanche, +) (string, error) { + repoDir := filepath.Join(app.GetReposDir(), constants.BridgeDir) + if err := os.MkdirAll(repoDir, constants.DefaultPerms755); err != nil { + return "", err + } + return repoDir, nil +} + +func DownloadRepo( + app *application.Avalanche, +) error { + if err := vm.CheckGitIsInstalled(); err != nil { + return err + } + repoDir, err := RepoDir(app) + if err != nil { + return err + } + cmd := exec.Command("git", "init", "-q") + cmd.Dir = repoDir + utils.SetupRealtimeCLIOutput(cmd, true, true) + if err := cmd.Run(); err != nil { + return fmt.Errorf("could not init git directory on %s: %w", repoDir, err) + } + cmd = exec.Command("git", "remote", "-v") + cmd.Dir = repoDir + remoteStdout, stderr := utils.SetupRealtimeCLIOutput(cmd, false, true) + if err := cmd.Run(); err != nil { + fmt.Println(remoteStdout) + fmt.Println(stderr) + return fmt.Errorf("could check git remote conf on %s: %w", repoDir, err) + } + if remoteStdout.String() == "" { + cmd = exec.Command("git", "remote", "add", "origin", constants.BridgeURL) + cmd.Dir = repoDir + utils.SetupRealtimeCLIOutput(cmd, true, true) + if err := cmd.Run(); err != nil { + return fmt.Errorf("could not add origin %s on git: %w", constants.BridgeURL, err) + } + cmd = exec.Command("git", "fetch", "--depth", "1", "origin", constants.BridgeBranch, "-q") + cmd.Dir = repoDir + utils.SetupRealtimeCLIOutput(cmd, true, true) + if err := cmd.Run(); err != nil { + return fmt.Errorf("could not fetch git branch/commit %s of repository %s: %w", constants.BridgeBranch, constants.BridgeURL, err) + } + cmd = exec.Command("git", "checkout", constants.BridgeBranch) + cmd.Dir = repoDir + stdout, stderr := utils.SetupRealtimeCLIOutput(cmd, false, false) + if err := cmd.Run(); err != nil { + fmt.Println(stdout) + fmt.Println(stderr) + return fmt.Errorf("could not checkout git branch %s of repository %s: %w", constants.BridgeBranch, constants.BridgeURL, err) + } + } else { + cmd = exec.Command("git", "pull") + cmd.Dir = repoDir + stdout, stderr := utils.SetupRealtimeCLIOutput(cmd, false, false) + if err := cmd.Run(); err != nil { + fmt.Println(stdout) + fmt.Println(stderr) + return fmt.Errorf("could not pull git branch %s of repository %s: %w", constants.BridgeBranch, constants.BridgeURL, err) + } + } + return nil +} diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index 7bcda42d0..b591e183e 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -345,4 +345,9 @@ const ( // Docker RemoteDockeSocketPath = "/var/run/docker.sock" + + // Bridge + BridgeDir = "teleporter-token-bridge" + BridgeURL = "https://github.com/ava-labs/teleporter-token-bridge" + BridgeBranch = "main" ) From ff679eab7d60400db4bd66ca0f8adf22b268b092 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 10 Jun 2024 20:13:34 -0300 Subject: [PATCH 47/87] nits --- cmd/teleportercmd/bridgecmd/deploy.go | 2 +- pkg/bridge/build.go | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index 55fb97c7e..35e06ef98 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -266,7 +266,7 @@ func CallDeploy(_ []string, flags DeployFlags) error { } // Setup Contracts - ux.Logger.PrintToUser("Downloading and Building Smart Contracts") + ux.Logger.PrintToUser("Downloading Smart Contracts") if err := bridge.DownloadRepo(app); err != nil { return err } diff --git a/pkg/bridge/build.go b/pkg/bridge/build.go index 1897cf447..d246bbdc7 100644 --- a/pkg/bridge/build.go +++ b/pkg/bridge/build.go @@ -84,5 +84,19 @@ func DownloadRepo( return fmt.Errorf("could not pull git branch %s of repository %s: %w", constants.BridgeBranch, constants.BridgeURL, err) } } + cmd = exec.Command( + "git", + "submodule", + "update", + "--init", + "--recursive", + ) + cmd.Dir = repoDir + stdout, stderr := utils.SetupRealtimeCLIOutput(cmd, false, false) + if err := cmd.Run(); err != nil { + fmt.Println(stdout) + fmt.Println(stderr) + return fmt.Errorf("could not update submodules of repository %s: %w", constants.BridgeURL, err) + } return nil } From 8f2f493e8d1b77a01b2c65ea2a7abe693b44146b Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 10 Jun 2024 21:01:26 -0300 Subject: [PATCH 48/87] added bridge contracts download + compilation --- cmd/teleportercmd/bridgecmd/deploy.go | 8 ++- pkg/bridge/build.go | 89 +++++++++++++++------------ pkg/utils/file.go | 11 ++++ 3 files changed, 67 insertions(+), 41 deletions(-) diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index 35e06ef98..d0268e59d 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -266,11 +266,15 @@ func CallDeploy(_ []string, flags DeployFlags) error { } // Setup Contracts - ux.Logger.PrintToUser("Downloading Smart Contracts") + ux.Logger.PrintToUser("Downloading Bridge Contracts") if err := bridge.DownloadRepo(app); err != nil { return err } - return nil + ux.Logger.PrintToUser("Compiling Bridge") + if err := bridge.BuildContracts(app); err != nil { + return err + } + ux.Logger.PrintToUser("") // Hub Deploy bridgeSrcDir := utils.ExpandHome("~/Workspace/projects/teleporter-token-bridge/") diff --git a/pkg/bridge/build.go b/pkg/bridge/build.go index d246bbdc7..de80c5926 100644 --- a/pkg/bridge/build.go +++ b/pkg/bridge/build.go @@ -29,6 +29,30 @@ func RepoDir( return repoDir, nil } +func BuildContracts( + app *application.Avalanche, +) error { + repoDir, err := RepoDir(app) + if err != nil { + return err + } + cmd := exec.Command( + forgePath, + "build", + "--extra-output-files", + "abi", + "bin", + ) + cmd.Dir = filepath.Join(repoDir, "contracts") + stdout, stderr := utils.SetupRealtimeCLIOutput(cmd, false, false) + if err := cmd.Run(); err != nil { + fmt.Println(stdout) + fmt.Println(stderr) + return fmt.Errorf("could not build contracts: %w", err) + } + return nil +} + func DownloadRepo( app *application.Avalanche, ) error { @@ -39,50 +63,36 @@ func DownloadRepo( if err != nil { return err } - cmd := exec.Command("git", "init", "-q") - cmd.Dir = repoDir - utils.SetupRealtimeCLIOutput(cmd, true, true) - if err := cmd.Run(); err != nil { - return fmt.Errorf("could not init git directory on %s: %w", repoDir, err) - } - cmd = exec.Command("git", "remote", "-v") - cmd.Dir = repoDir - remoteStdout, stderr := utils.SetupRealtimeCLIOutput(cmd, false, true) - if err := cmd.Run(); err != nil { - fmt.Println(remoteStdout) - fmt.Println(stderr) - return fmt.Errorf("could check git remote conf on %s: %w", repoDir, err) + alreadyCloned, err := utils.NonEmptyDirectory(repoDir) + if err != nil { + return err } - if remoteStdout.String() == "" { - cmd = exec.Command("git", "remote", "add", "origin", constants.BridgeURL) - cmd.Dir = repoDir - utils.SetupRealtimeCLIOutput(cmd, true, true) - if err := cmd.Run(); err != nil { - return fmt.Errorf("could not add origin %s on git: %w", constants.BridgeURL, err) - } - cmd = exec.Command("git", "fetch", "--depth", "1", "origin", constants.BridgeBranch, "-q") - cmd.Dir = repoDir - utils.SetupRealtimeCLIOutput(cmd, true, true) - if err := cmd.Run(); err != nil { - return fmt.Errorf("could not fetch git branch/commit %s of repository %s: %w", constants.BridgeBranch, constants.BridgeURL, err) - } - cmd = exec.Command("git", "checkout", constants.BridgeBranch) - cmd.Dir = repoDir + if !alreadyCloned { + cmd := exec.Command( + "git", + "clone", + "-b", + constants.BridgeBranch, + constants.BridgeURL, + repoDir, + "--recurse-submodules", + "--shallow-submodules", + ) stdout, stderr := utils.SetupRealtimeCLIOutput(cmd, false, false) if err := cmd.Run(); err != nil { fmt.Println(stdout) fmt.Println(stderr) - return fmt.Errorf("could not checkout git branch %s of repository %s: %w", constants.BridgeBranch, constants.BridgeURL, err) - } - } else { - cmd = exec.Command("git", "pull") - cmd.Dir = repoDir - stdout, stderr := utils.SetupRealtimeCLIOutput(cmd, false, false) - if err := cmd.Run(); err != nil { - fmt.Println(stdout) - fmt.Println(stderr) - return fmt.Errorf("could not pull git branch %s of repository %s: %w", constants.BridgeBranch, constants.BridgeURL, err) + return fmt.Errorf("could not clone repository %s: %w", constants.BridgeURL, err) } + return nil + } + cmd := exec.Command("git", "pull") + cmd.Dir = repoDir + stdout, stderr := utils.SetupRealtimeCLIOutput(cmd, false, false) + if err := cmd.Run(); err != nil { + fmt.Println(stdout) + fmt.Println(stderr) + return fmt.Errorf("could not pull repository %s: %w", constants.BridgeURL, err) } cmd = exec.Command( "git", @@ -90,9 +100,10 @@ func DownloadRepo( "update", "--init", "--recursive", + "--single-branch", ) cmd.Dir = repoDir - stdout, stderr := utils.SetupRealtimeCLIOutput(cmd, false, false) + stdout, stderr = utils.SetupRealtimeCLIOutput(cmd, false, false) if err := cmd.Run(); err != nil { fmt.Println(stdout) fmt.Println(stderr) diff --git a/pkg/utils/file.go b/pkg/utils/file.go index 68eeb3024..3898b3d00 100644 --- a/pkg/utils/file.go +++ b/pkg/utils/file.go @@ -10,6 +10,17 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/constants" ) +func NonEmptyDirectory(dirName string) (bool, error) { + if !DirectoryExists(dirName) { + return false, fmt.Errorf("%s is not a directory", dirName) + } + files, err := os.ReadDir(dirName) + if err != nil { + return false, err + } + return len(files) != 0, nil +} + func DirectoryExists(dirName string) bool { info, err := os.Stat(dirName) if os.IsNotExist(err) { From f0e780f8df60e84b203b33367de7cfecb72391eb Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 10 Jun 2024 21:17:10 -0300 Subject: [PATCH 49/87] nit --- cmd/teleportercmd/bridgecmd/deploy.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index d0268e59d..e0767b5c9 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -277,7 +277,10 @@ func CallDeploy(_ []string, flags DeployFlags) error { ux.Logger.PrintToUser("") // Hub Deploy - bridgeSrcDir := utils.ExpandHome("~/Workspace/projects/teleporter-token-bridge/") + bridgeSrcDir, err := bridge.RepoDir(app) + if err != nil { + return err + } var ( hubAddress common.Address tokenSymbol string From 6dc2f8a1aed44f7c60da73f725420932bbbeb6c0 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 10 Jun 2024 23:23:10 -0300 Subject: [PATCH 50/87] add explanations --- cmd/teleportercmd/bridgecmd/deploy.go | 49 +++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index e0767b5c9..0b4e0de88 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -208,22 +208,57 @@ func CallDeploy(_ []string, flags DeployFlags) error { } flags.hubFlags.erc20Address = erc20TokenAddr.Hex() if p := utils.Find(popularTokensInfo, func(p PopularTokenInfo) bool { return p.TokenContractAddress == erc20TokenAddr.Hex() }); p != nil { - ux.Logger.PrintToUser("You have entered the address of %s, a popular token in the subnet.", p.TokenName) - deployANewHupOption := "Yes, I want to deploy a new Bridge Hub" - useTheExistingHubOption := "No, I want to use the existing official Bridge Hub" - options := []string{deployANewHupOption, useTheExistingHubOption} - _, err = app.Prompt.CaptureList( - "Are you sure you want to deploy a new Bridge Hub for it?", + chainName := "C-Chain" + if !flags.hubFlags.chainFlags.CChain { + chainName = flags.hubFlags.chainFlags.SubnetName + } + ux.Logger.PrintToUser("There already is a Token Hub for %s deployed on %s.", p.TokenName, chainName) + ux.Logger.PrintToUser("") + ux.Logger.PrintToUser("Hub Address: %s", p.BridgeHubAddress) + deployANewHupOption := "Yes, use the existing Hub" + useTheExistingHubOption := "No, deploy my own Hub" + options := []string{deployANewHupOption, useTheExistingHubOption, explainOption} + option, err := app.Prompt.CaptureList( + "Do you want to use the existing Hub?", options, ) if err != nil { return err } + switch option { + case useTheExistingHubOption: + flags.hubFlags.hubAddress = p.BridgeHubAddress + flags.hubFlags.erc20Address = "" + case deployANewHupOption: + case explainOption: + ux.Logger.PrintToUser("There is already a Bridge Hub deployed for the popular token %s on %s.", + p.TokenName, + chainName, + ) + ux.Logger.PrintToUser("Connect to that Hub to participate in standard cross chain transfers") + ux.Logger.PrintToUser("for the token, including transfers to any of the registered Spoke subnets.") + ux.Logger.PrintToUser("Deploy a new Hub if wanting to have isolated cross chain transfers for") + ux.Logger.PrintToUser("your application, or if wanting to provide a new bridge alternative") + ux.Logger.PrintToUser("for the token.") + } } } case explainOption: - ux.Logger.PrintToUser("The difference is...") + ux.Logger.PrintToUser("A bridge consists of one Hub and at least one but possibly many Spokes.") + ux.Logger.PrintToUser("The Hub manages the asset to be bridged out to Spoke instances. It lives on the Subnet") + ux.Logger.PrintToUser("where the asset exists") + ux.Logger.PrintToUser("The Spokes live on the other Subnets that want to import the asset bridged by the Hub.") ux.Logger.PrintToUser("") + if len(popularTokensDesc) != 0 { + ux.Logger.PrintToUser("A popular token of a subnet is assumed to already have a Hub Deployed. In this case") + ux.Logger.PrintToUser("the Hub parameters will be automatically obtained, and a new Spoke will be created on") + ux.Logger.PrintToUser("the other Subnet, to access the popular token.") + } + ux.Logger.PrintToUser("For a token that already has a Hub deployed, the Hub parameters will be prompted,") + ux.Logger.PrintToUser("and a new Spoke will be created on the other Subnet to access that token.") + ux.Logger.PrintToUser("If deploying a new Hub for the token, the token parameters will be prompted,") + ux.Logger.PrintToUser("and both a new Hub will be created on the token Subnet, and a new Spoke will be created") + ux.Logger.PrintToUser("on the other Subnet to access that token.") continue } break From 7863968053df8d91e45e57d58b62a231a2d2eff7 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Mon, 10 Jun 2024 23:28:25 -0300 Subject: [PATCH 51/87] nit --- cmd/teleportercmd/bridgecmd/deploy.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index 0b4e0de88..45c2fa059 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -208,11 +208,7 @@ func CallDeploy(_ []string, flags DeployFlags) error { } flags.hubFlags.erc20Address = erc20TokenAddr.Hex() if p := utils.Find(popularTokensInfo, func(p PopularTokenInfo) bool { return p.TokenContractAddress == erc20TokenAddr.Hex() }); p != nil { - chainName := "C-Chain" - if !flags.hubFlags.chainFlags.CChain { - chainName = flags.hubFlags.chainFlags.SubnetName - } - ux.Logger.PrintToUser("There already is a Token Hub for %s deployed on %s.", p.TokenName, chainName) + ux.Logger.PrintToUser("There already is a Token Hub for %s deployed on %s.", p.TokenName, hubChain) ux.Logger.PrintToUser("") ux.Logger.PrintToUser("Hub Address: %s", p.BridgeHubAddress) deployANewHupOption := "Yes, use the existing Hub" @@ -233,7 +229,7 @@ func CallDeploy(_ []string, flags DeployFlags) error { case explainOption: ux.Logger.PrintToUser("There is already a Bridge Hub deployed for the popular token %s on %s.", p.TokenName, - chainName, + hubChain, ) ux.Logger.PrintToUser("Connect to that Hub to participate in standard cross chain transfers") ux.Logger.PrintToUser("for the token, including transfers to any of the registered Spoke subnets.") From e93333d431269471f416c439bfb19968bc0f92ea Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Tue, 11 Jun 2024 11:29:44 -0300 Subject: [PATCH 52/87] started working simple contract method call --- cmd/keycmd/list.go | 8 +++++-- cmd/keycmd/transfer.go | 50 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/cmd/keycmd/list.go b/cmd/keycmd/list.go index 8dcf26659..dafd4717f 100644 --- a/cmd/keycmd/list.go +++ b/cmd/keycmd/list.go @@ -488,11 +488,15 @@ func getEvmBasedChainAddrInfo( return nil, err } } + taggedChainToken := chainToken + if taggedChainToken != "AVAX" { + taggedChainToken = fmt.Sprintf("%s (Native)", taggedChainToken) + } info := addressInfo{ kind: kind, name: name, chain: chainName, - token: chainToken, + token: taggedChainToken, address: cChainAddr, balance: cChainBalance, network: network.Name(), @@ -519,7 +523,7 @@ func getEvmBasedChainAddrInfo( kind: kind, name: name, chain: chainName, - token: fmt.Sprintf("%s @%s..", tokenName, tokenAddress[:7]), + token: fmt.Sprintf("%s (%s.)", tokenName, tokenAddress[:6]), address: cChainAddr, balance: formattedBalance, network: network.Name(), diff --git a/cmd/keycmd/transfer.go b/cmd/keycmd/transfer.go index 41ff46898..97e5f98c5 100644 --- a/cmd/keycmd/transfer.go +++ b/cmd/keycmd/transfer.go @@ -5,9 +5,11 @@ package keycmd import ( "context" "fmt" + "math/big" "time" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" + "github.com/ava-labs/avalanche-cli/pkg/contract" "github.com/ava-labs/avalanche-cli/pkg/key" "github.com/ava-labs/avalanche-cli/pkg/networkoptions" "github.com/ava-labs/avalanche-cli/pkg/prompts" @@ -27,6 +29,7 @@ import ( "github.com/ava-labs/avalanchego/vms/secp256k1fx" "github.com/ava-labs/avalanchego/wallet/subnet/primary" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" + goethereumcommon "github.com/ethereum/go-ethereum/common" "github.com/spf13/cobra" ) @@ -135,6 +138,53 @@ func newTransferCmd() *cobra.Command { } func transferF(*cobra.Command, []string) error { + val, _ := new(big.Int).SetString("2000000000000000000000", 10) + err := contract.TxToMethod( + "http://127.0.0.1:9650/ext/bc/C/rpc", + "56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027", + goethereumcommon.HexToAddress("0x5DB9A7629912EBF95876228C24A848de0bfB43A9"), + "approve(address, uint256)->(bool)", + goethereumcommon.HexToAddress("0xa4DfF80B4a1D748BF28BC4A271eD834689Ea3407"), + val, + ) + type t struct { + A1 [32]byte + A2 goethereumcommon.Address + A3 goethereumcommon.Address + A4 goethereumcommon.Address + A5 *big.Int + A6 *big.Int + A7 *big.Int + A8 goethereumcommon.Address + } + chain, err := ids.FromString("nqp2DJw1VbjBhG2mGeH5C1JAshqNcTtpBEkj14kcYiT79Jwwu") + if err != nil { + return err + } + tval := t{ + A1: chain, + A2: goethereumcommon.HexToAddress("0xb623C4495220C603D0A939D32478F55891a61750"), + A3: goethereumcommon.HexToAddress("0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC"), + A4: goethereumcommon.HexToAddress("0x5DB9A7629912EBF95876228C24A848de0bfB43A9"), + A5: big.NewInt(0), + A6: big.NewInt(0), + A7: big.NewInt(250000), + A8: goethereumcommon.Address{}, + } + val, _ = new(big.Int).SetString("1000000000000000000000", 10) + err = contract.TxToMethod( + "http://127.0.0.1:9650/ext/bc/C/rpc", + "56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027", + goethereumcommon.HexToAddress("0xa4DfF80B4a1D748BF28BC4A271eD834689Ea3407"), + "send((bytes32:A1, address:A2, address:A3, address:A4, uint256:A5, uint256:A6, uint256:A7, address:A8), uint256)", + tval, + val, + ) + if err != nil { + return err + } + return nil + if send && receive { return fmt.Errorf("only one of %s, %s flags should be selected", sendFlag, receiveFlag) } From 74cb23c5c549351f1fdd9413c985cbf4b8695812 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Tue, 11 Jun 2024 11:32:04 -0300 Subject: [PATCH 53/87] this is beauty --- cmd/keycmd/transfer.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmd/keycmd/transfer.go b/cmd/keycmd/transfer.go index 97e5f98c5..b8e9ef936 100644 --- a/cmd/keycmd/transfer.go +++ b/cmd/keycmd/transfer.go @@ -147,6 +147,9 @@ func transferF(*cobra.Command, []string) error { goethereumcommon.HexToAddress("0xa4DfF80B4a1D748BF28BC4A271eD834689Ea3407"), val, ) + if err != nil { + return err + } type t struct { A1 [32]byte A2 goethereumcommon.Address From 55f8dcb4902857b8c5d18d1bb17919728878d72d Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Tue, 11 Jun 2024 15:03:06 -0300 Subject: [PATCH 54/87] added native transfer --- cmd/keycmd/transfer.go | 51 +++++++++++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/cmd/keycmd/transfer.go b/cmd/keycmd/transfer.go index b8e9ef936..915addbde 100644 --- a/cmd/keycmd/transfer.go +++ b/cmd/keycmd/transfer.go @@ -138,15 +138,7 @@ func newTransferCmd() *cobra.Command { } func transferF(*cobra.Command, []string) error { - val, _ := new(big.Int).SetString("2000000000000000000000", 10) - err := contract.TxToMethod( - "http://127.0.0.1:9650/ext/bc/C/rpc", - "56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027", - goethereumcommon.HexToAddress("0x5DB9A7629912EBF95876228C24A848de0bfB43A9"), - "approve(address, uint256)->(bool)", - goethereumcommon.HexToAddress("0xa4DfF80B4a1D748BF28BC4A271eD834689Ea3407"), - val, - ) + chain, err := ids.FromString("nqp2DJw1VbjBhG2mGeH5C1JAshqNcTtpBEkj14kcYiT79Jwwu") if err != nil { return err } @@ -160,11 +152,47 @@ func transferF(*cobra.Command, []string) error { A7 *big.Int A8 goethereumcommon.Address } - chain, err := ids.FromString("nqp2DJw1VbjBhG2mGeH5C1JAshqNcTtpBEkj14kcYiT79Jwwu") + tval := t{ + A1: chain, + A2: goethereumcommon.HexToAddress("0xb623C4495220C603D0A939D32478F55891a61750"), + A3: goethereumcommon.HexToAddress("0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC"), + A4: goethereumcommon.HexToAddress("0x5DB9A7629912EBF95876228C24A848de0bfB43A9"), + A5: big.NewInt(0), + A6: big.NewInt(0), + A7: big.NewInt(250000), + A8: goethereumcommon.Address{}, + } + val, _ := new(big.Int).SetString("1000000000000000000000", 10) + err = contract.TxToMethod( + "http://127.0.0.1:9650/ext/bc/C/rpc", + "56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027", + goethereumcommon.HexToAddress("0x4Ac1d98D9cEF99EC6546dEd4Bd550b0b287aaD6D"), + val, + "send((bytes32:A1, address:A2, address:A3, address:A4, uint256:A5, uint256:A6, uint256:A7, address:A8))", + tval, + ) if err != nil { return err } - tval := t{ + return nil + val, _ = new(big.Int).SetString("2000000000000000000000", 10) + err = contract.TxToMethod( + "http://127.0.0.1:9650/ext/bc/C/rpc", + "56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027", + goethereumcommon.HexToAddress("0x5DB9A7629912EBF95876228C24A848de0bfB43A9"), + nil, + "approve(address, uint256)->(bool)", + goethereumcommon.HexToAddress("0xa4DfF80B4a1D748BF28BC4A271eD834689Ea3407"), + val, + ) + if err != nil { + return err + } + chain, err = ids.FromString("nqp2DJw1VbjBhG2mGeH5C1JAshqNcTtpBEkj14kcYiT79Jwwu") + if err != nil { + return err + } + tval = t{ A1: chain, A2: goethereumcommon.HexToAddress("0xb623C4495220C603D0A939D32478F55891a61750"), A3: goethereumcommon.HexToAddress("0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC"), @@ -179,6 +207,7 @@ func transferF(*cobra.Command, []string) error { "http://127.0.0.1:9650/ext/bc/C/rpc", "56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027", goethereumcommon.HexToAddress("0xa4DfF80B4a1D748BF28BC4A271eD834689Ea3407"), + nil, "send((bytes32:A1, address:A2, address:A3, address:A4, uint256:A5, uint256:A6, uint256:A7, address:A8), uint256)", tval, val, From 9629c7f9338b241804a9ba2f63ddf29a59aca5f5 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Tue, 11 Jun 2024 15:25:22 -0300 Subject: [PATCH 55/87] avoid passing in field names --- cmd/keycmd/transfer.go | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/cmd/keycmd/transfer.go b/cmd/keycmd/transfer.go index 915addbde..3085cee78 100644 --- a/cmd/keycmd/transfer.go +++ b/cmd/keycmd/transfer.go @@ -45,17 +45,21 @@ const ( ) var ( - transferSupportedNetworkOptions = []networkoptions.NetworkOption{networkoptions.Mainnet, networkoptions.Fuji, networkoptions.Local} - send bool - receive bool - keyName string - ledgerIndex uint32 - force bool - receiverAddrStr string - amountFlt float64 - receiveRecoveryStep uint64 - PToX bool - PToP bool + transferSupportedNetworkOptions = []networkoptions.NetworkOption{ + networkoptions.Mainnet, + networkoptions.Fuji, + networkoptions.Local, + } + send bool + receive bool + keyName string + ledgerIndex uint32 + force bool + receiverAddrStr string + amountFlt float64 + receiveRecoveryStep uint64 + PToX bool + PToP bool ) func newTransferCmd() *cobra.Command { @@ -168,7 +172,7 @@ func transferF(*cobra.Command, []string) error { "56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027", goethereumcommon.HexToAddress("0x4Ac1d98D9cEF99EC6546dEd4Bd550b0b287aaD6D"), val, - "send((bytes32:A1, address:A2, address:A3, address:A4, uint256:A5, uint256:A6, uint256:A7, address:A8))", + "send((bytes32, address, address, address, uint256, uint256, uint256, address))", tval, ) if err != nil { From bd58420755e9f5a87f92c50895f73f884549499c Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Tue, 11 Jun 2024 15:38:56 -0300 Subject: [PATCH 56/87] added contract call --- cmd/keycmd/transfer.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/cmd/keycmd/transfer.go b/cmd/keycmd/transfer.go index 3085cee78..1191422f6 100644 --- a/cmd/keycmd/transfer.go +++ b/cmd/keycmd/transfer.go @@ -142,6 +142,18 @@ func newTransferCmd() *cobra.Command { } func transferF(*cobra.Command, []string) error { + out, err := contract.CallToMethod( + "http://127.0.0.1:9650/ext/bc/C/rpc", + goethereumcommon.HexToAddress("0x4Ac1d98D9cEF99EC6546dEd4Bd550b0b287aaD6D"), + "wrappedToken()->(address)", + ) + if err != nil { + return err + } + addr, b := out[0].(goethereumcommon.Address) + fmt.Println(b) + fmt.Println(addr) + return nil chain, err := ids.FromString("nqp2DJw1VbjBhG2mGeH5C1JAshqNcTtpBEkj14kcYiT79Jwwu") if err != nil { return err From 3ce261de5d7be6249340df1c6c3a8cb38c24bd6f Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Tue, 11 Jun 2024 15:41:20 -0300 Subject: [PATCH 57/87] add contract file --- pkg/contract/contract.go | 225 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 pkg/contract/contract.go diff --git a/pkg/contract/contract.go b/pkg/contract/contract.go new file mode 100644 index 000000000..319b4ce6e --- /dev/null +++ b/pkg/contract/contract.go @@ -0,0 +1,225 @@ +// Copyright (C) 2022, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +package contract + +import ( + _ "embed" + "encoding/json" + "fmt" + "math/big" + "reflect" + "strings" + + "github.com/ava-labs/avalanche-cli/pkg/evm" + "github.com/ava-labs/subnet-evm/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" +) + +func removeSurroundingParenthesis(s string) (string, error) { + s = strings.TrimSpace(s) + if len(s) > 0 { + if string(s[0]) != "(" || string(s[len(s)-1]) != ")" { + return "", fmt.Errorf("expected esp %q to be surrounded by parenthesis", s) + } + s = s[1 : len(s)-1] + } + return s, nil +} + +func getWords(s string) []string { + words := []string{} + word := "" + insideParenthesis := false + for _, rune := range s { + c := string(rune) + if insideParenthesis { + if c == ")" { + words = append(words, word) + word = "" + insideParenthesis = false + } else { + word += c + } + continue + } + if c == " " || c == "," || c == "(" { + if word != "" { + words = append(words, word) + word = "" + } + } + if c == " " || c == "," { + continue + } + if c == "(" { + insideParenthesis = true + continue + } + word += c + } + if word != "" { + words = append(words, word) + } + return words +} + +func getMap( + types []string, + params ...interface{}, +) []map[string]interface{} { + r := []map[string]interface{}{} + for i, t := range types { + spaceIndex := strings.Index(t, " ") + commaIndex := strings.Index(t, ",") + m := map[string]interface{}{} + if spaceIndex != -1 || commaIndex != -1 { + // complex type + m["components"] = getMap(getWords(t), params[i]) + m["internaltype"] = "tuple" + m["type"] = "tuple" + m["name"] = "" + } else { + name := "" + if len(params) == 1 { + rt := reflect.TypeOf(params[0]) + if rt.NumField() == len(types) { + name = rt.Field(i).Name + } + } + m["internaltype"] = t + m["type"] = t + m["name"] = name + } + r = append(r, m) + } + return r +} + +func ParseMethodEsp( + methodEsp string, + paid bool, + view bool, + params ...interface{}, +) (string, string, error) { + index := strings.Index(methodEsp, "(") + if index == -1 { + return methodEsp, "", nil + } + methodName := methodEsp[:index] + methodTypes := methodEsp[index:] + methodInputs := "" + methodOutputs := "" + index = strings.Index(methodTypes, "->") + if index == -1 { + methodInputs = methodTypes + } else { + methodInputs = methodTypes[:index] + methodOutputs = methodTypes[index+2:] + } + var err error + methodInputs, err = removeSurroundingParenthesis(methodInputs) + if err != nil { + return "", "", err + } + methodOutputs, err = removeSurroundingParenthesis(methodOutputs) + if err != nil { + return "", "", err + } + inputTypes := getWords(methodInputs) + outputTypes := getWords(methodOutputs) + inputs := getMap(inputTypes, params...) + outputs := getMap(outputTypes) + abiMap := []map[string]interface{}{ + { + "inputs": inputs, + "outputs": outputs, + "name": methodName, + "statemutability": "nonpayable", + "type": "function", + }, + } + if paid { + abiMap[0]["statemutability"] = "payable" + } + if view { + abiMap[0]["statemutability"] = "view" + } + abiBytes, err := json.MarshalIndent(abiMap, "", " ") + if err != nil { + return "", "", err + } + return methodName, string(abiBytes), nil +} + +func TxToMethod( + rpcURL string, + prefundedPrivateKey string, + contractAddress common.Address, + payment *big.Int, + methodEsp string, + params ...interface{}, +) error { + methodName, methodABI, err := ParseMethodEsp(methodEsp, payment != nil, false, params...) + if err != nil { + return err + } + metadata := &bind.MetaData{ + ABI: methodABI, + } + abi, err := metadata.GetAbi() + if err != nil { + return err + } + client, err := evm.GetClient(rpcURL) + if err != nil { + return err + } + defer client.Close() + contract := bind.NewBoundContract(contractAddress, *abi, client, client, client) + txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) + if err != nil { + return err + } + txOpts.Value = payment + tx, err := contract.Transact(txOpts, methodName, params...) + if err != nil { + return err + } + if _, success, err := evm.WaitForTransaction(client, tx); err != nil { + return err + } else if !success { + return fmt.Errorf("failed receipt status deploying contract") + } + return nil +} + +func CallToMethod( + rpcURL string, + contractAddress common.Address, + methodEsp string, + params ...interface{}, +) ([]interface{}, error) { + methodName, methodABI, err := ParseMethodEsp(methodEsp, false, true, params...) + if err != nil { + return nil, err + } + metadata := &bind.MetaData{ + ABI: methodABI, + } + abi, err := metadata.GetAbi() + if err != nil { + return nil, err + } + client, err := evm.GetClient(rpcURL) + if err != nil { + return nil, err + } + defer client.Close() + contract := bind.NewBoundContract(contractAddress, *abi, client, client, client) + var out []interface{} + err = contract.Call(&bind.CallOpts{}, &out, methodName, params...) + if err != nil { + return nil, err + } + return out, nil +} From bc6241d6f5c99057a42c1f8f517402c255dc3d95 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Tue, 11 Jun 2024 16:17:44 -0300 Subject: [PATCH 58/87] check hub kind --- cmd/teleportercmd/bridgecmd/deploy.go | 32 +++++++++++++++++-------- pkg/bridge/{bridge.go => deploy.go} | 34 --------------------------- 2 files changed, 22 insertions(+), 44 deletions(-) rename pkg/bridge/{bridge.go => deploy.go} (90%) diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index 45c2fa059..2aa83b984 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -313,11 +313,11 @@ func CallDeploy(_ []string, flags DeployFlags) error { return err } var ( - hubAddress common.Address - tokenSymbol string - tokenName string - tokenDecimals uint8 - erc20TokenAddress common.Address + hubAddress common.Address + tokenSymbol string + tokenName string + tokenDecimals uint8 + tokenAddress common.Address ) // TODO: need registry address, manager address, private key for the hub chain (academy for fuji) hubEndpoint, _, hubBlockchainID, _, hubRegistryAddress, hubKey, err := GetSubnetParams( @@ -330,23 +330,35 @@ func CallDeploy(_ []string, flags DeployFlags) error { } if flags.hubFlags.hubAddress != "" { hubAddress = common.HexToAddress(flags.hubFlags.hubAddress) - erc20TokenAddress, err = bridge.GetHubERC20Address(bridgeSrcDir, hubEndpoint, hubAddress) + hubKind, err := bridge.GetHubKind(hubEndpoint, hubAddress) if err != nil { return err } + switch hubKind { + case bridge.ERC20TokenHub: + tokenAddress, err = bridge.GetERC20HubTokenAddress(hubEndpoint, hubAddress) + if err != nil { + return err + } + case bridge.NativeTokenHub: + tokenAddress, err = bridge.GetNativeHubTokenAddress(hubEndpoint, hubAddress) + if err != nil { + return err + } + } tokenSymbol, tokenName, tokenDecimals, err = bridge.GetTokenParams( hubEndpoint, - erc20TokenAddress.Hex(), + tokenAddress.Hex(), ) if err != nil { return err } } if flags.hubFlags.erc20Address != "" { - erc20TokenAddress = common.HexToAddress(flags.hubFlags.erc20Address) + tokenAddress = common.HexToAddress(flags.hubFlags.erc20Address) tokenSymbol, tokenName, tokenDecimals, err = bridge.GetTokenParams( hubEndpoint, - erc20TokenAddress.Hex(), + tokenAddress.Hex(), ) if err != nil { return err @@ -357,7 +369,7 @@ func CallDeploy(_ []string, flags DeployFlags) error { hubKey.PrivKeyHex(), common.HexToAddress(hubRegistryAddress), common.HexToAddress(hubKey.C()), - erc20TokenAddress, + tokenAddress, tokenDecimals, ) if err != nil { diff --git a/pkg/bridge/bridge.go b/pkg/bridge/deploy.go similarity index 90% rename from pkg/bridge/bridge.go rename to pkg/bridge/deploy.go index 512af156e..dca02c58b 100644 --- a/pkg/bridge/bridge.go +++ b/pkg/bridge/deploy.go @@ -11,46 +11,12 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/evm" "github.com/ava-labs/avalanche-cli/pkg/utils" - subnetevmabi "github.com/ava-labs/subnet-evm/accounts/abi" "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" "github.com/liyue201/erc20-go/erc20" ) -func GetHubERC20Address( - srcDir string, - rpcURL string, - address common.Address, -) (common.Address, error) { - srcDir = utils.ExpandHome(srcDir) - abiPath := filepath.Join(srcDir, "contracts/out/ERC20TokenHub.sol/ERC20TokenHub.abi.json") - abiBytes, err := os.ReadFile(abiPath) - if err != nil { - return common.Address{}, err - } - metadata := &bind.MetaData{ - ABI: string(abiBytes), - } - abi, err := metadata.GetAbi() - if err != nil { - return common.Address{}, err - } - client, err := evm.GetClient(rpcURL) - if err != nil { - return common.Address{}, err - } - defer client.Close() - contract := bind.NewBoundContract(address, *abi, client, client, client) - var out []interface{} - err = contract.Call(&bind.CallOpts{}, &out, "token") - if err != nil { - return common.Address{}, err - } - out0 := *subnetevmabi.ConvertType(out[0], new(common.Address)).(*common.Address) - return out0, nil -} - type TeleporterFeeInfo struct { FeeTokenAddress common.Address Amount *big.Int From 20198b43437ed56010ea259e58937cf9f13167bf Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Tue, 11 Jun 2024 16:54:56 -0300 Subject: [PATCH 59/87] add send function for bridge hubs --- pkg/bridge/operate.go | 164 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 pkg/bridge/operate.go diff --git a/pkg/bridge/operate.go b/pkg/bridge/operate.go new file mode 100644 index 000000000..0dd5e704a --- /dev/null +++ b/pkg/bridge/operate.go @@ -0,0 +1,164 @@ +// Copyright (C) 2022, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +package bridge + +import ( + _ "embed" + "math/big" + + "github.com/ava-labs/avalanche-cli/pkg/contract" + "github.com/ava-labs/avalanchego/ids" + "github.com/ethereum/go-ethereum/common" +) + +type HubKind int64 + +const ( + Undefined HubKind = iota + ERC20TokenHub + NativeTokenHub +) + +func GetHubKind( + rpcURL string, + hubAddress common.Address, +) (HubKind, error) { + if _, err := ERC20TokenHubGetTokenAddress(rpcURL, hubAddress); err == nil { + return ERC20TokenHub, nil + } + if _, err := NativeTokenHubGetTokenAddress(rpcURL, hubAddress); err == nil { + return NativeTokenHub, nil + } else { + return Undefined, err + } +} + +func ERC20TokenHubGetTokenAddress( + rpcURL string, + hubAddress common.Address, +) (common.Address, error) { + out, err := contract.CallToMethod( + rpcURL, + hubAddress, + "token()->(address)", + ) + if err != nil { + return common.Address{}, err + } + tokenAddress := out[0].(common.Address) + return tokenAddress, nil +} + +func NativeTokenHubGetTokenAddress( + rpcURL string, + hubAddress common.Address, +) (common.Address, error) { + out, err := contract.CallToMethod( + rpcURL, + hubAddress, + "wrappedToken()->(address)", + ) + if err != nil { + return common.Address{}, err + } + tokenAddress := out[0].(common.Address) + return tokenAddress, nil +} + +func ERC20TokenHubSend( + rpcURL string, + hubAddress common.Address, + privateKey string, + destinationBlockchainID ids.ID, + destinationBridgeEnd common.Address, + amountRecipient common.Address, + amount *big.Int, +) error { + type Params struct { + DestinationBlockchainID [32]byte + DestinationBridgeEnd common.Address + AmountRecipient common.Address + PrimaryFeeTokenAddress common.Address + PrimaryFee *big.Int + SecondaryFee *big.Int + RequiredGasLimit *big.Int + MultiHopFallback common.Address + } + tokenAddress, err := ERC20TokenHubGetTokenAddress(rpcURL, hubAddress) + if err != nil { + return err + } + if err := contract.TxToMethod( + rpcURL, + privateKey, + tokenAddress, + nil, + "approve(address, uint256)->(bool)", + hubAddress, + amount, + ); err != nil { + return err + } + params := Params{ + DestinationBlockchainID: destinationBlockchainID, + DestinationBridgeEnd: destinationBridgeEnd, + AmountRecipient: amountRecipient, + PrimaryFeeTokenAddress: tokenAddress, // in theory this is optional + PrimaryFee: big.NewInt(0), + SecondaryFee: big.NewInt(0), + RequiredGasLimit: big.NewInt(250000), + MultiHopFallback: common.Address{}, + } + return contract.TxToMethod( + rpcURL, + privateKey, + hubAddress, + nil, + "send((bytes32, address, address, address, uint256, uint256, uint256, address), uint256)", + params, + amount, + ) +} + +func NativeTokenHubSend( + rpcURL string, + hubAddress common.Address, + privateKey string, + destinationBlockchainID ids.ID, + destinationBridgeEnd common.Address, + amountRecipient common.Address, + amount *big.Int, +) error { + type Params struct { + DestinationBlockchainID [32]byte + DestinationBridgeEnd common.Address + AmountRecipient common.Address + PrimaryFeeTokenAddress common.Address + PrimaryFee *big.Int + SecondaryFee *big.Int + RequiredGasLimit *big.Int + MultiHopFallback common.Address + } + tokenAddress, err := NativeTokenHubGetTokenAddress(rpcURL, hubAddress) + if err != nil { + return err + } + params := Params{ + DestinationBlockchainID: destinationBlockchainID, + DestinationBridgeEnd: destinationBridgeEnd, + AmountRecipient: amountRecipient, + PrimaryFeeTokenAddress: tokenAddress, // in theory this is optional + PrimaryFee: big.NewInt(0), + SecondaryFee: big.NewInt(0), + RequiredGasLimit: big.NewInt(250000), + MultiHopFallback: common.Address{}, + } + return contract.TxToMethod( + rpcURL, + privateKey, + hubAddress, + amount, + "send((bytes32, address, address, address, uint256, uint256, uint256, address))", + params, + ) +} From 6f02e700fe5d9469331fb946c4dd50d8e82e0e37 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Tue, 11 Jun 2024 16:57:22 -0300 Subject: [PATCH 60/87] cleanup of key transfer --- cmd/keycmd/transfer.go | 94 --------------------------- cmd/teleportercmd/bridgecmd/deploy.go | 4 +- 2 files changed, 2 insertions(+), 96 deletions(-) diff --git a/cmd/keycmd/transfer.go b/cmd/keycmd/transfer.go index 1191422f6..281592a20 100644 --- a/cmd/keycmd/transfer.go +++ b/cmd/keycmd/transfer.go @@ -5,11 +5,9 @@ package keycmd import ( "context" "fmt" - "math/big" "time" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" - "github.com/ava-labs/avalanche-cli/pkg/contract" "github.com/ava-labs/avalanche-cli/pkg/key" "github.com/ava-labs/avalanche-cli/pkg/networkoptions" "github.com/ava-labs/avalanche-cli/pkg/prompts" @@ -29,7 +27,6 @@ import ( "github.com/ava-labs/avalanchego/vms/secp256k1fx" "github.com/ava-labs/avalanchego/wallet/subnet/primary" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" - goethereumcommon "github.com/ethereum/go-ethereum/common" "github.com/spf13/cobra" ) @@ -142,97 +139,6 @@ func newTransferCmd() *cobra.Command { } func transferF(*cobra.Command, []string) error { - out, err := contract.CallToMethod( - "http://127.0.0.1:9650/ext/bc/C/rpc", - goethereumcommon.HexToAddress("0x4Ac1d98D9cEF99EC6546dEd4Bd550b0b287aaD6D"), - "wrappedToken()->(address)", - ) - if err != nil { - return err - } - addr, b := out[0].(goethereumcommon.Address) - fmt.Println(b) - fmt.Println(addr) - return nil - chain, err := ids.FromString("nqp2DJw1VbjBhG2mGeH5C1JAshqNcTtpBEkj14kcYiT79Jwwu") - if err != nil { - return err - } - type t struct { - A1 [32]byte - A2 goethereumcommon.Address - A3 goethereumcommon.Address - A4 goethereumcommon.Address - A5 *big.Int - A6 *big.Int - A7 *big.Int - A8 goethereumcommon.Address - } - tval := t{ - A1: chain, - A2: goethereumcommon.HexToAddress("0xb623C4495220C603D0A939D32478F55891a61750"), - A3: goethereumcommon.HexToAddress("0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC"), - A4: goethereumcommon.HexToAddress("0x5DB9A7629912EBF95876228C24A848de0bfB43A9"), - A5: big.NewInt(0), - A6: big.NewInt(0), - A7: big.NewInt(250000), - A8: goethereumcommon.Address{}, - } - val, _ := new(big.Int).SetString("1000000000000000000000", 10) - err = contract.TxToMethod( - "http://127.0.0.1:9650/ext/bc/C/rpc", - "56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027", - goethereumcommon.HexToAddress("0x4Ac1d98D9cEF99EC6546dEd4Bd550b0b287aaD6D"), - val, - "send((bytes32, address, address, address, uint256, uint256, uint256, address))", - tval, - ) - if err != nil { - return err - } - return nil - val, _ = new(big.Int).SetString("2000000000000000000000", 10) - err = contract.TxToMethod( - "http://127.0.0.1:9650/ext/bc/C/rpc", - "56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027", - goethereumcommon.HexToAddress("0x5DB9A7629912EBF95876228C24A848de0bfB43A9"), - nil, - "approve(address, uint256)->(bool)", - goethereumcommon.HexToAddress("0xa4DfF80B4a1D748BF28BC4A271eD834689Ea3407"), - val, - ) - if err != nil { - return err - } - chain, err = ids.FromString("nqp2DJw1VbjBhG2mGeH5C1JAshqNcTtpBEkj14kcYiT79Jwwu") - if err != nil { - return err - } - tval = t{ - A1: chain, - A2: goethereumcommon.HexToAddress("0xb623C4495220C603D0A939D32478F55891a61750"), - A3: goethereumcommon.HexToAddress("0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC"), - A4: goethereumcommon.HexToAddress("0x5DB9A7629912EBF95876228C24A848de0bfB43A9"), - A5: big.NewInt(0), - A6: big.NewInt(0), - A7: big.NewInt(250000), - A8: goethereumcommon.Address{}, - } - val, _ = new(big.Int).SetString("1000000000000000000000", 10) - err = contract.TxToMethod( - "http://127.0.0.1:9650/ext/bc/C/rpc", - "56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027", - goethereumcommon.HexToAddress("0xa4DfF80B4a1D748BF28BC4A271eD834689Ea3407"), - nil, - "send((bytes32:A1, address:A2, address:A3, address:A4, uint256:A5, uint256:A6, uint256:A7, address:A8), uint256)", - tval, - val, - ) - if err != nil { - return err - } - return nil - if send && receive { return fmt.Errorf("only one of %s, %s flags should be selected", sendFlag, receiveFlag) } diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index 2aa83b984..51f83f6a5 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -336,12 +336,12 @@ func CallDeploy(_ []string, flags DeployFlags) error { } switch hubKind { case bridge.ERC20TokenHub: - tokenAddress, err = bridge.GetERC20HubTokenAddress(hubEndpoint, hubAddress) + tokenAddress, err = bridge.ERC20TokenHubGetTokenAddress(hubEndpoint, hubAddress) if err != nil { return err } case bridge.NativeTokenHub: - tokenAddress, err = bridge.GetNativeHubTokenAddress(hubEndpoint, hubAddress) + tokenAddress, err = bridge.NativeTokenHubGetTokenAddress(hubEndpoint, hubAddress) if err != nil { return err } From 0eb66983329de0a88ca009095af3ed57583dd44a Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Tue, 11 Jun 2024 20:05:25 -0300 Subject: [PATCH 61/87] full go and back for erc20 - erc20 --- cmd/keycmd/transfer.go | 203 +++++++++++++++++++++++--- cmd/teleportercmd/bridgecmd/deploy.go | 6 +- pkg/bridge/operate.go | 93 ++++++++++-- 3 files changed, 268 insertions(+), 34 deletions(-) diff --git a/cmd/keycmd/transfer.go b/cmd/keycmd/transfer.go index 281592a20..c5e197496 100644 --- a/cmd/keycmd/transfer.go +++ b/cmd/keycmd/transfer.go @@ -5,8 +5,11 @@ package keycmd import ( "context" "fmt" + "math/big" + "strings" "time" + "github.com/ava-labs/avalanche-cli/pkg/bridge" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" "github.com/ava-labs/avalanche-cli/pkg/key" "github.com/ava-labs/avalanche-cli/pkg/networkoptions" @@ -27,6 +30,7 @@ import ( "github.com/ava-labs/avalanchego/vms/secp256k1fx" "github.com/ava-labs/avalanchego/wallet/subnet/primary" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" + goethereumcommon "github.com/ethereum/go-ethereum/common" "github.com/spf13/cobra" ) @@ -35,7 +39,7 @@ const ( receiveFlag = "receive" keyNameFlag = "key" ledgerIndexFlag = "ledger" - receiverAddrFlag = "target-addr" + destinationAddrFlag = "destination-addr" amountFlag = "amount" wrongLedgerIndexVal = 32768 receiveRecoveryStepFlag = "receive-recovery-step" @@ -52,11 +56,17 @@ var ( keyName string ledgerIndex uint32 force bool - receiverAddrStr string + destinationAddrStr string amountFlt float64 receiveRecoveryStep uint64 PToX bool PToP bool + // bridge experimental + originSubnet string + destinationSubnet string + originBridgeAddress string + destinationBridgeAddress string + destinationKeyName string ) func newTransferCmd() *cobra.Command { @@ -72,13 +82,13 @@ func newTransferCmd() *cobra.Command { &PToX, "fund-x-chain", false, - "fund X-Chain account on target", + "fund X-Chain account on destination", ) cmd.Flags().BoolVar( &PToP, "fund-p-chain", false, - "fund P-Chain account on target", + "fund P-Chain account on destination", ) cmd.Flags().BoolVar( &force, @@ -122,18 +132,48 @@ func newTransferCmd() *cobra.Command { "receive step to use for multiple step transaction recovery", ) cmd.Flags().StringVarP( - &receiverAddrStr, - receiverAddrFlag, + &destinationAddrStr, + destinationAddrFlag, "a", "", - "receiver address", + "destination address", + ) + cmd.Flags().StringVar( + &destinationKeyName, + "destination-key", + "", + "key associated to a destination address", ) cmd.Flags().Float64VarP( &amountFlt, amountFlag, "o", 0, - "amount to send or receive (AVAX units)", + "amount to send or receive (AVAX or TOKEN units)", + ) + cmd.Flags().StringVar( + &originSubnet, + "origin-subnet", + "", + "subnet where the funds belong (bridge experimental)", + ) + cmd.Flags().StringVar( + &destinationSubnet, + "destination-subnet", + "", + "subnet where the funds will be sent (bridge experimental)", + ) + cmd.Flags().StringVar( + &originBridgeAddress, + "origin-bridge-address", + "", + "bridge address at the origin subnet (bridge experimental)", + ) + cmd.Flags().StringVar( + &destinationBridgeAddress, + "destination-bridge-address", + "", + "bridge address at the destination subnet (bridge experimental)", ) return cmd } @@ -160,6 +200,127 @@ func transferF(*cobra.Command, []string) error { return err } + // bridge experimental + // bridge hub -> spoke + if originSubnet != "" { + originURL := network.CChainEndpoint() + if strings.ToLower(originSubnet) != "c-chain" { + sc, err := app.LoadSidecar(originSubnet) + if err != nil { + return err + } + blockchainID := sc.Networks[network.Name()].BlockchainID + if blockchainID == ids.Empty { + return fmt.Errorf("subnet %s is not deployed to %s", originSubnet, network) + } + originURL = network.BlockchainEndpoint(blockchainID.String()) + } + if destinationSubnet == "" { + return fmt.Errorf("you should set destination subnet") + } + var destinationBlockchainID ids.ID + if strings.ToLower(destinationSubnet) == "c-chain" { + destinationBlockchainID, err = utils.GetChainID(network.Endpoint, "C") + if err != nil { + return err + } + } else { + sc, err := app.LoadSidecar(destinationSubnet) + if err != nil { + return err + } + blockchainID := sc.Networks[network.Name()].BlockchainID + if blockchainID == ids.Empty { + return fmt.Errorf("subnet %s is not deployed to %s", destinationSubnet, network.Name()) + } + destinationBlockchainID = blockchainID + } + if originBridgeAddress == "" { + return fmt.Errorf("you should set bridge address at origin") + } else { + if err := prompts.ValidateAddress(originBridgeAddress); err != nil { + return err + } + } + if destinationBridgeAddress == "" { + return fmt.Errorf("you should set bridge address at destination") + } else { + if err := prompts.ValidateAddress(destinationBridgeAddress); err != nil { + return err + } + } + if keyName == "" { + return fmt.Errorf("you should set the key that has the funds") + } + originK, err := app.GetKey(keyName, network, false) + if err != nil { + return err + } + privateKey := originK.PrivKeyHex() + var destinationAddr goethereumcommon.Address + if destinationAddrStr != "" { + if err := prompts.ValidateAddress(destinationAddrStr); err != nil { + return err + } + destinationAddr = goethereumcommon.HexToAddress(destinationAddrStr) + } else if destinationKeyName != "" { + destinationK, err := app.GetKey(destinationKeyName, network, false) + if err != nil { + return err + } + destinationAddrStr = destinationK.C() + destinationAddr = goethereumcommon.HexToAddress(destinationAddrStr) + } else { + return fmt.Errorf("you should set the destination address or destination key") + } + if amountFlt == 0 { + return fmt.Errorf("you should set the amount") + } + amount := new(big.Float).SetFloat64(amountFlt) + amount = amount.Mul(amount, new(big.Float).SetFloat64(float64(units.Avax))) + amount = amount.Mul(amount, new(big.Float).SetFloat64(float64(units.Avax))) + amountInt, _ := amount.Int(nil) + endpointKind, err := bridge.GetEndpointKind( + originURL, + goethereumcommon.HexToAddress(originBridgeAddress), + ) + if err != nil { + return err + } + switch endpointKind { + case bridge.ERC20TokenSpoke: + return bridge.ERC20TokenSpokeSend( + originURL, + goethereumcommon.HexToAddress(originBridgeAddress), + privateKey, + destinationBlockchainID, + goethereumcommon.HexToAddress(destinationBridgeAddress), + destinationAddr, + amountInt, + ) + case bridge.ERC20TokenHub: + return bridge.ERC20TokenHubSend( + originURL, + goethereumcommon.HexToAddress(originBridgeAddress), + privateKey, + destinationBlockchainID, + goethereumcommon.HexToAddress(destinationBridgeAddress), + destinationAddr, + amountInt, + ) + case bridge.NativeTokenHub: + return bridge.NativeTokenHubSend( + originURL, + goethereumcommon.HexToAddress(originBridgeAddress), + privateKey, + destinationBlockchainID, + goethereumcommon.HexToAddress(destinationBridgeAddress), + destinationAddr, + amountInt, + ) + } + } + if !send && !receive { option, err := app.Prompt.CaptureList( "Step of the transfer", @@ -196,7 +357,7 @@ func transferF(*cobra.Command, []string) error { if send { goalStr = " for the sender address" } else { - goalStr = " for the receiver address" + goalStr = " for the destination address" } useLedger, keyName, err = prompts.GetFujiKeyOrLedger(app.Prompt, goalStr, app.GetKeyDir()) if err != nil { @@ -250,28 +411,28 @@ func transferF(*cobra.Command, []string) error { } } - var receiverAddr ids.ShortID + var destinationAddr ids.ShortID if send { - if receiverAddrStr == "" { + if destinationAddrStr == "" { if PToP { - receiverAddrStr, err = app.Prompt.CapturePChainAddress("Receiver address", network) + destinationAddrStr, err = app.Prompt.CapturePChainAddress("Destination address", network) if err != nil { return err } } else { - receiverAddrStr, err = app.Prompt.CaptureXChainAddress("Receiver address", network) + destinationAddrStr, err = app.Prompt.CaptureXChainAddress("Destination address", network) if err != nil { return err } } } - receiverAddr, err = address.ParseToID(receiverAddrStr) + destinationAddr, err = address.ParseToID(destinationAddrStr) if err != nil { return err } } else { - receiverAddr = kc.Addresses().List()[0] - receiverAddrStr, err = address.Format("P", key.GetHRP(network.ID), receiverAddr[:]) + destinationAddr = kc.Addresses().List()[0] + destinationAddrStr, err = address.Format("P", key.GetHRP(network.ID), destinationAddr[:]) if err != nil { return err } @@ -285,17 +446,17 @@ func transferF(*cobra.Command, []string) error { if err != nil { return err } - if addr == receiverAddr && PToP { - return fmt.Errorf("sender addr is the same as receiver addr") + if addr == destinationAddr && PToP { + return fmt.Errorf("sender addr is the same as destination addr") } - ux.Logger.PrintToUser("- send %.9f AVAX from %s to target address %s", float64(amount)/float64(units.Avax), addrStr, receiverAddrStr) + ux.Logger.PrintToUser("- send %.9f AVAX from %s to destination address %s", float64(amount)/float64(units.Avax), addrStr, destinationAddrStr) totalFee := 4 * fee if PToX { totalFee = 2 * fee } ux.Logger.PrintToUser("- take a fee of %.9f AVAX from source address %s", float64(totalFee)/float64(units.Avax), addrStr) } else { - ux.Logger.PrintToUser("- receive %.9f AVAX at target address %s", float64(amount)/float64(units.Avax), receiverAddrStr) + ux.Logger.PrintToUser("- receive %.9f AVAX at destination address %s", float64(amount)/float64(units.Avax), destinationAddrStr) } ux.Logger.PrintToUser("") @@ -313,7 +474,7 @@ func transferF(*cobra.Command, []string) error { to := secp256k1fx.OutputOwners{ Threshold: 1, - Addrs: []ids.ShortID{receiverAddr}, + Addrs: []ids.ShortID{destinationAddr}, } if send { diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index 51f83f6a5..045f384d6 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -330,11 +330,11 @@ func CallDeploy(_ []string, flags DeployFlags) error { } if flags.hubFlags.hubAddress != "" { hubAddress = common.HexToAddress(flags.hubFlags.hubAddress) - hubKind, err := bridge.GetHubKind(hubEndpoint, hubAddress) + endpointKind, err := bridge.GetEndpointKind(hubEndpoint, hubAddress) if err != nil { return err } - switch hubKind { + switch endpointKind { case bridge.ERC20TokenHub: tokenAddress, err = bridge.ERC20TokenHubGetTokenAddress(hubEndpoint, hubAddress) if err != nil { @@ -345,6 +345,8 @@ func CallDeploy(_ []string, flags DeployFlags) error { if err != nil { return err } + default: + return fmt.Errorf("unsupported bridge endpoint kind %d", endpointKind) } tokenSymbol, tokenName, tokenDecimals, err = bridge.GetTokenParams( hubEndpoint, diff --git a/pkg/bridge/operate.go b/pkg/bridge/operate.go index 0dd5e704a..03d8bfc3f 100644 --- a/pkg/bridge/operate.go +++ b/pkg/bridge/operate.go @@ -11,23 +11,27 @@ import ( "github.com/ethereum/go-ethereum/common" ) -type HubKind int64 +type EndpointKind int64 const ( - Undefined HubKind = iota + Undefined EndpointKind = iota ERC20TokenHub NativeTokenHub + ERC20TokenSpoke ) -func GetHubKind( +func GetEndpointKind( rpcURL string, - hubAddress common.Address, -) (HubKind, error) { - if _, err := ERC20TokenHubGetTokenAddress(rpcURL, hubAddress); err == nil { + address common.Address, +) (EndpointKind, error) { + if _, err := ERC20TokenHubGetTokenAddress(rpcURL, address); err == nil { return ERC20TokenHub, nil } - if _, err := NativeTokenHubGetTokenAddress(rpcURL, hubAddress); err == nil { + if _, err := NativeTokenHubGetTokenAddress(rpcURL, address); err == nil { return NativeTokenHub, nil + } + if _, err := ERC20TokenSpokeGetTokenHubAddress(rpcURL, address); err == nil { + return ERC20TokenSpoke, nil } else { return Undefined, err } @@ -35,11 +39,11 @@ func GetHubKind( func ERC20TokenHubGetTokenAddress( rpcURL string, - hubAddress common.Address, + address common.Address, ) (common.Address, error) { out, err := contract.CallToMethod( rpcURL, - hubAddress, + address, "token()->(address)", ) if err != nil { @@ -51,11 +55,11 @@ func ERC20TokenHubGetTokenAddress( func NativeTokenHubGetTokenAddress( rpcURL string, - hubAddress common.Address, + address common.Address, ) (common.Address, error) { out, err := contract.CallToMethod( rpcURL, - hubAddress, + address, "wrappedToken()->(address)", ) if err != nil { @@ -65,6 +69,22 @@ func NativeTokenHubGetTokenAddress( return tokenAddress, nil } +func ERC20TokenSpokeGetTokenHubAddress( + rpcURL string, + address common.Address, +) (common.Address, error) { + out, err := contract.CallToMethod( + rpcURL, + address, + "tokenHubAddress()->(address)", + ) + if err != nil { + return common.Address{}, err + } + tokenHubAddress := out[0].(common.Address) + return tokenHubAddress, nil +} + func ERC20TokenHubSend( rpcURL string, hubAddress common.Address, @@ -162,3 +182,54 @@ func NativeTokenHubSend( params, ) } + +func ERC20TokenSpokeSend( + rpcURL string, + spokeAddress common.Address, + privateKey string, + destinationBlockchainID ids.ID, + destinationBridgeEnd common.Address, + amountRecipient common.Address, + amount *big.Int, +) error { + if err := contract.TxToMethod( + rpcURL, + privateKey, + spokeAddress, + nil, + "approve(address, uint256)->(bool)", + spokeAddress, + amount, + ); err != nil { + return err + } + type Params struct { + DestinationBlockchainID [32]byte + DestinationBridgeEnd common.Address + AmountRecipient common.Address + PrimaryFeeTokenAddress common.Address + PrimaryFee *big.Int + SecondaryFee *big.Int + RequiredGasLimit *big.Int + MultiHopFallback common.Address + } + params := Params{ + DestinationBlockchainID: destinationBlockchainID, + DestinationBridgeEnd: destinationBridgeEnd, + AmountRecipient: amountRecipient, + PrimaryFeeTokenAddress: common.Address{}, + PrimaryFee: big.NewInt(0), + SecondaryFee: big.NewInt(0), + RequiredGasLimit: big.NewInt(250000), + MultiHopFallback: common.Address{}, + } + return contract.TxToMethod( + rpcURL, + privateKey, + spokeAddress, + nil, + "send((bytes32, address, address, address, uint256, uint256, uint256, address), uint256)", + params, + amount, + ) +} From 1695263419195ead7ce8029c7784a1d90beed15f Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Tue, 11 Jun 2024 20:16:53 -0300 Subject: [PATCH 62/87] fix symbol on key list --- cmd/keycmd/list.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/keycmd/list.go b/cmd/keycmd/list.go index dafd4717f..3168dc9fe 100644 --- a/cmd/keycmd/list.go +++ b/cmd/keycmd/list.go @@ -508,7 +508,7 @@ func getEvmBasedChainAddrInfo( if err != nil { return addressInfos, err } - tokenName, err := token.Name(nil) + tokenSymbol, err := token.Symbol(nil) if err == nil { // just ignore contract address access errors as those may depend on network balance, err := token.BalanceOf(nil, common.HexToAddress(cChainAddr)) @@ -523,7 +523,7 @@ func getEvmBasedChainAddrInfo( kind: kind, name: name, chain: chainName, - token: fmt.Sprintf("%s (%s.)", tokenName, tokenAddress[:6]), + token: fmt.Sprintf("%s (%s.)", tokenSymbol, tokenAddress[:6]), address: cChainAddr, balance: formattedBalance, network: network.Name(), From d03080d351efc55d2a1ccd4a464450956b966232 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Tue, 11 Jun 2024 21:01:15 -0300 Subject: [PATCH 63/87] remove all abi file ref --- pkg/bridge/deploy.go | 275 +++++++-------------------------------- pkg/bridge/erc20.go | 37 ++++++ pkg/contract/contract.go | 66 ++++++++-- 3 files changed, 140 insertions(+), 238 deletions(-) create mode 100644 pkg/bridge/erc20.go diff --git a/pkg/bridge/deploy.go b/pkg/bridge/deploy.go index dca02c58b..6782de71d 100644 --- a/pkg/bridge/deploy.go +++ b/pkg/bridge/deploy.go @@ -1,20 +1,16 @@ -// Copyright (C) 2022, Ava Labs, Inc. All rights reserved. +// Cpopyright (C) 2022, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. package bridge import ( _ "embed" - "fmt" "math/big" "os" "path/filepath" - "github.com/ava-labs/avalanche-cli/pkg/evm" + "github.com/ava-labs/avalanche-cli/pkg/contract" "github.com/ava-labs/avalanche-cli/pkg/utils" - "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/liyue201/erc20-go/erc20" ) type TeleporterFeeInfo struct { @@ -22,62 +18,37 @@ type TeleporterFeeInfo struct { Amount *big.Int } +type TokenSpokeSettings struct { + TeleporterRegistryAddress common.Address + TeleporterManager common.Address + TokenHubBlockchainID [32]byte + TokenHubAddress common.Address + TokenHubDecimals uint8 +} + func RegisterERC20Spoke( srcDir string, rpcURL string, - prefundedPrivateKey string, - address common.Address, + privateKey string, + spokeAddress common.Address, ) error { - srcDir = utils.ExpandHome(srcDir) - abiPath := filepath.Join(srcDir, "contracts/out/ERC20TokenSpoke.sol/ERC20TokenSpoke.abi.json") - abiBytes, err := os.ReadFile(abiPath) - if err != nil { - return err - } - metadata := &bind.MetaData{ - ABI: string(abiBytes), - } - abi, err := metadata.GetAbi() - if err != nil { - return err - } - client, err := evm.GetClient(rpcURL) - if err != nil { - return err - } - defer client.Close() - txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) - if err != nil { - return err - } feeInfo := TeleporterFeeInfo{ Amount: big.NewInt(0), } - contract := bind.NewBoundContract(address, *abi, client, client, client) - tx, err := contract.Transact(txOpts, "registerWithHub", feeInfo) - if err != nil { - return err - } - if _, success, err := evm.WaitForTransaction(client, tx); err != nil { - return err - } else if !success { - return fmt.Errorf("failed receipt status deploying contract") - } - return nil -} - -type TokenSpokeSettings struct { - TeleporterRegistryAddress common.Address - TeleporterManager common.Address - TokenHubBlockchainID [32]byte - TokenHubAddress common.Address - TokenHubDecimals uint8 + return contract.TxToMethod( + rpcURL, + privateKey, + spokeAddress, + nil, + "registerWithHub((address, uint256))", + feeInfo, + ) } func DeployERC20Spoke( srcDir string, rpcURL string, - prefundedPrivateKey string, + privateKey string, teleporterRegistryAddress common.Address, teleporterManagerAddress common.Address, tokenHubBlockchainID [32]byte, @@ -86,35 +57,11 @@ func DeployERC20Spoke( tokenSymbol string, tokenDecimals uint8, ) (common.Address, error) { - srcDir = utils.ExpandHome(srcDir) - abiPath := filepath.Join(srcDir, "contracts/out/ERC20TokenSpoke.sol/ERC20TokenSpoke.abi.json") binPath := filepath.Join(srcDir, "contracts/out/ERC20TokenSpoke.sol/ERC20TokenSpoke.bin") - abiBytes, err := os.ReadFile(abiPath) - if err != nil { - return common.Address{}, err - } binBytes, err := os.ReadFile(binPath) if err != nil { return common.Address{}, err } - metadata := &bind.MetaData{ - ABI: string(abiBytes), - Bin: string(binBytes), - } - abi, err := metadata.GetAbi() - if err != nil { - return common.Address{}, err - } - bin := common.FromHex(metadata.Bin) - client, err := evm.GetClient(rpcURL) - if err != nil { - return common.Address{}, err - } - defer client.Close() - txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) - if err != nil { - return common.Address{}, err - } tokenSpokeSettings := TokenSpokeSettings{ TeleporterRegistryAddress: teleporterRegistryAddress, TeleporterManager: teleporterManagerAddress, @@ -123,212 +70,84 @@ func DeployERC20Spoke( // TODO: user case for hub having diff decimals TokenHubDecimals: tokenDecimals, } - address, tx, _, err := bind.DeployContract( - txOpts, - *abi, - bin, - client, + return contract.DeployContract( + rpcURL, + privateKey, + binBytes, + "((address, address, bytes32, address, uint8), string, string, uint8)", tokenSpokeSettings, tokenName, tokenSymbol, tokenDecimals, ) - if err != nil { - return common.Address{}, err - } - if _, success, err := evm.WaitForTransaction(client, tx); err != nil { - return common.Address{}, err - } else if !success { - return common.Address{}, fmt.Errorf("failed receipt status deploying contract") - } - return address, nil } func DeployERC20Hub( srcDir string, rpcURL string, - prefundedPrivateKey string, + privateKey string, teleporterRegistryAddress common.Address, teleporterManagerAddress common.Address, erc20TokenAddress common.Address, erc20TokenDecimals uint8, ) (common.Address, error) { - srcDir = utils.ExpandHome(srcDir) - abiPath := filepath.Join(srcDir, "contracts/out/ERC20TokenHub.sol/ERC20TokenHub.abi.json") binPath := filepath.Join(srcDir, "contracts/out/ERC20TokenHub.sol/ERC20TokenHub.bin") - abiBytes, err := os.ReadFile(abiPath) - if err != nil { - return common.Address{}, err - } binBytes, err := os.ReadFile(binPath) if err != nil { return common.Address{}, err } - metadata := &bind.MetaData{ - ABI: string(abiBytes), - Bin: string(binBytes), - } - abi, err := metadata.GetAbi() - if err != nil { - return common.Address{}, err - } - bin := common.FromHex(metadata.Bin) - client, err := evm.GetClient(rpcURL) - if err != nil { - return common.Address{}, err - } - defer client.Close() - txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) - if err != nil { - return common.Address{}, err - } - address, tx, _, err := bind.DeployContract( - txOpts, - *abi, - bin, - client, + return contract.DeployContract( + rpcURL, + privateKey, + binBytes, + "(address, address, address, uint8)", teleporterRegistryAddress, teleporterManagerAddress, erc20TokenAddress, erc20TokenDecimals, ) - if err != nil { - return common.Address{}, err - } - if _, success, err := evm.WaitForTransaction(client, tx); err != nil { - return common.Address{}, err - } else if !success { - return common.Address{}, fmt.Errorf("failed receipt status deploying contract") - } - return address, nil } func DeployNativeHub( srcDir string, rpcURL string, - prefundedPrivateKey string, + privateKey string, teleporterRegistryAddress common.Address, teleporterManagerAddress common.Address, wrappedNativeTokenAddress common.Address, ) (common.Address, error) { - srcDir = utils.ExpandHome(srcDir) - abiPath := filepath.Join(srcDir, "contracts/out/NativeTokenHub.sol/NativeTokenHub.abi.json") binPath := filepath.Join(srcDir, "contracts/out/NativeTokenHub.sol/NativeTokenHub.bin") - abiBytes, err := os.ReadFile(abiPath) - if err != nil { - return common.Address{}, err - } binBytes, err := os.ReadFile(binPath) if err != nil { return common.Address{}, err } - metadata := &bind.MetaData{ - ABI: string(abiBytes), - Bin: string(binBytes), - } - abi, err := metadata.GetAbi() - if err != nil { - return common.Address{}, err - } - bin := common.FromHex(metadata.Bin) - client, err := evm.GetClient(rpcURL) - if err != nil { - return common.Address{}, err - } - defer client.Close() - txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) - if err != nil { - return common.Address{}, err - } - address, tx, _, err := bind.DeployContract( - txOpts, - *abi, - bin, - client, + return contract.DeployContract( + rpcURL, + privateKey, + binBytes, + "(address, address, address)", teleporterRegistryAddress, teleporterManagerAddress, wrappedNativeTokenAddress, ) - if err != nil { - return common.Address{}, err - } - if _, success, err := evm.WaitForTransaction(client, tx); err != nil { - return common.Address{}, err - } else if !success { - return common.Address{}, fmt.Errorf("failed receipt status deploying contract") - } - return address, nil } func DeployWrappedNativeToken( srcDir string, rpcURL string, - prefundedPrivateKey string, + privateKey string, tokenSymbol string, ) (common.Address, error) { - srcDir = utils.ExpandHome(srcDir) - abiPath := filepath.Join(srcDir, "contracts/out/WrappedNativeToken.sol/WrappedNativeToken.abi.json") - binPath := filepath.Join(srcDir, "contracts/out/WrappedNativeToken.sol/WrappedNativeToken.bin") - abiBytes, err := os.ReadFile(abiPath) - if err != nil { - return common.Address{}, err - } + binPath := filepath.Join(utils.ExpandHome(srcDir), "contracts/out/WrappedNativeToken.sol/WrappedNativeToken.bin") binBytes, err := os.ReadFile(binPath) if err != nil { return common.Address{}, err } - metadata := &bind.MetaData{ - ABI: string(abiBytes), - Bin: string(binBytes), - } - abi, err := metadata.GetAbi() - if err != nil { - return common.Address{}, err - } - bin := common.FromHex(metadata.Bin) - client, err := evm.GetClient(rpcURL) - if err != nil { - return common.Address{}, err - } - defer client.Close() - txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) - if err != nil { - return common.Address{}, err - } - address, tx, _, err := bind.DeployContract(txOpts, *abi, bin, client, tokenSymbol) - if err != nil { - return common.Address{}, err - } - if _, success, err := evm.WaitForTransaction(client, tx); err != nil { - return common.Address{}, err - } else if !success { - return common.Address{}, fmt.Errorf("failed receipt status deploying contract") - } - return address, nil -} - -func GetTokenParams(endpoint string, tokenAddress string) (string, string, uint8, error) { - address := common.HexToAddress(tokenAddress) - client, err := ethclient.Dial(endpoint) - if err != nil { - return "", "", 0, err - } - token, err := erc20.NewGGToken(address, client) - if err != nil { - return "", "", 0, err - } - tokenName, err := token.Name(nil) - if err != nil { - return "", "", 0, err - } - tokenSymbol, err := token.Symbol(nil) - if err != nil { - return "", "", 0, err - } - // TODO: find out if there are decimals options and why (academy) - tokenDecimals, err := token.Decimals(nil) - if err != nil { - return "", "", 0, err - } - return tokenSymbol, tokenName, tokenDecimals, nil + return contract.DeployContract( + rpcURL, + privateKey, + binBytes, + "(string)", + tokenSymbol, + ) } diff --git a/pkg/bridge/erc20.go b/pkg/bridge/erc20.go new file mode 100644 index 000000000..aea885314 --- /dev/null +++ b/pkg/bridge/erc20.go @@ -0,0 +1,37 @@ +// Copyright (C) 2022, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +package bridge + +import ( + _ "embed" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/liyue201/erc20-go/erc20" +) + +func GetTokenParams(endpoint string, tokenAddress string) (string, string, uint8, error) { + address := common.HexToAddress(tokenAddress) + client, err := ethclient.Dial(endpoint) + if err != nil { + return "", "", 0, err + } + token, err := erc20.NewGGToken(address, client) + if err != nil { + return "", "", 0, err + } + tokenName, err := token.Name(nil) + if err != nil { + return "", "", 0, err + } + tokenSymbol, err := token.Symbol(nil) + if err != nil { + return "", "", 0, err + } + // TODO: find out if there are decimals options and why (academy) + tokenDecimals, err := token.Decimals(nil) + if err != nil { + return "", "", 0, err + } + return tokenSymbol, tokenName, tokenDecimals, nil +} diff --git a/pkg/contract/contract.go b/pkg/contract/contract.go index 319b4ce6e..f9bdbd55c 100644 --- a/pkg/contract/contract.go +++ b/pkg/contract/contract.go @@ -82,7 +82,7 @@ func getMap( name := "" if len(params) == 1 { rt := reflect.TypeOf(params[0]) - if rt.NumField() == len(types) { + if rt.Kind() == reflect.Struct && rt.NumField() == len(types) { name = rt.Field(i).Name } } @@ -97,6 +97,7 @@ func getMap( func ParseMethodEsp( methodEsp string, + constructor bool, paid bool, view bool, params ...interface{}, @@ -132,17 +133,21 @@ func ParseMethodEsp( abiMap := []map[string]interface{}{ { "inputs": inputs, - "outputs": outputs, - "name": methodName, - "statemutability": "nonpayable", + "stateMutability": "nonpayable", "type": "function", }, } + if !constructor { + abiMap[0]["outputs"] = outputs + abiMap[0]["name"] = methodName + } else { + abiMap[0]["type"] = "constructor" + } if paid { - abiMap[0]["statemutability"] = "payable" + abiMap[0]["stateMutability"] = "payable" } if view { - abiMap[0]["statemutability"] = "view" + abiMap[0]["stateMutability"] = "view" } abiBytes, err := json.MarshalIndent(abiMap, "", " ") if err != nil { @@ -153,13 +158,13 @@ func ParseMethodEsp( func TxToMethod( rpcURL string, - prefundedPrivateKey string, + privateKey string, contractAddress common.Address, payment *big.Int, methodEsp string, params ...interface{}, ) error { - methodName, methodABI, err := ParseMethodEsp(methodEsp, payment != nil, false, params...) + methodName, methodABI, err := ParseMethodEsp(methodEsp, false, payment != nil, false, params...) if err != nil { return err } @@ -176,7 +181,7 @@ func TxToMethod( } defer client.Close() contract := bind.NewBoundContract(contractAddress, *abi, client, client, client) - txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) + txOpts, err := evm.GetTxOptsWithSigner(client, privateKey) if err != nil { return err } @@ -199,7 +204,7 @@ func CallToMethod( methodEsp string, params ...interface{}, ) ([]interface{}, error) { - methodName, methodABI, err := ParseMethodEsp(methodEsp, false, true, params...) + methodName, methodABI, err := ParseMethodEsp(methodEsp, false, false, true, params...) if err != nil { return nil, err } @@ -223,3 +228,44 @@ func CallToMethod( } return out, nil } + +func DeployContract( + rpcURL string, + privateKey string, + binBytes []byte, + methodEsp string, + params ...interface{}, +) (common.Address, error) { + _, methodABI, err := ParseMethodEsp(methodEsp, true, false, false, params...) + if err != nil { + return common.Address{}, err + } + metadata := &bind.MetaData{ + ABI: methodABI, + Bin: string(binBytes), + } + abi, err := metadata.GetAbi() + if err != nil { + return common.Address{}, err + } + bin := common.FromHex(metadata.Bin) + client, err := evm.GetClient(rpcURL) + if err != nil { + return common.Address{}, err + } + defer client.Close() + txOpts, err := evm.GetTxOptsWithSigner(client, privateKey) + if err != nil { + return common.Address{}, err + } + address, tx, _, err := bind.DeployContract(txOpts, *abi, bin, client, params...) + if err != nil { + return common.Address{}, err + } + if _, success, err := evm.WaitForTransaction(client, tx); err != nil { + return common.Address{}, err + } else if !success { + return common.Address{}, fmt.Errorf("failed receipt status deploying contract") + } + return address, nil +} From d348164c2af0f85d7a9812726725f13420e3838d Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Tue, 11 Jun 2024 21:06:43 -0300 Subject: [PATCH 64/87] do not compile abi anymore --- pkg/bridge/build.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/bridge/build.go b/pkg/bridge/build.go index de80c5926..17a5e38e8 100644 --- a/pkg/bridge/build.go +++ b/pkg/bridge/build.go @@ -40,7 +40,6 @@ func BuildContracts( forgePath, "build", "--extra-output-files", - "abi", "bin", ) cmd.Dir = filepath.Join(repoDir, "contracts") From db8fe3c4ae450bfea253de06721d574e6b1c63fa Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Tue, 11 Jun 2024 21:10:10 -0300 Subject: [PATCH 65/87] lint --- cmd/keycmd/transfer.go | 9 +++++---- cmd/teleportercmd/bridgecmd/deploy.go | 1 - pkg/bridge/deploy.go | 1 - 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/cmd/keycmd/transfer.go b/cmd/keycmd/transfer.go index c5e197496..1603a0d6b 100644 --- a/cmd/keycmd/transfer.go +++ b/cmd/keycmd/transfer.go @@ -211,7 +211,7 @@ func transferF(*cobra.Command, []string) error { } blockchainID := sc.Networks[network.Name()].BlockchainID if blockchainID == ids.Empty { - return fmt.Errorf("subnet %s is not deployed to %s", originSubnet, network) + return fmt.Errorf("subnet %s is not deployed to %s", originSubnet, network.Name()) } originURL = network.BlockchainEndpoint(blockchainID.String()) } @@ -258,19 +258,20 @@ func transferF(*cobra.Command, []string) error { } privateKey := originK.PrivKeyHex() var destinationAddr goethereumcommon.Address - if destinationAddrStr != "" { + switch { + case destinationAddrStr != "": if err := prompts.ValidateAddress(destinationAddrStr); err != nil { return err } destinationAddr = goethereumcommon.HexToAddress(destinationAddrStr) - } else if destinationKeyName != "" { + case destinationKeyName != "": destinationK, err := app.GetKey(destinationKeyName, network, false) if err != nil { return err } destinationAddrStr = destinationK.C() destinationAddr = goethereumcommon.HexToAddress(destinationAddrStr) - } else { + default: return fmt.Errorf("you should set the destination address or destination key") } if amountFlt == 0 { diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index 045f384d6..144e38a7f 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -451,7 +451,6 @@ func CallDeploy(_ []string, flags DeployFlags) error { } if err := bridge.RegisterERC20Spoke( - bridgeSrcDir, spokeEndpoint, spokeKey.PrivKeyHex(), spokeAddress, diff --git a/pkg/bridge/deploy.go b/pkg/bridge/deploy.go index 6782de71d..43d292447 100644 --- a/pkg/bridge/deploy.go +++ b/pkg/bridge/deploy.go @@ -27,7 +27,6 @@ type TokenSpokeSettings struct { } func RegisterERC20Spoke( - srcDir string, rpcURL string, privateKey string, spokeAddress common.Address, From 6eef54605a1487429c6aa62cc030e75b37996a78 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Tue, 11 Jun 2024 22:15:08 -0300 Subject: [PATCH 66/87] add prompts to key transfer --- cmd/keycmd/transfer.go | 173 ++++++++++++++++++++----- cmd/teleportercmd/bridgecmd/helpers.go | 58 ++------- pkg/application/app.go | 18 +++ pkg/prompts/prompts.go | 50 +++++++ 4 files changed, 218 insertions(+), 81 deletions(-) diff --git a/cmd/keycmd/transfer.go b/cmd/keycmd/transfer.go index 1603a0d6b..0a3cd7fed 100644 --- a/cmd/keycmd/transfer.go +++ b/cmd/keycmd/transfer.go @@ -49,6 +49,7 @@ var ( transferSupportedNetworkOptions = []networkoptions.NetworkOption{ networkoptions.Mainnet, networkoptions.Fuji, + networkoptions.Devnet, networkoptions.Local, } send bool @@ -189,7 +190,7 @@ func transferF(*cobra.Command, []string) error { network, err := networkoptions.GetNetworkFromCmdLineFlags( app, - "", + "On what Network do you want to execute the transfer?", globalNetworkFlags, false, false, @@ -200,9 +201,77 @@ func transferF(*cobra.Command, []string) error { return err } + subnetNames, err := app.GetSubnetNamesOnNetwork(network) + if err != nil { + return err + } + + if originSubnet == "" && !PToX && !PToP { + prompt := "Where are the funds to transfer?" + cancel, pChain, _, cChain, subnetName, err := prompts.PromptChain( + app.Prompt, + prompt, + subnetNames, + false, + true, + false, + "", + ) + if err != nil { + return err + } + switch { + case cancel: + return nil + case pChain: + option, err := app.Prompt.CaptureList( + "Destination Chain", + []string{"P-Chain", "X-Chain"}, + ) + if err != nil { + return err + } + if option == "P-Chain" { + PToP = true + } else { + PToX = true + } + case cChain: + originSubnet = "c-chain" + default: + originSubnet = subnetName + } + } + // bridge experimental - // bridge hub -> spoke if originSubnet != "" { + if destinationSubnet == "" { + prompt := "Where are the funds going to?" + avoidSubnet := originSubnet + if originSubnet == "c-chain" { + avoidSubnet = "" + } + cancel, _, _, cChain, subnetName, err := prompts.PromptChain( + app.Prompt, + prompt, + subnetNames, + true, + true, + originSubnet == "c-chain", + avoidSubnet, + ) + if err != nil { + return err + } + switch { + case cancel: + return nil + case cChain: + destinationSubnet = "c-chain" + default: + destinationSubnet = subnetName + } + } originURL := network.CChainEndpoint() if strings.ToLower(originSubnet) != "c-chain" { sc, err := app.LoadSidecar(originSubnet) @@ -215,9 +284,6 @@ func transferF(*cobra.Command, []string) error { } originURL = network.BlockchainEndpoint(blockchainID.String()) } - if destinationSubnet == "" { - return fmt.Errorf("you should set destination subnet") - } var destinationBlockchainID ids.ID if strings.ToLower(destinationSubnet) == "c-chain" { destinationBlockchainID, err = utils.GetChainID(network.Endpoint, "C") @@ -236,21 +302,36 @@ func transferF(*cobra.Command, []string) error { destinationBlockchainID = blockchainID } if originBridgeAddress == "" { - return fmt.Errorf("you should set bridge address at origin") + addr, err := app.Prompt.CaptureAddress( + fmt.Sprintf("Enter the address of the Bridge on %s", originSubnet), + ) + if err != nil { + return err + } + originBridgeAddress = addr.Hex() } else { if err := prompts.ValidateAddress(originBridgeAddress); err != nil { return err } } if destinationBridgeAddress == "" { - return fmt.Errorf("you should set bridge address at destination") + addr, err := app.Prompt.CaptureAddress( + fmt.Sprintf("Enter the address of the Bridge on %s", destinationSubnet), + ) + if err != nil { + return err + } + destinationBridgeAddress = addr.Hex() } else { if err := prompts.ValidateAddress(destinationBridgeAddress); err != nil { return err } } if keyName == "" { - return fmt.Errorf("you should set the key that has the funds") + keyName, err = prompts.CaptureKeyName(app.Prompt, "fund the transfer", app.GetKeyDir(), true) + if err != nil { + return err + } } originK, err := app.GetKey(keyName, network, false) if err != nil { @@ -258,6 +339,30 @@ func transferF(*cobra.Command, []string) error { } privateKey := originK.PrivKeyHex() var destinationAddr goethereumcommon.Address + if destinationAddrStr == "" && destinationKeyName == "" { + option, err := app.Prompt.CaptureList( + "Do you want to choose a stored key for the destination, or input a destination address?", + []string{"Key", "Address"}, + ) + if err != nil { + return err + } + switch option { + case "Key": + destinationKeyName, err = prompts.CaptureKeyName(app.Prompt, "receive the transfer", app.GetKeyDir(), true) + if err != nil { + return err + } + case "Address": + addr, err := app.Prompt.CaptureAddress( + "Enter the destination address", + ) + if err != nil { + return err + } + destinationAddrStr = addr.Hex() + } + } switch { case destinationAddrStr != "": if err := prompts.ValidateAddress(destinationAddrStr); err != nil { @@ -275,7 +380,10 @@ func transferF(*cobra.Command, []string) error { return fmt.Errorf("you should set the destination address or destination key") } if amountFlt == 0 { - return fmt.Errorf("you should set the amount") + amountFlt, err = captureAmount(true, "TOKEN units") + if err != nil { + return err + } } amount := new(big.Float).SetFloat64(amountFlt) amount = amount.Mul(amount, new(big.Float).SetFloat64(float64(units.Avax))) @@ -337,21 +445,6 @@ func transferF(*cobra.Command, []string) error { } } - if !PToP && !PToX { - option, err := app.Prompt.CaptureList( - "Destination Chain", - []string{"P-Chain", "X-Chain"}, - ) - if err != nil { - return err - } - if option == "P-Chain" { - PToP = true - } else { - PToX = true - } - } - if keyName == "" && ledgerIndex == wrongLedgerIndexVal { var useLedger bool goalStr := "" @@ -373,18 +466,7 @@ func transferF(*cobra.Command, []string) error { } if amountFlt == 0 { - var promptStr string - if send { - promptStr = "Amount to send (AVAX units)" - } else { - promptStr = "Amount to receive (AVAX units)" - } - amountFlt, err = app.Prompt.CaptureFloat(promptStr, func(v float64) error { - if v <= 0 { - return fmt.Errorf("value %f must be greater than zero", v) - } - return nil - }) + amountFlt, err = captureAmount(send, "AVAX units") if err != nil { return err } @@ -646,3 +728,22 @@ func transferF(*cobra.Command, []string) error { return nil } + +func captureAmount(sending bool, tokenDesc string) (float64, error) { + var promptStr string + if sending { + promptStr = fmt.Sprintf("Amount to send (%s)", tokenDesc) + } else { + promptStr = fmt.Sprintf("Amount to receive (%s)", tokenDesc) + } + amountFlt, err := app.Prompt.CaptureFloat(promptStr, func(v float64) error { + if v <= 0 { + return fmt.Errorf("value %f must be greater than zero", v) + } + return nil + }) + if err != nil { + return 0, err + } + return amountFlt, nil +} diff --git a/cmd/teleportercmd/bridgecmd/helpers.go b/cmd/teleportercmd/bridgecmd/helpers.go index e36b0ab88..1f5b6c0de 100644 --- a/cmd/teleportercmd/bridgecmd/helpers.go +++ b/cmd/teleportercmd/bridgecmd/helpers.go @@ -5,30 +5,15 @@ package bridgecmd import ( _ "embed" "fmt" - "strings" "github.com/ava-labs/avalanche-cli/pkg/key" "github.com/ava-labs/avalanche-cli/pkg/models" + "github.com/ava-labs/avalanche-cli/pkg/prompts" "github.com/ava-labs/avalanche-cli/pkg/subnet" "github.com/ava-labs/avalanche-cli/pkg/utils" - "github.com/ava-labs/avalanche-cli/pkg/ux" "github.com/ava-labs/avalanchego/ids" ) -func filterSubnetsByNetwork(network models.Network, subnetNames []string) ([]string, error) { - filtered := []string{} - for _, subnetName := range subnetNames { - sc, err := app.LoadSidecar(subnetName) - if err != nil { - return nil, err - } - if sc.Networks[network.Name()].BlockchainID != ids.Empty { - filtered = append(filtered, subnetName) - } - } - return filtered, nil -} - func validateSubnet(network models.Network, subnetName string) error { sc, err := app.LoadSidecar(subnetName) if err != nil { @@ -47,41 +32,24 @@ func promptChain( avoidSubnet string, chainFlags *ChainFlags, ) (bool, error) { - subnetNames, err := app.GetSubnetNames() - if err != nil { - return false, err - } - subnetNames, err = filterSubnetsByNetwork(network, subnetNames) + subnetNames, err := app.GetSubnetNamesOnNetwork(network) if err != nil { return false, err } - subnetNames = utils.RemoveFromSlice(subnetNames, avoidSubnet) - cChainOption := "C-Chain" - notListedOption := "My blockchain isn't listed" - subnetOptions := []string{} - if !avoidCChain { - subnetOptions = append(subnetOptions, cChainOption) - } - subnetOptions = append(subnetOptions, utils.Map(subnetNames, func(s string) string { return "Subnet " + s })...) - subnetOptions = append(subnetOptions, notListedOption) - subnetOption, err := app.Prompt.CaptureListWithSize( + cancel, _, _, cChain, subnetName, err := prompts.PromptChain( + app.Prompt, prompt, - subnetOptions, - 11, + subnetNames, + true, + true, + avoidCChain, + avoidSubnet, ) - if err != nil { - return false, err - } - if subnetOption == notListedOption { - ux.Logger.PrintToUser("Please import the subnet first, using the `avalanche subnet import` command suite") - return true, nil - } - if subnetOption == cChainOption { - chainFlags.CChain = true - } else { - chainFlags.SubnetName = strings.TrimPrefix(subnetOption, "Subnet ") + if err == nil { + chainFlags.SubnetName = subnetName + chainFlags.CChain = cChain } - return false, nil + return cancel, err } func GetSubnetParams( diff --git a/pkg/application/app.go b/pkg/application/app.go index 5eafe7622..5bccf2317 100644 --- a/pkg/application/app.go +++ b/pkg/application/app.go @@ -631,6 +631,24 @@ func (app *Avalanche) GetSubnetNames() ([]string, error) { return names, nil } +func (app *Avalanche) GetSubnetNamesOnNetwork(network models.Network) ([]string, error) { + subnetNames, err := app.GetSubnetNames() + if err != nil { + return nil, err + } + filtered := []string{} + for _, subnetName := range subnetNames { + sc, err := app.LoadSidecar(subnetName) + if err != nil { + return nil, err + } + if sc.Networks[network.Name()].BlockchainID != ids.Empty { + filtered = append(filtered, subnetName) + } + } + return filtered, nil +} + func (*Avalanche) readFile(path string) ([]byte, error) { if err := os.MkdirAll(filepath.Dir(path), constants.DefaultPerms755); err != nil { return nil, err diff --git a/pkg/prompts/prompts.go b/pkg/prompts/prompts.go index 86cf7ddaa..e5289a880 100644 --- a/pkg/prompts/prompts.go +++ b/pkg/prompts/prompts.go @@ -884,3 +884,53 @@ func CaptureBoolFlag( return cmd.Flags().GetBool(flagName) } } + +func PromptChain( + prompter Prompter, + prompt string, + subnetNames []string, + avoidPChain bool, + avoidXChain bool, + avoidCChain bool, + avoidSubnet string, +) (bool, bool, bool, bool, string, error) { + pChainOption := "P-Chain" + xChainOption := "X-Chain" + cChainOption := "C-Chain" + notListedOption := "My blockchain isn't listed" + subnetOptions := []string{} + if !avoidPChain { + subnetOptions = append(subnetOptions, pChainOption) + } + if !avoidXChain { + subnetOptions = append(subnetOptions, xChainOption) + } + if !avoidCChain { + subnetOptions = append(subnetOptions, cChainOption) + } + subnetNames = utils.RemoveFromSlice(subnetNames, avoidSubnet) + subnetOptions = append(subnetOptions, utils.Map(subnetNames, func(s string) string { return "Subnet " + s })...) + subnetOptions = append(subnetOptions, notListedOption) + subnetOption, err := prompter.CaptureListWithSize( + prompt, + subnetOptions, + 11, + ) + if err != nil { + return false, false, false, false, "", err + } + if subnetOption == notListedOption { + ux.Logger.PrintToUser("Please import the subnet first, using the `avalanche subnet import` command suite") + return true, false, false, false, "", nil + } + switch subnetOption { + case pChainOption: + return false, true, false, false, "", nil + case xChainOption: + return false, false, true, false, "", nil + case cChainOption: + return false, false, false, true, "", nil + default: + return false, false, false, false, strings.TrimPrefix(subnetOption, "Subnet "), nil + } +} From 42197c8531dadab56a57df658ddfb1446a678e47 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Tue, 11 Jun 2024 22:21:14 -0300 Subject: [PATCH 67/87] lint --- cmd/keycmd/transfer.go | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/cmd/keycmd/transfer.go b/cmd/keycmd/transfer.go index 0a3cd7fed..2c2d5dbe2 100644 --- a/cmd/keycmd/transfer.go +++ b/cmd/keycmd/transfer.go @@ -35,6 +35,7 @@ import ( ) const ( + cChain = "c-chain" sendFlag = "send" receiveFlag = "receive" keyNameFlag = "key" @@ -208,7 +209,7 @@ func transferF(*cobra.Command, []string) error { if originSubnet == "" && !PToX && !PToP { prompt := "Where are the funds to transfer?" - cancel, pChain, _, cChain, subnetName, err := prompts.PromptChain( + cancel, pChainChoosen, _, cChainChoosen, subnetName, err := prompts.PromptChain( app.Prompt, prompt, subnetNames, @@ -223,7 +224,7 @@ func transferF(*cobra.Command, []string) error { switch { case cancel: return nil - case pChain: + case pChainChoosen: option, err := app.Prompt.CaptureList( "Destination Chain", []string{"P-Chain", "X-Chain"}, @@ -236,8 +237,8 @@ func transferF(*cobra.Command, []string) error { } else { PToX = true } - case cChain: - originSubnet = "c-chain" + case cChainChoosen: + originSubnet = cChain default: originSubnet = subnetName } @@ -248,16 +249,16 @@ func transferF(*cobra.Command, []string) error { if destinationSubnet == "" { prompt := "Where are the funds going to?" avoidSubnet := originSubnet - if originSubnet == "c-chain" { + if originSubnet == cChain { avoidSubnet = "" } - cancel, _, _, cChain, subnetName, err := prompts.PromptChain( + cancel, _, _, cChainChoosen, subnetName, err := prompts.PromptChain( app.Prompt, prompt, subnetNames, true, true, - originSubnet == "c-chain", + originSubnet == cChain, avoidSubnet, ) if err != nil { @@ -266,14 +267,14 @@ func transferF(*cobra.Command, []string) error { switch { case cancel: return nil - case cChain: - destinationSubnet = "c-chain" + case cChainChoosen: + destinationSubnet = cChain default: destinationSubnet = subnetName } } originURL := network.CChainEndpoint() - if strings.ToLower(originSubnet) != "c-chain" { + if strings.ToLower(originSubnet) != cChain { sc, err := app.LoadSidecar(originSubnet) if err != nil { return err @@ -285,7 +286,7 @@ func transferF(*cobra.Command, []string) error { originURL = network.BlockchainEndpoint(blockchainID.String()) } var destinationBlockchainID ids.ID - if strings.ToLower(destinationSubnet) == "c-chain" { + if strings.ToLower(destinationSubnet) == cChain { destinationBlockchainID, err = utils.GetChainID(network.Endpoint, "C") if err != nil { return err From c952590b6b27101cccd70a136988573ce6f583ab Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Tue, 11 Jun 2024 23:04:01 -0300 Subject: [PATCH 68/87] add subnets flag to list to select different subnet balances --- cmd/keycmd/create.go | 2 +- cmd/keycmd/list.go | 121 ++++++++++++++++++++++++------------------- 2 files changed, 69 insertions(+), 54 deletions(-) diff --git a/cmd/keycmd/create.go b/cmd/keycmd/create.go index 15963ddba..30a943b61 100644 --- a/cmd/keycmd/create.go +++ b/cmd/keycmd/create.go @@ -57,7 +57,7 @@ func createKey(_ *cobra.Command, args []string) error { pchain := true cchain := true xchain := true - clients, err := getClients(networks, pchain, cchain, xchain, "") + clients, err := getClients(networks, pchain, cchain, xchain, nil) if err != nil { return err } diff --git a/cmd/keycmd/list.go b/cmd/keycmd/list.go index 3168dc9fe..a6da40777 100644 --- a/cmd/keycmd/list.go +++ b/cmd/keycmd/list.go @@ -6,7 +6,6 @@ import ( "fmt" "math/big" "os" - "strings" "github.com/ava-labs/avalanche-cli/cmd/subnetcmd" "github.com/ava-labs/avalanche-cli/pkg/key" @@ -32,7 +31,6 @@ const ( pchainFlag = "pchain" cchainFlag = "cchain" xchainFlag = "xchain" - chainsFlag = "chains" ledgerIndicesFlag = "ledger" useNanoAvaxFlag = "use-nano-avax" keysFlag = "keys" @@ -45,13 +43,12 @@ var ( pchain bool cchain bool xchain bool - chains string useNanoAvax bool ledgerIndices []uint - subnetName string keys []string tokenAddresses []string subnetToken string + subnets []string ) // avalanche subnet list @@ -110,17 +107,11 @@ keys or for the ledger addresses associated to certain indices.`, []string{}, "list addresses for the given keys", ) - cmd.Flags().StringVar( - &subnetName, - "subnet", - "", - "provide balance information for the given subnet (Subnet-Evm based only)", - ) - cmd.Flags().StringVar( - &chains, - chainsFlag, - "pxc", - "short way to specify which chains to show information about (p=show p-chain, x=show x-chain, c=show c-chain). defaults to pxc", + cmd.Flags().StringSliceVar( + &subnets, + "subnets", + []string{}, + "specify which subnets to show information about (p=p-chain, x=x-chain, c=c-chain, and subnet names). defaults to `p,x,c`", ) cmd.Flags().StringSliceVar( &tokenAddresses, @@ -135,12 +126,12 @@ type Clients struct { x map[models.Network]avm.Client p map[models.Network]platformvm.Client c map[models.Network]ethclient.Client - evm map[models.Network]ethclient.Client cGeth map[models.Network]*goethereumethclient.Client - evmGeth map[models.Network]*goethereumethclient.Client + evm map[models.Network]map[string]ethclient.Client + evmGeth map[models.Network]map[string]*goethereumethclient.Client } -func getClients(networks []models.Network, pchain bool, cchain bool, xchain bool, subnetName string) ( +func getClients(networks []models.Network, pchain bool, cchain bool, xchain bool, subnets []string) ( *Clients, error, ) { @@ -148,9 +139,9 @@ func getClients(networks []models.Network, pchain bool, cchain bool, xchain bool xClients := map[models.Network]avm.Client{} pClients := map[models.Network]platformvm.Client{} cClients := map[models.Network]ethclient.Client{} - evmClients := map[models.Network]ethclient.Client{} cGethClients := map[models.Network]*goethereumethclient.Client{} - evmGethClients := map[models.Network]*goethereumethclient.Client{} + evmClients := map[models.Network]map[string]ethclient.Client{} + evmGethClients := map[models.Network]map[string]*goethereumethclient.Client{} for _, network := range networks { if pchain { pClients[network] = platformvm.NewClient(network.Endpoint) @@ -170,32 +161,42 @@ func getClients(networks []models.Network, pchain bool, cchain bool, xchain bool } } } - if subnetName != "" { - _, err = subnetcmd.ValidateSubnetNameAndGetChains([]string{subnetName}) - if err != nil { - return nil, err - } - b, _, err := subnetcmd.HasSubnetEVMGenesis(subnetName) - if err != nil { - return nil, err - } - if b { - sc, err := app.LoadSidecar(subnetName) + for _, subnetName := range subnets { + if subnetName != "p" && subnetName != "x" && subnetName != "c" { + _, err = subnetcmd.ValidateSubnetNameAndGetChains([]string{subnetName}) + if err != nil { + return nil, err + } + b, _, err := subnetcmd.HasSubnetEVMGenesis(subnetName) if err != nil { return nil, err } - subnetToken = sc.TokenSymbol - chainID := sc.Networks[network.Name()].BlockchainID - if chainID != ids.Empty { - evmClients[network], err = ethclient.Dial(network.BlockchainEndpoint(chainID.String())) + if b { + sc, err := app.LoadSidecar(subnetName) if err != nil { return nil, err } - if len(tokenAddresses) != 0 { - evmGethClients[network], err = goethereumethclient.Dial(network.BlockchainEndpoint(chainID.String())) + subnetToken = sc.TokenSymbol + chainID := sc.Networks[network.Name()].BlockchainID + if chainID != ids.Empty { + _, b := evmClients[network] + if !b { + evmClients[network] = map[string]ethclient.Client{} + } + evmClients[network][subnetName], err = ethclient.Dial(network.BlockchainEndpoint(chainID.String())) if err != nil { return nil, err } + if len(tokenAddresses) != 0 { + _, b := evmGethClients[network] + if !b { + evmGethClients[network] = map[string]*goethereumethclient.Client{} + } + evmGethClients[network][subnetName], err = goethereumethclient.Dial(network.BlockchainEndpoint(chainID.String())) + if err != nil { + return nil, err + } + } } } } @@ -248,20 +249,23 @@ func listKeys(*cobra.Command, []string) error { false, false, listSupportedNetworkOptions, - subnetName, + "", ) if err != nil { return err } networks = append(networks, network) } - if !strings.Contains(chains, "p") { + if len(subnets) == 0 { + subnets = []string{"p", "x", "c"} + } + if !utils.Belongs(subnets, "p") { pchain = false } - if !strings.Contains(chains, "x") { + if !utils.Belongs(subnets, "x") { xchain = false } - if !strings.Contains(chains, "c") { + if !utils.Belongs(subnets, "c") { cchain = false } queryLedger := len(ledgerIndices) > 0 @@ -270,7 +274,7 @@ func listKeys(*cobra.Command, []string) error { cchain = false xchain = false } - clients, err := getClients(networks, pchain, cchain, xchain, subnetName) + clients, err := getClients(networks, pchain, cchain, xchain, subnets) if err != nil { return err } @@ -328,15 +332,26 @@ func getStoredKeyInfo( } if _, ok := clients.evm[network]; ok { evmAddr := sk.C() - addrInfo, err := getEvmBasedChainAddrInfo(subnetName, subnetToken, clients.evm, clients.evmGeth, network, evmAddr, "stored", keyName) - if err != nil { - return nil, err + for subnetName := range clients.evm[network] { + addrInfo, err := getEvmBasedChainAddrInfo( + subnetName, + subnetToken, + clients.evm[network][subnetName], + clients.evmGeth[network][subnetName], + network, + evmAddr, + "stored", + keyName, + ) + if err != nil { + return nil, err + } + addrInfos = append(addrInfos, addrInfo...) } - addrInfos = append(addrInfos, addrInfo...) } if _, ok := clients.c[network]; ok { cChainAddr := sk.C() - addrInfo, err := getEvmBasedChainAddrInfo("C-Chain", "AVAX", clients.c, clients.cGeth, network, cChainAddr, "stored", keyName) + addrInfo, err := getEvmBasedChainAddrInfo("C-Chain", "AVAX", clients.c[network], clients.cGeth[network], network, cChainAddr, "stored", keyName) if err != nil { return nil, err } @@ -474,14 +489,14 @@ func getXChainAddrInfo( func getEvmBasedChainAddrInfo( chainName string, chainToken string, - cClients map[models.Network]ethclient.Client, - cGethClients map[models.Network]*goethereumethclient.Client, + cClient ethclient.Client, + cGethClient *goethereumethclient.Client, network models.Network, cChainAddr string, kind string, name string, ) ([]addressInfo, error) { - cChainBalance, err := getCChainBalanceStr(cClients[network], cChainAddr) + cChainBalance, err := getCChainBalanceStr(cClient, cChainAddr) if err != nil { // just ignore local network errors if network.Kind != models.Local { @@ -502,9 +517,9 @@ func getEvmBasedChainAddrInfo( network: network.Name(), } addressInfos := []addressInfo{info} - if cGethClients != nil && cGethClients[network] != nil { + if cGethClient != nil { for _, tokenAddress := range tokenAddresses { - token, err := erc20.NewGGToken(common.HexToAddress(tokenAddress), cGethClients[network]) + token, err := erc20.NewGGToken(common.HexToAddress(tokenAddress), cGethClient) if err != nil { return addressInfos, err } @@ -536,7 +551,7 @@ func getEvmBasedChainAddrInfo( } func printAddrInfos(addrInfos []addressInfo) { - header := []string{"Kind", "Name", "Chain", "Address", "Token", "Balance", "Network"} + header := []string{"Kind", "Name", "Subnet", "Address", "Token", "Balance", "Network"} table := tablewriter.NewWriter(os.Stdout) table.SetHeader(header) table.SetRowLine(true) From 3895c561c6f15df80b20969f37ea16304c37c24b Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Tue, 11 Jun 2024 23:17:31 -0300 Subject: [PATCH 69/87] nit --- cmd/keycmd/list.go | 27 ++++++++++++++++----------- pkg/bridge/deploy.go | 2 +- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/cmd/keycmd/list.go b/cmd/keycmd/list.go index a6da40777..bf1a7570a 100644 --- a/cmd/keycmd/list.go +++ b/cmd/keycmd/list.go @@ -38,17 +38,22 @@ const ( var ( globalNetworkFlags networkoptions.NetworkFlags - listSupportedNetworkOptions = []networkoptions.NetworkOption{networkoptions.Mainnet, networkoptions.Fuji, networkoptions.Local, networkoptions.Cluster} - all bool - pchain bool - cchain bool - xchain bool - useNanoAvax bool - ledgerIndices []uint - keys []string - tokenAddresses []string - subnetToken string - subnets []string + listSupportedNetworkOptions = []networkoptions.NetworkOption{ + networkoptions.Mainnet, + networkoptions.Fuji, + networkoptions.Local, + networkoptions.Devnet, + } + all bool + pchain bool + cchain bool + xchain bool + useNanoAvax bool + ledgerIndices []uint + keys []string + tokenAddresses []string + subnetToken string + subnets []string ) // avalanche subnet list diff --git a/pkg/bridge/deploy.go b/pkg/bridge/deploy.go index 43d292447..07fd251f6 100644 --- a/pkg/bridge/deploy.go +++ b/pkg/bridge/deploy.go @@ -1,4 +1,4 @@ -// Cpopyright (C) 2022, Ava Labs, Inc. All rights reserved. +// Copyright (C) 2022, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. package bridge From 49a7561d71dcd49b30f6c5b726ff25c94ed5855c Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Tue, 11 Jun 2024 23:31:51 -0300 Subject: [PATCH 70/87] fix e2e --- tests/e2e/testcases/key/suite.go | 2 +- tests/e2e/utils/helpers.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/e2e/testcases/key/suite.go b/tests/e2e/testcases/key/suite.go index fe20f8f72..298e0bbad 100644 --- a/tests/e2e/testcases/key/suite.go +++ b/tests/e2e/testcases/key/suite.go @@ -132,7 +132,7 @@ var _ = ginkgo.Describe("[Key]", func() { // if there are independent regexes instead of one large one, // difficult to understand (go regexes don't support Perl regex // Go RE2 library doesn't support lookahead and lookbehind - regex1 := `.*NAME.*CHAIN.*ADDRESS.*NETWORK` + regex1 := `.*NAME.*SUBNET.*ADDRESS.*NETWORK` regex2 := `.*e2eKey.*C-Chain.*0x[a-fA-F0-9]{40}` regex3 := `.*P-Chain.*[(P-custom)(P-fuji)][a-zA-Z0-9]{39}` regex4 := `.*P-avax[a-zA-Z0-9]{39}` diff --git a/tests/e2e/utils/helpers.go b/tests/e2e/utils/helpers.go index 9bca0570d..aca0c642c 100644 --- a/tests/e2e/utils/helpers.go +++ b/tests/e2e/utils/helpers.go @@ -42,7 +42,7 @@ import ( ) const ( - expectedKeyListLineComponents = 8 + expectedKeyListLineComponents = 9 expectedRPCComponentsLen = 7 blockchainIDPos = 5 subnetEVMName = "subnet-evm" @@ -398,7 +398,7 @@ func ParseAddrBalanceFromKeyListOutput(output string, keyName string) (string, u ) } addr := strings.TrimSpace(components[4]) - balanceStr := strings.TrimSpace(components[5]) + balanceStr := strings.TrimSpace(components[6]) balance, err := strconv.ParseUint(balanceStr, 0, 64) if err != nil { return "", 0, fmt.Errorf("error parsing expected float %s", balanceStr) From 3084d1c0073cd7f0a685e3b6ab9fa87d13b2c998 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Tue, 11 Jun 2024 23:50:07 -0300 Subject: [PATCH 71/87] fix key e2e --- cmd/keycmd/create.go | 37 ++++++++++++++++++++------------ tests/e2e/commands/key.go | 3 ++- tests/e2e/testcases/key/suite.go | 4 ++-- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/cmd/keycmd/create.go b/cmd/keycmd/create.go index 30a943b61..cc5b562dc 100644 --- a/cmd/keycmd/create.go +++ b/cmd/keycmd/create.go @@ -18,8 +18,9 @@ const ( ) var ( - forceCreate bool - filename string + forceCreate bool + skipBalances bool + filename string ) func createKey(_ *cobra.Command, args []string) error { @@ -53,19 +54,21 @@ func createKey(_ *cobra.Command, args []string) error { return err } ux.Logger.PrintToUser("Key loaded") - networks := []models.Network{models.NewFujiNetwork(), models.NewMainnetNetwork()} - pchain := true - cchain := true - xchain := true - clients, err := getClients(networks, pchain, cchain, xchain, nil) - if err != nil { - return err + if !skipBalances { + networks := []models.Network{models.NewFujiNetwork(), models.NewMainnetNetwork()} + pchain := true + cchain := true + xchain := true + clients, err := getClients(networks, pchain, cchain, xchain, nil) + if err != nil { + return err + } + addrInfos, err := getStoredKeyInfo(clients, networks, keyName) + if err != nil { + return err + } + printAddrInfos(addrInfos) } - addrInfos, err := getStoredKeyInfo(clients, networks, keyName) - if err != nil { - return err - } - printAddrInfos(addrInfos) } return nil @@ -101,5 +104,11 @@ If you'd like to import an existing key instead of generating one from scratch, false, "overwrite an existing key with the same name", ) + cmd.Flags().BoolVar( + &skipBalances, + "skip-balances", + false, + "do not query public network balances for an imported key", + ) return cmd } diff --git a/tests/e2e/commands/key.go b/tests/e2e/commands/key.go index 806869205..31525c5e7 100644 --- a/tests/e2e/commands/key.go +++ b/tests/e2e/commands/key.go @@ -33,6 +33,7 @@ func CreateKeyFromPath(keyName string, keyPath string) (string, error) { "--file", keyPath, keyName, + "--skip-balances", "--"+constants.SkipUpdateFlag, ) out, err := cmd.Output() @@ -127,7 +128,7 @@ func KeyTransferSend(keyName string, targetAddr string, amount string) (string, "--key", keyName, "--send", - "--target-addr", + "--destination-addr", targetAddr, "--amount", amount, diff --git a/tests/e2e/testcases/key/suite.go b/tests/e2e/testcases/key/suite.go index 298e0bbad..2e75f86a7 100644 --- a/tests/e2e/testcases/key/suite.go +++ b/tests/e2e/testcases/key/suite.go @@ -135,7 +135,7 @@ var _ = ginkgo.Describe("[Key]", func() { regex1 := `.*NAME.*SUBNET.*ADDRESS.*NETWORK` regex2 := `.*e2eKey.*C-Chain.*0x[a-fA-F0-9]{40}` regex3 := `.*P-Chain.*[(P-custom)(P-fuji)][a-zA-Z0-9]{39}` - regex4 := `.*P-avax[a-zA-Z0-9]{39}` + regex4 := `.*P-fuji[a-zA-Z0-9]{39}` // Create a key output, err := commands.CreateKey(keyName) @@ -146,7 +146,7 @@ var _ = ginkgo.Describe("[Key]", func() { gomega.Expect(err).Should(gomega.BeNil()) // Call list cmd - output, err = commands.ListKeys("mainnet", false, false) + output, err = commands.ListKeys("fuji", false, false) if err != nil { fmt.Println(output) utils.PrintStdErr(err) From 00c04b69a96ae470124502e70f8fbf6502f9f68e Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Wed, 12 Jun 2024 07:11:59 -0300 Subject: [PATCH 72/87] fix recommended tags --- cmd/teleportercmd/bridgecmd/deploy.go | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/cmd/teleportercmd/bridgecmd/deploy.go b/cmd/teleportercmd/bridgecmd/deploy.go index 144e38a7f..6f834796d 100644 --- a/cmd/teleportercmd/bridgecmd/deploy.go +++ b/cmd/teleportercmd/bridgecmd/deploy.go @@ -128,8 +128,8 @@ func CallDeploy(_ []string, flags DeployFlags) error { return err } prompt := "What kind of token do you want to bridge?" - popularOption := "A popular token (e.g. AVAX, USDC, WAVAX, ...)" - hubDeployedOption := "A token that already has a Hub deployed" + popularOption := "A popular token (e.g. AVAX, USDC, WAVAX, ...) (recommended)" + hubDeployedOption := "A token that already has a Hub deployed (recommended)" deployNewHubOption := "Deploy a new Hub for the token" explainOption := "Explain the difference" goBackOption := "Go Back" @@ -144,11 +144,7 @@ func CallDeploy(_ []string, flags DeployFlags) error { popularTokensDesc := utils.Map( popularTokensInfo, func(i PopularTokenInfo) string { - if i.BridgeHubAddress == "" { - return i.Desc() - } else { - return i.Desc() + " (recommended)" - } + return i.Desc() }, ) options := []string{popularOption, hubDeployedOption, deployNewHubOption, explainOption} @@ -211,7 +207,7 @@ func CallDeploy(_ []string, flags DeployFlags) error { ux.Logger.PrintToUser("There already is a Token Hub for %s deployed on %s.", p.TokenName, hubChain) ux.Logger.PrintToUser("") ux.Logger.PrintToUser("Hub Address: %s", p.BridgeHubAddress) - deployANewHupOption := "Yes, use the existing Hub" + deployANewHupOption := "Yes, use the existing Hub (recommended)" useTheExistingHubOption := "No, deploy my own Hub" options := []string{deployANewHupOption, useTheExistingHubOption, explainOption} option, err := app.Prompt.CaptureList( From 28846084a31c4d6e07df932443b41b2c4ca8df92 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Wed, 12 Jun 2024 08:36:35 -0300 Subject: [PATCH 73/87] enable filtering out native token on key list --- cmd/keycmd/list.go | 70 ++++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/cmd/keycmd/list.go b/cmd/keycmd/list.go index bf1a7570a..7ba326866 100644 --- a/cmd/keycmd/list.go +++ b/cmd/keycmd/list.go @@ -44,16 +44,17 @@ var ( networkoptions.Local, networkoptions.Devnet, } - all bool - pchain bool - cchain bool - xchain bool - useNanoAvax bool - ledgerIndices []uint - keys []string - tokenAddresses []string - subnetToken string - subnets []string + all bool + pchain bool + cchain bool + xchain bool + useNanoAvax bool + ledgerIndices []uint + keys []string + tokenAddresses []string + subnetToken string + subnets []string + showNativeToken bool ) // avalanche subnet list @@ -116,12 +117,12 @@ keys or for the ledger addresses associated to certain indices.`, &subnets, "subnets", []string{}, - "specify which subnets to show information about (p=p-chain, x=x-chain, c=c-chain, and subnet names). defaults to `p,x,c`", + "subnets to show information about (p=p-chain, x=x-chain, c=c-chain, and subnet names) (default p,x,c)", ) cmd.Flags().StringSliceVar( &tokenAddresses, "tokens", - []string{}, + []string{"Native"}, "provide balance information for the given token contract addresses (Evm only)", ) return cmd @@ -279,6 +280,10 @@ func listKeys(*cobra.Command, []string) error { cchain = false xchain = false } + if utils.Belongs(tokenAddresses, "Native") { + showNativeToken = true + } + tokenAddresses = utils.RemoveFromSlice(tokenAddresses, "Native") clients, err := getClients(networks, pchain, cchain, xchain, subnets) if err != nil { return err @@ -501,27 +506,30 @@ func getEvmBasedChainAddrInfo( kind string, name string, ) ([]addressInfo, error) { - cChainBalance, err := getCChainBalanceStr(cClient, cChainAddr) - if err != nil { - // just ignore local network errors - if network.Kind != models.Local { - return nil, err + addressInfos := []addressInfo{} + if showNativeToken { + cChainBalance, err := getCChainBalanceStr(cClient, cChainAddr) + if err != nil { + // just ignore local network errors + if network.Kind != models.Local { + return nil, err + } } + taggedChainToken := chainToken + if taggedChainToken != "AVAX" { + taggedChainToken = fmt.Sprintf("%s (Native)", taggedChainToken) + } + info := addressInfo{ + kind: kind, + name: name, + chain: chainName, + token: taggedChainToken, + address: cChainAddr, + balance: cChainBalance, + network: network.Name(), + } + addressInfos = append(addressInfos, info) } - taggedChainToken := chainToken - if taggedChainToken != "AVAX" { - taggedChainToken = fmt.Sprintf("%s (Native)", taggedChainToken) - } - info := addressInfo{ - kind: kind, - name: name, - chain: chainName, - token: taggedChainToken, - address: cChainAddr, - balance: cChainBalance, - network: network.Name(), - } - addressInfos := []addressInfo{info} if cGethClient != nil { for _, tokenAddress := range tokenAddresses { token, err := erc20.NewGGToken(common.HexToAddress(tokenAddress), cGethClient) From f4dc802b6a13e3c0d510042c5b6c5ada5f85d47e Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Wed, 12 Jun 2024 08:54:52 -0300 Subject: [PATCH 74/87] make transaction commit to wait for tx acceptance --- cmd/transactioncmd/transaction_commit.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/transactioncmd/transaction_commit.go b/cmd/transactioncmd/transaction_commit.go index 25e618ea7..8a27734fc 100644 --- a/cmd/transactioncmd/transaction_commit.go +++ b/cmd/transactioncmd/transaction_commit.go @@ -83,7 +83,7 @@ func commitTx(_ *cobra.Command, args []string) error { } deployer := subnet.NewPublicDeployer(app, keychain.NewKeychain(network, kc, nil, nil), network) - txID, err := deployer.Commit(tx, false) + txID, err := deployer.Commit(tx, true) if err != nil { return err } From 669d5b12cb9d6b29994749c2ef198afc4ae537b4 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Wed, 12 Jun 2024 09:54:38 -0300 Subject: [PATCH 75/87] download registry bytecode --- pkg/teleporter/teleporter.go | 175 ++++++++++++++++++++--------------- 1 file changed, 100 insertions(+), 75 deletions(-) diff --git a/pkg/teleporter/teleporter.go b/pkg/teleporter/teleporter.go index d28211d7f..01241554a 100644 --- a/pkg/teleporter/teleporter.go +++ b/pkg/teleporter/teleporter.go @@ -20,60 +20,66 @@ import ( "github.com/ava-labs/subnet-evm/accounts/abi/bind" "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/ethclient" - teleporterRegistry "github.com/ava-labs/teleporter/abi-bindings/go/Teleporter/upgrades/TeleporterRegistry" + registry "github.com/ava-labs/teleporter/abi-bindings/go/Teleporter/upgrades/TeleporterRegistry" "github.com/ethereum/go-ethereum/common" ) const ( - // TODO: use abi without any download? - teleporterReleaseURL = "https://github.com/ava-labs/teleporter/releases/download/%s/" - teleporterMessengerContractAddressURLFmt = teleporterReleaseURL + "/TeleporterMessenger_Contract_Address_%s.txt" - teleporterMessengerDeployerAddressURLFmt = teleporterReleaseURL + "/TeleporterMessenger_Deployer_Address_%s.txt" - teleporterMessengerDeployerTxURLFmt = teleporterReleaseURL + "/TeleporterMessenger_Deployment_Transaction_%s.txt" + releaseURL = "https://github.com/ava-labs/teleporter/releases/download/%s/" + messengerContractAddressURLFmt = releaseURL + "/TeleporterMessenger_Contract_Address_%s.txt" + messengerDeployerAddressURLFmt = releaseURL + "/TeleporterMessenger_Deployer_Address_%s.txt" + messengerDeployerTxURLFmt = releaseURL + "/TeleporterMessenger_Deployment_Transaction_%s.txt" + registryBytecodeURLFmt = releaseURL + "/TeleporterRegisrtry_Bytecode_%s.txt" ) var ( - teleporterMessengerDeployerRequiredBalance = big.NewInt(0). - Mul(big.NewInt(1e18), big.NewInt(10)) + messengerDeployerRequiredBalance = big.NewInt(0). + Mul(big.NewInt(1e18), big.NewInt(10)) // 10 AVAX TeleporterPrefundedAddressBalance = big.NewInt(0). Mul(big.NewInt(1e18), big.NewInt(600)) // 600 AVAX ) -func getTeleporterURLs(version string) (string, string, string) { - teleporterMessengerContractAddressURL := fmt.Sprintf( - teleporterMessengerContractAddressURLFmt, +func getTeleporterURLs(version string) (string, string, string, string) { + messengerContractAddressURL := fmt.Sprintf( + messengerContractAddressURLFmt, version, version, ) - teleporterMessengerDeployerAddressURL := fmt.Sprintf( - teleporterMessengerDeployerAddressURLFmt, + messengerDeployerAddressURL := fmt.Sprintf( + messengerDeployerAddressURLFmt, version, version, ) - teleporterMessengerDeployerTxURL := fmt.Sprintf( - teleporterMessengerDeployerTxURLFmt, + messengerDeployerTxURL := fmt.Sprintf( + messengerDeployerTxURLFmt, version, version, ) - return teleporterMessengerContractAddressURL, teleporterMessengerDeployerAddressURL, teleporterMessengerDeployerTxURL + registryBydecodeURL := fmt.Sprintf( + registryBytecodeURLFmt, + version, + version, + ) + return messengerContractAddressURL, messengerDeployerAddressURL, messengerDeployerTxURL, registryBydecodeURL } type Deployer struct { - teleporterMessengerContractAddress string - teleporterMessengerDeployerAddress string - teleporterMessengerDeployerTx string + messengerContractAddress string + messengerDeployerAddress string + messengerDeployerTx string + registryBydecode string } func (t *Deployer) GetAssets( teleporterInstallDir string, version string, -) (string, string, string, error) { +) (string, string, string, string, error) { if err := t.DownloadAssets(teleporterInstallDir, version); err != nil { - return "", "", "", err + return "", "", "", "", err } - return t.teleporterMessengerContractAddress, t.teleporterMessengerDeployerAddress, t.teleporterMessengerDeployerTx, nil + return t.messengerContractAddress, t.messengerDeployerAddress, t.messengerDeployerTx, t.registryBydecode, nil } func (t *Deployer) DownloadAssets( @@ -82,71 +88,90 @@ func (t *Deployer) DownloadAssets( ) error { var err error binDir := filepath.Join(teleporterInstallDir, version) - teleporterMessengerContractAddressURL, teleporterMessengerDeployerAddressURL, teleporterMessengerDeployerTxURL := getTeleporterURLs( + messengerContractAddressURL, messengerDeployerAddressURL, messengerDeployerTxURL, registryBydecodeURL := getTeleporterURLs( version, ) - teleporterMessengerContractAddressPath := filepath.Join( + messengerContractAddressPath := filepath.Join( + binDir, + filepath.Base(messengerContractAddressURL), + ) + messengerDeployerAddressPath := filepath.Join( binDir, - filepath.Base(teleporterMessengerContractAddressURL), + filepath.Base(messengerDeployerAddressURL), ) - teleporterMessengerDeployerAddressPath := filepath.Join( + messengerDeployerTxPath := filepath.Join( binDir, - filepath.Base(teleporterMessengerDeployerAddressURL), + filepath.Base(messengerDeployerTxURL), ) - teleporterMessengerDeployerTxPath := filepath.Join( + registryBytecodePath := filepath.Join( binDir, - filepath.Base(teleporterMessengerDeployerTxURL), + filepath.Base(registryBydecodeURL), ) - if t.teleporterMessengerContractAddress == "" { - var teleporterMessengerContractAddressBytes []byte - if utils.FileExists(teleporterMessengerContractAddressPath) { - teleporterMessengerContractAddressBytes, err = os.ReadFile( - teleporterMessengerContractAddressPath, + if t.messengerContractAddress == "" { + var messengerContractAddressBytes []byte + if utils.FileExists(messengerContractAddressPath) { + messengerContractAddressBytes, err = os.ReadFile( + messengerContractAddressPath, ) if err != nil { return err } } else { // get target teleporter messenger contract address - teleporterMessengerContractAddressBytes, err = utils.DownloadWithTee(teleporterMessengerContractAddressURL, teleporterMessengerContractAddressPath) + messengerContractAddressBytes, err = utils.DownloadWithTee(messengerContractAddressURL, messengerContractAddressPath) if err != nil { return err } } - t.teleporterMessengerContractAddress = string(teleporterMessengerContractAddressBytes) + t.messengerContractAddress = string(messengerContractAddressBytes) } - if t.teleporterMessengerDeployerAddress == "" { - var teleporterMessengerDeployerAddressBytes []byte - if utils.FileExists(teleporterMessengerDeployerAddressPath) { - teleporterMessengerDeployerAddressBytes, err = os.ReadFile( - teleporterMessengerDeployerAddressPath, + if t.messengerDeployerAddress == "" { + var messengerDeployerAddressBytes []byte + if utils.FileExists(messengerDeployerAddressPath) { + messengerDeployerAddressBytes, err = os.ReadFile( + messengerDeployerAddressPath, ) if err != nil { return err } } else { // get teleporter deployer address - teleporterMessengerDeployerAddressBytes, err = utils.DownloadWithTee(teleporterMessengerDeployerAddressURL, teleporterMessengerDeployerAddressPath) + messengerDeployerAddressBytes, err = utils.DownloadWithTee(messengerDeployerAddressURL, messengerDeployerAddressPath) if err != nil { return err } } - t.teleporterMessengerDeployerAddress = string(teleporterMessengerDeployerAddressBytes) + t.messengerDeployerAddress = string(messengerDeployerAddressBytes) } - if t.teleporterMessengerDeployerTx == "" { - var teleporterMessengerDeployerTxBytes []byte - if utils.FileExists(teleporterMessengerDeployerTxPath) { - teleporterMessengerDeployerTxBytes, err = os.ReadFile(teleporterMessengerDeployerTxPath) + if t.messengerDeployerTx == "" { + var messengerDeployerTxBytes []byte + if utils.FileExists(messengerDeployerTxPath) { + messengerDeployerTxBytes, err = os.ReadFile(messengerDeployerTxPath) if err != nil { return err } } else { - teleporterMessengerDeployerTxBytes, err = utils.DownloadWithTee(teleporterMessengerDeployerTxURL, teleporterMessengerDeployerTxPath) + messengerDeployerTxBytes, err = utils.DownloadWithTee(messengerDeployerTxURL, messengerDeployerTxPath) if err != nil { return err } } - t.teleporterMessengerDeployerTx = string(teleporterMessengerDeployerTxBytes) + t.messengerDeployerTx = string(messengerDeployerTxBytes) + } + if t.registryBydecode == "" { + var registryBytecodeBytes []byte + if utils.FileExists(registryBytecodePath) { + registryBytecodeBytes, err = os.ReadFile(registryBytecodePath) + if err != nil { + return err + } + } else { + registryBytecodeBytes, err = utils.DownloadWithTee(registryBydecodeURL, registryBytecodePath) + if err != nil { + return err + } + } + t.registryBydecode = string(registryBytecodeBytes) } return nil } @@ -198,41 +223,41 @@ func (t *Deployer) DeployMessenger( if err != nil { return false, "", err } - if teleporterMessengerAlreadyDeployed, err := evm.ContractAlreadyDeployed(client, t.teleporterMessengerContractAddress); err != nil { + if messengerAlreadyDeployed, err := evm.ContractAlreadyDeployed(client, t.messengerContractAddress); err != nil { return false, "", fmt.Errorf("failure making a request to %s: %w", rpcURL, err) - } else if teleporterMessengerAlreadyDeployed { + } else if messengerAlreadyDeployed { ux.Logger.PrintToUser("Teleporter Messenger has already been deployed to %s", subnetName) - return true, t.teleporterMessengerContractAddress, nil + return true, t.messengerContractAddress, nil } // get teleporter deployer balance - teleporterMessengerDeployerBalance, err := evm.GetAddressBalance( + messengerDeployerBalance, err := evm.GetAddressBalance( client, - t.teleporterMessengerDeployerAddress, + t.messengerDeployerAddress, ) if err != nil { return false, "", err } - if teleporterMessengerDeployerBalance.Cmp(teleporterMessengerDeployerRequiredBalance) < 0 { + if messengerDeployerBalance.Cmp(messengerDeployerRequiredBalance) < 0 { toFund := big.NewInt(0). - Sub(teleporterMessengerDeployerRequiredBalance, teleporterMessengerDeployerBalance) + Sub(messengerDeployerRequiredBalance, messengerDeployerBalance) if err := evm.FundAddress( client, prefundedPrivateKey, - t.teleporterMessengerDeployerAddress, + t.messengerDeployerAddress, toFund, ); err != nil { return false, "", err } } - if err := evm.IssueTx(client, t.teleporterMessengerDeployerTx); err != nil { + if err := evm.IssueTx(client, t.messengerDeployerTx); err != nil { return false, "", err } ux.Logger.PrintToUser( "Teleporter Messenger successfully deployed to %s (%s)", subnetName, - t.teleporterMessengerContractAddress, + t.messengerContractAddress, ) - return false, t.teleporterMessengerContractAddress, nil + return false, t.messengerContractAddress, nil } func (t *Deployer) DeployRegistry( @@ -245,11 +270,11 @@ func (t *Deployer) DeployRegistry( if err := t.DownloadAssets(teleporterInstallDir, version); err != nil { return "", err } - teleporterMessengerContractAddress := common.HexToAddress(t.teleporterMessengerContractAddress) - teleporterRegistryConstructorInput := []teleporterRegistry.ProtocolRegistryEntry{ + messengerContractAddress := common.HexToAddress(t.messengerContractAddress) + registryConstructorInput := []registry.ProtocolRegistryEntry{ { Version: big.NewInt(1), - ProtocolAddress: teleporterMessengerContractAddress, + ProtocolAddress: messengerContractAddress, }, } client, err := evm.GetClient(rpcURL) @@ -261,10 +286,10 @@ func (t *Deployer) DeployRegistry( if err != nil { return "", err } - teleporterRegistryAddress, tx, _, err := DeployTeleporterRegistry( + registryAddress, tx, _, err := DeployTeleporterRegistry( txOpts, client, - teleporterRegistryConstructorInput, + registryConstructorInput, ) if err != nil { return "", err @@ -277,16 +302,16 @@ func (t *Deployer) DeployRegistry( ux.Logger.PrintToUser( "Teleporter Registry successfully deployed to %s (%s)", subnetName, - teleporterRegistryAddress, + registryAddress, ) - return teleporterRegistryAddress.String(), nil + return registryAddress.String(), nil } func DeployTeleporterRegistry( txOpts *bind.TransactOpts, client ethclient.Client, - teleporterRegistryConstructorInput []teleporterRegistry.ProtocolRegistryEntry, -) (common.Address, *types.Transaction, *teleporterRegistry.TeleporterRegistry, error) { + registryConstructorInput []registry.ProtocolRegistryEntry, +) (common.Address, *types.Transaction, *registry.TeleporterRegistry, error) { const ( repeatsOnFailure = 3 sleepBetweenRepeats = 1 * time.Second @@ -294,17 +319,17 @@ func DeployTeleporterRegistry( var ( addr common.Address tx *types.Transaction - registry *teleporterRegistry.TeleporterRegistry + registry *registry.TeleporterRegistry err error ) for i := 0; i < repeatsOnFailure; i++ { ctx, cancel := utils.GetAPILargeContext() defer cancel() txOpts.Context = ctx - addr, tx, registry, err = teleporterRegistry.DeployTeleporterRegistry( + addr, tx, registry, err = registry.DeployTeleporterRegistry( txOpts, client, - teleporterRegistryConstructorInput, + registryConstructorInput, ) if err == nil { break @@ -366,7 +391,7 @@ func DeployAndFundRelayer( } endpoint := network.BlockchainEndpoint(blockchainID) td := Deployer{} - alreadyDeployed, teleporterMessengerAddress, teleporterRegistryAddress, err := td.Deploy( + alreadyDeployed, messengerAddress, registryAddress, err := td.Deploy( app.GetTeleporterBinDir(), teleporterVersion, subnetName, @@ -393,7 +418,7 @@ func DeployAndFundRelayer( return false, "", "", err } } - return alreadyDeployed, teleporterMessengerAddress, teleporterRegistryAddress, err + return alreadyDeployed, messengerAddress, registryAddress, err } func getTeleporterKeyInfo( @@ -434,7 +459,7 @@ func GetInfo( return nil, err } deployer := Deployer{} - _, ti.MessengerDeployerAddress, _, err = deployer.GetAssets( + _, ti.MessengerDeployerAddress, _, _, err = deployer.GetAssets( app.GetTeleporterBinDir(), ti.Version, ) From 16b916b105ec7c19e71064c70c8b9a1d4f0f8fa2 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Wed, 12 Jun 2024 10:51:26 -0300 Subject: [PATCH 76/87] deploy registry binary --- pkg/contract/contract.go | 95 ++++++++++++++++++++++++++++++------ pkg/teleporter/teleporter.go | 86 ++++++++------------------------ 2 files changed, 99 insertions(+), 82 deletions(-) diff --git a/pkg/contract/contract.go b/pkg/contract/contract.go index f9bdbd55c..c54644497 100644 --- a/pkg/contract/contract.go +++ b/pkg/contract/contract.go @@ -26,23 +26,43 @@ func removeSurroundingParenthesis(s string) (string, error) { return s, nil } +func removeSurroundingBrackets(s string) (string, error) { + s = strings.TrimSpace(s) + if len(s) > 0 { + if string(s[0]) != "[" || string(s[len(s)-1]) != "]" { + return "", fmt.Errorf("expected esp %q to be surrounded by parenthesis", s) + } + s = s[1 : len(s)-1] + } + return s, nil +} + func getWords(s string) []string { words := []string{} word := "" insideParenthesis := false + insideBrackets := false for _, rune := range s { c := string(rune) if insideParenthesis { + word += c if c == ")" { words = append(words, word) word = "" insideParenthesis = false - } else { - word += c } continue } - if c == " " || c == "," || c == "(" { + if insideBrackets { + word += c + if c == "]" { + words = append(words, word) + word = "" + insideBrackets = false + } + continue + } + if c == " " || c == "," || c == "(" || c == "[" { if word != "" { words = append(words, word) word = "" @@ -53,7 +73,9 @@ func getWords(s string) []string { } if c == "(" { insideParenthesis = true - continue + } + if c == "[" { + insideBrackets = true } word += c } @@ -66,24 +88,59 @@ func getWords(s string) []string { func getMap( types []string, params ...interface{}, -) []map[string]interface{} { +) ([]map[string]interface{}, error) { r := []map[string]interface{}{} for i, t := range types { - spaceIndex := strings.Index(t, " ") - commaIndex := strings.Index(t, ",") m := map[string]interface{}{} - if spaceIndex != -1 || commaIndex != -1 { - // complex type - m["components"] = getMap(getWords(t), params[i]) + switch { + case string(t[0]) == "(": + // struct type + var err error + t, err = removeSurroundingParenthesis(t) + if err != nil { + return nil, err + } + m["components"], err = getMap(getWords(t), params[i]) + if err != nil { + return nil, err + } m["internaltype"] = "tuple" m["type"] = "tuple" m["name"] = "" - } else { + case string(t[0]) == "[": + // TODO: add more types + // slice struct type + var err error + t, err = removeSurroundingBrackets(t) + if err != nil { + return nil, err + } + if string(t[0]) == "(" { + t, err = removeSurroundingParenthesis(t) + if err != nil { + return nil, err + } + m["components"], err = getMap(getWords(t), params[i]) + if err != nil { + return nil, err + } + m["internaltype"] = "tuple[]" + m["type"] = "tuple[]" + m["name"] = "" + } else { + m["internaltype"] = fmt.Sprintf("%s[]", t) + m["type"] = fmt.Sprintf("%s[]", t) + m["name"] = "" + } + default: name := "" if len(params) == 1 { - rt := reflect.TypeOf(params[0]) + rt := reflect.ValueOf(params[0]) + if rt.Kind() == reflect.Slice && rt.Len() > 0 { + rt = rt.Index(0) + } if rt.Kind() == reflect.Struct && rt.NumField() == len(types) { - name = rt.Field(i).Name + name = rt.Type().Field(i).Name } } m["internaltype"] = t @@ -92,7 +149,7 @@ func getMap( } r = append(r, m) } - return r + return r, nil } func ParseMethodEsp( @@ -128,8 +185,14 @@ func ParseMethodEsp( } inputTypes := getWords(methodInputs) outputTypes := getWords(methodOutputs) - inputs := getMap(inputTypes, params...) - outputs := getMap(outputTypes) + inputs, err := getMap(inputTypes, params...) + if err != nil { + return "", "", err + } + outputs, err := getMap(outputTypes) + if err != nil { + return "", "", err + } abiMap := []map[string]interface{}{ { "inputs": inputs, diff --git a/pkg/teleporter/teleporter.go b/pkg/teleporter/teleporter.go index 01241554a..957ec9ee6 100644 --- a/pkg/teleporter/teleporter.go +++ b/pkg/teleporter/teleporter.go @@ -7,20 +7,16 @@ import ( "math/big" "os" "path/filepath" - "time" "github.com/ava-labs/avalanche-cli/pkg/application" "github.com/ava-labs/avalanche-cli/pkg/binutils" "github.com/ava-labs/avalanche-cli/pkg/constants" + "github.com/ava-labs/avalanche-cli/pkg/contract" "github.com/ava-labs/avalanche-cli/pkg/evm" "github.com/ava-labs/avalanche-cli/pkg/key" "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" - "github.com/ava-labs/subnet-evm/accounts/abi/bind" - "github.com/ava-labs/subnet-evm/core/types" - "github.com/ava-labs/subnet-evm/ethclient" - registry "github.com/ava-labs/teleporter/abi-bindings/go/Teleporter/upgrades/TeleporterRegistry" "github.com/ethereum/go-ethereum/common" ) @@ -29,7 +25,7 @@ const ( messengerContractAddressURLFmt = releaseURL + "/TeleporterMessenger_Contract_Address_%s.txt" messengerDeployerAddressURLFmt = releaseURL + "/TeleporterMessenger_Deployer_Address_%s.txt" messengerDeployerTxURLFmt = releaseURL + "/TeleporterMessenger_Deployment_Transaction_%s.txt" - registryBytecodeURLFmt = releaseURL + "/TeleporterRegisrtry_Bytecode_%s.txt" + registryBytecodeURLFmt = releaseURL + "/TeleporterRegistry_Bytecode_%s.txt" ) var ( @@ -181,7 +177,7 @@ func (t *Deployer) Deploy( version string, subnetName string, rpcURL string, - prefundedPrivateKey string, + privateKey string, deployMessenger bool, deployRegistry bool, ) (bool, string, string, error) { @@ -197,12 +193,12 @@ func (t *Deployer) Deploy( version, subnetName, rpcURL, - prefundedPrivateKey, + privateKey, ) } if err == nil && deployRegistry { if !deployMessenger || !alreadyDeployed { - registryAddress, err = t.DeployRegistry(teleporterInstallDir, version, subnetName, rpcURL, prefundedPrivateKey) + registryAddress, err = t.DeployRegistry(teleporterInstallDir, version, subnetName, rpcURL, privateKey) } } return alreadyDeployed, messengerAddress, registryAddress, err @@ -213,7 +209,7 @@ func (t *Deployer) DeployMessenger( version string, subnetName string, rpcURL string, - prefundedPrivateKey string, + privateKey string, ) (bool, string, error) { if err := t.DownloadAssets(teleporterInstallDir, version); err != nil { return false, "", err @@ -242,7 +238,7 @@ func (t *Deployer) DeployMessenger( Sub(messengerDeployerRequiredBalance, messengerDeployerBalance) if err := evm.FundAddress( client, - prefundedPrivateKey, + privateKey, t.messengerDeployerAddress, toFund, ); err != nil { @@ -265,80 +261,38 @@ func (t *Deployer) DeployRegistry( version string, subnetName string, rpcURL string, - prefundedPrivateKey string, + privateKey string, ) (string, error) { if err := t.DownloadAssets(teleporterInstallDir, version); err != nil { return "", err } messengerContractAddress := common.HexToAddress(t.messengerContractAddress) - registryConstructorInput := []registry.ProtocolRegistryEntry{ + type ProtocolRegistryEntry struct { + Version *big.Int + ProtocolAddress common.Address + } + constructorInput := []ProtocolRegistryEntry{ { Version: big.NewInt(1), ProtocolAddress: messengerContractAddress, }, } - client, err := evm.GetClient(rpcURL) - if err != nil { - return "", err - } - defer client.Close() - txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) - if err != nil { - return "", err - } - registryAddress, tx, _, err := DeployTeleporterRegistry( - txOpts, - client, - registryConstructorInput, + registryAddress, err := contract.DeployContract( + rpcURL, + privateKey, + []byte(t.registryBydecode), + "([(uint256, address)])", + constructorInput, ) if err != nil { return "", err } - if _, success, err := evm.WaitForTransaction(client, tx); err != nil { - return "", err - } else if !success { - return "", fmt.Errorf("failed receipt status deploying teleporter registry") - } ux.Logger.PrintToUser( "Teleporter Registry successfully deployed to %s (%s)", subnetName, registryAddress, ) - return registryAddress.String(), nil -} - -func DeployTeleporterRegistry( - txOpts *bind.TransactOpts, - client ethclient.Client, - registryConstructorInput []registry.ProtocolRegistryEntry, -) (common.Address, *types.Transaction, *registry.TeleporterRegistry, error) { - const ( - repeatsOnFailure = 3 - sleepBetweenRepeats = 1 * time.Second - ) - var ( - addr common.Address - tx *types.Transaction - registry *registry.TeleporterRegistry - err error - ) - for i := 0; i < repeatsOnFailure; i++ { - ctx, cancel := utils.GetAPILargeContext() - defer cancel() - txOpts.Context = ctx - addr, tx, registry, err = registry.DeployTeleporterRegistry( - txOpts, - client, - registryConstructorInput, - ) - if err == nil { - break - } - err = fmt.Errorf("failure deploying teleporter registry on %#v: %w", client, err) - ux.Logger.RedXToUser("%s", err) - time.Sleep(sleepBetweenRepeats) - } - return addr, tx, registry, err + return registryAddress.Hex(), nil } func getPrivateKey( From 02748029cfa145375ec177286680d43277f9ea14 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Wed, 12 Jun 2024 12:23:46 -0300 Subject: [PATCH 77/87] nit --- cmd/teleportercmd/msg.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cmd/teleportercmd/msg.go b/cmd/teleportercmd/msg.go index 840977f0f..22b6e303d 100644 --- a/cmd/teleportercmd/msg.go +++ b/cmd/teleportercmd/msg.go @@ -23,8 +23,14 @@ import ( ) var ( - msgSupportedNetworkOptions = []networkoptions.NetworkOption{networkoptions.Local, networkoptions.Cluster, networkoptions.Fuji, networkoptions.Mainnet, networkoptions.Devnet} - globalNetworkFlags networkoptions.NetworkFlags + msgSupportedNetworkOptions = []networkoptions.NetworkOption{ + networkoptions.Local, + networkoptions.Cluster, + networkoptions.Fuji, + networkoptions.Mainnet, + networkoptions.Devnet, + } + globalNetworkFlags networkoptions.NetworkFlags ) // avalanche teleporter msg From c07265ed4eb0a8aad57311ee089b03ca97e7fd95 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Wed, 12 Jun 2024 12:39:01 -0300 Subject: [PATCH 78/87] add methods to set the contracts by file --- pkg/teleporter/teleporter.go | 57 ++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/pkg/teleporter/teleporter.go b/pkg/teleporter/teleporter.go index 957ec9ee6..b5b06e179 100644 --- a/pkg/teleporter/teleporter.go +++ b/pkg/teleporter/teleporter.go @@ -78,6 +78,63 @@ func (t *Deployer) GetAssets( return t.messengerContractAddress, t.messengerDeployerAddress, t.messengerDeployerTx, t.registryBydecode, nil } +func (t *Deployer) SetAssetsFromPaths( + messengerContractAddressPath string, + messengerDeployerAddressPath string, + messengerDeployerTxPath string, + registryBydecodePath string, +) error { + if messengerContractAddressPath != "" { + if bs, err := os.ReadFile(messengerContractAddressPath); err != nil { + return err + } else { + t.messengerContractAddress = string(bs) + } + } + if messengerDeployerAddressPath != "" { + if bs, err := os.ReadFile(messengerDeployerAddressPath); err != nil { + return err + } else { + t.messengerDeployerAddress = string(bs) + } + } + if messengerDeployerTxPath != "" { + if bs, err := os.ReadFile(messengerDeployerTxPath); err != nil { + return err + } else { + t.messengerDeployerTx = string(bs) + } + } + if registryBydecodePath != "" { + if bs, err := os.ReadFile(registryBydecodePath); err != nil { + return err + } else { + t.registryBydecode = string(bs) + } + } + return nil +} + +func (t *Deployer) SetAssets( + messengerContractAddress string, + messengerDeployerAddress string, + messengerDeployerTx string, + registryBydecode string, +) { + if messengerContractAddress != "" { + t.messengerContractAddress = messengerContractAddress + } + if messengerDeployerAddress != "" { + t.messengerDeployerAddress = messengerDeployerAddress + } + if messengerDeployerTx != "" { + t.messengerDeployerTx = messengerDeployerTx + } + if registryBydecode != "" { + t.registryBydecode = registryBydecode + } +} + func (t *Deployer) DownloadAssets( teleporterInstallDir string, version string, From 2b529f46631a9f7b1247325ed9a63ca14767bdec Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Wed, 12 Jun 2024 13:25:16 -0300 Subject: [PATCH 79/87] add asset stuff to lib --- cmd/nodecmd/wiz.go | 63 +++++++++++++++++++++++------------- cmd/teleportercmd/deploy.go | 53 +++++++++++++++++++++--------- pkg/teleporter/teleporter.go | 12 +++++-- 3 files changed, 89 insertions(+), 39 deletions(-) diff --git a/cmd/nodecmd/wiz.go b/cmd/nodecmd/wiz.go index 95498cff6..98b84b258 100644 --- a/cmd/nodecmd/wiz.go +++ b/cmd/nodecmd/wiz.go @@ -44,26 +44,33 @@ const ( ) var ( - forceSubnetCreate bool - subnetGenesisFile string - useEvmSubnet bool - useCustomSubnet bool - evmVersion string - evmChainID uint64 - evmToken string - evmDefaults bool - useLatestEvmReleasedVersion bool - useLatestEvmPreReleasedVersion bool - customVMRepoURL string - customVMBranch string - customVMBuildScript string - nodeConf string - subnetConf string - chainConf string - validators []string - customGrafanaDashboardPath string - teleporterReady bool - runRelayer bool + forceSubnetCreate bool + subnetGenesisFile string + useEvmSubnet bool + useCustomSubnet bool + evmVersion string + evmChainID uint64 + evmToken string + evmDefaults bool + useLatestEvmReleasedVersion bool + useLatestEvmPreReleasedVersion bool + customVMRepoURL string + customVMBranch string + customVMBuildScript string + nodeConf string + subnetConf string + chainConf string + validators []string + customGrafanaDashboardPath string + teleporterReady bool + runRelayer bool + teleporterVersion string + teleporterMessengerContractAddressPath string + teleporterMessengerDeployerAddressPath string + teleporterMessengerDeployerTxPath string + teleporterRegistryBydecodePath string + deployTeleporterMessenger bool + deployTeleporterRegistry bool ) func newWizCmd() *cobra.Command { @@ -124,6 +131,13 @@ The node wiz command creates a devnet and deploys, sync and validate a subnet in cmd.Flags().StringVar(&volumeType, "aws-volume-type", "gp3", "AWS volume type") cmd.Flags().IntVar(&volumeSize, "aws-volume-size", constants.CloudServerStorageSize, "AWS volume size in GB") cmd.Flags().StringVar(&grafanaPkg, "grafana-pkg", "", "use grafana pkg instead of apt repo(by default), for example https://dl.grafana.com/oss/release/grafana_10.4.1_amd64.deb") + cmd.Flags().StringVar(&teleporterVersion, "teleporter-version", "latest", "teleporter version to deploy") + cmd.Flags().StringVar(&teleporterMessengerContractAddressPath, "teleporter-messenger-contract-address-path", "", "path to a teleporter messenger contract address file") + cmd.Flags().StringVar(&teleporterMessengerDeployerAddressPath, "teleporter-messenger-deployer-address-path", "", "path to a teleporter messenger deployer address file") + cmd.Flags().StringVar(&teleporterMessengerDeployerTxPath, "teleporter-messenger-deployer-tx-path", "", "path to a teleporter messenger deployer tx file") + cmd.Flags().StringVar(&teleporterRegistryBydecodePath, "teleporter-registry-bytecode-path", "", "path to a teleporter registry bytecode file") + cmd.Flags().BoolVar(&deployTeleporterMessenger, "deploy-teleporter-messenger", true, "deploy Teleporter Messenger") + cmd.Flags().BoolVar(&deployTeleporterRegistry, "deploy-teleporter-registry", true, "deploy Teleporter Registry") return cmd } @@ -350,8 +364,13 @@ func wiz(cmd *cobra.Command, args []string) error { Network: networkoptions.NetworkFlags{ ClusterName: clusterName, }, - DeployMessenger: true, - DeployRegistry: true, + DeployMessenger: deployTeleporterMessenger, + DeployRegistry: deployTeleporterRegistry, + Version: teleporterVersion, + MessengerContractAddressPath: teleporterMessengerContractAddressPath, + MessengerDeployerAddressPath: teleporterMessengerDeployerAddressPath, + MessengerDeployerTxPath: teleporterMessengerDeployerTxPath, + RegistryBydecodePath: teleporterRegistryBydecodePath, } if err := teleportercmd.CallDeploy([]string{}, flags); err != nil { return err diff --git a/cmd/teleportercmd/deploy.go b/cmd/teleportercmd/deploy.go index 7b98ae414..75042edfc 100644 --- a/cmd/teleportercmd/deploy.go +++ b/cmd/teleportercmd/deploy.go @@ -20,17 +20,21 @@ import ( ) type DeployFlags struct { - Network networkoptions.NetworkFlags - SubnetName string - BlockchainID string - CChain bool - PrivateKey string - KeyName string - GenesisKey bool - DeployMessenger bool - DeployRegistry bool - TeleporterVersion string - RPCURL string + Network networkoptions.NetworkFlags + SubnetName string + BlockchainID string + CChain bool + PrivateKey string + KeyName string + GenesisKey bool + DeployMessenger bool + DeployRegistry bool + RPCURL string + Version string + MessengerContractAddressPath string + MessengerDeployerAddressPath string + MessengerDeployerTxPath string + RegistryBydecodePath string } const ( @@ -65,8 +69,12 @@ func newDeployCmd() *cobra.Command { cmd.Flags().BoolVar(&deployFlags.GenesisKey, "genesis-key", false, "use genesis aidrop key to fund teleporter deploy") cmd.Flags().BoolVar(&deployFlags.DeployMessenger, "deploy-messenger", true, "deploy Teleporter Messenger") cmd.Flags().BoolVar(&deployFlags.DeployRegistry, "deploy-registry", true, "deploy Teleporter Registry") - cmd.Flags().StringVar(&deployFlags.TeleporterVersion, "version", "latest", "version to deploy") cmd.Flags().StringVar(&deployFlags.RPCURL, "rpc-url", "", "use the given RPC URL to connect to the subnet") + cmd.Flags().StringVar(&deployFlags.Version, "version", "latest", "version to deploy") + cmd.Flags().StringVar(&deployFlags.MessengerContractAddressPath, "messenger-contract-address-path", "", "path to a messenger contract address file") + cmd.Flags().StringVar(&deployFlags.MessengerDeployerAddressPath, "messenger-deployer-address-path", "", "path to a messenger deployer address file") + cmd.Flags().StringVar(&deployFlags.MessengerDeployerTxPath, "messenger-deployer-tx-path", "", "path to a messenger deployer tx file") + cmd.Flags().StringVar(&deployFlags.RegistryBydecodePath, "registry-bytecode-path", "", "path to a registry bytecode file") return cmd } @@ -234,9 +242,14 @@ func CallDeploy(_ []string, flags DeployFlags) error { privateKey = genesisPrivateKey } } - if flags.TeleporterVersion != "" && flags.TeleporterVersion != "latest" { - teleporterVersion = flags.TeleporterVersion - } else if teleporterVersion == "" { + if flags.Version != "" && flags.Version != "latest" { + teleporterVersion = flags.Version + } else if flags.MessengerContractAddressPath != "" || flags.MessengerDeployerAddressPath != "" || flags.MessengerDeployerTxPath != "" || flags.RegistryBydecodePath != "" { + teleporterVersion = "" + if flags.MessengerContractAddressPath == "" || flags.MessengerDeployerAddressPath == "" || flags.MessengerDeployerTxPath == "" || flags.RegistryBydecodePath == "" { + return fmt.Errorf("if setting any teleporter asset path, you must set all teleporter asset paths") + } + } else { teleporterInfo, err := teleporter.GetInfo(app) if err != nil { return err @@ -249,6 +262,16 @@ func CallDeploy(_ []string, flags DeployFlags) error { rpcURL = flags.RPCURL } td := teleporter.Deployer{} + if flags.MessengerContractAddressPath != "" { + if err := td.SetAssetsFromPaths( + flags.MessengerContractAddressPath, + flags.MessengerDeployerAddressPath, + flags.MessengerDeployerTxPath, + flags.RegistryBydecodePath, + ); err != nil { + return err + } + } alreadyDeployed, teleporterMessengerAddress, teleporterRegistryAddress, err := td.Deploy( app.GetTeleporterBinDir(), teleporterVersion, diff --git a/pkg/teleporter/teleporter.go b/pkg/teleporter/teleporter.go index b5b06e179..0d19a0e64 100644 --- a/pkg/teleporter/teleporter.go +++ b/pkg/teleporter/teleporter.go @@ -78,6 +78,13 @@ func (t *Deployer) GetAssets( return t.messengerContractAddress, t.messengerDeployerAddress, t.messengerDeployerTx, t.registryBydecode, nil } +func (t *Deployer) CheckAssets() error { + if t.messengerContractAddress == "" || t.messengerDeployerAddress == "" || t.messengerDeployerTx == "" || t.registryBydecode == "" { + return fmt.Errorf("teleporter assets has not been initialized") + } + return nil +} + func (t *Deployer) SetAssetsFromPaths( messengerContractAddressPath string, messengerDeployerAddressPath string, @@ -268,7 +275,7 @@ func (t *Deployer) DeployMessenger( rpcURL string, privateKey string, ) (bool, string, error) { - if err := t.DownloadAssets(teleporterInstallDir, version); err != nil { + if err := t.CheckAssets(); err != nil { return false, "", err } // check if contract is already deployed @@ -283,6 +290,7 @@ func (t *Deployer) DeployMessenger( return true, t.messengerContractAddress, nil } // get teleporter deployer balance + fmt.Println("PEPE", t.messengerDeployerAddress) messengerDeployerBalance, err := evm.GetAddressBalance( client, t.messengerDeployerAddress, @@ -320,7 +328,7 @@ func (t *Deployer) DeployRegistry( rpcURL string, privateKey string, ) (string, error) { - if err := t.DownloadAssets(teleporterInstallDir, version); err != nil { + if err := t.CheckAssets(); err != nil { return "", err } messengerContractAddress := common.HexToAddress(t.messengerContractAddress) From 2b5976082dd7d851b3161d6c26785e1b645280ee Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Wed, 12 Jun 2024 13:31:52 -0300 Subject: [PATCH 80/87] remove unneded version param from deploy --- cmd/teleportercmd/deploy.go | 6 ++---- pkg/teleporter/teleporter.go | 16 ++++++---------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/cmd/teleportercmd/deploy.go b/cmd/teleportercmd/deploy.go index 75042edfc..34a4cd88c 100644 --- a/cmd/teleportercmd/deploy.go +++ b/cmd/teleportercmd/deploy.go @@ -272,9 +272,9 @@ func CallDeploy(_ []string, flags DeployFlags) error { return err } } + //app.GetTeleporterBinDir(), + //teleporterVersion, alreadyDeployed, teleporterMessengerAddress, teleporterRegistryAddress, err := td.Deploy( - app.GetTeleporterBinDir(), - teleporterVersion, teleporterSubnetDesc, rpcURL, privateKey, @@ -311,8 +311,6 @@ func CallDeploy(_ []string, flags DeployFlags) error { return err } alreadyDeployed, teleporterMessengerAddress, teleporterRegistryAddress, err := td.Deploy( - app.GetTeleporterBinDir(), - teleporterVersion, cChainName, network.BlockchainEndpoint(cChainAlias), ewoq.PrivKeyHex(), diff --git a/pkg/teleporter/teleporter.go b/pkg/teleporter/teleporter.go index 0d19a0e64..bc78d800a 100644 --- a/pkg/teleporter/teleporter.go +++ b/pkg/teleporter/teleporter.go @@ -237,8 +237,6 @@ func (t *Deployer) DownloadAssets( } func (t *Deployer) Deploy( - teleporterInstallDir string, - version string, subnetName string, rpcURL string, privateKey string, @@ -253,8 +251,6 @@ func (t *Deployer) Deploy( ) if deployMessenger { alreadyDeployed, messengerAddress, err = t.DeployMessenger( - teleporterInstallDir, - version, subnetName, rpcURL, privateKey, @@ -262,15 +258,13 @@ func (t *Deployer) Deploy( } if err == nil && deployRegistry { if !deployMessenger || !alreadyDeployed { - registryAddress, err = t.DeployRegistry(teleporterInstallDir, version, subnetName, rpcURL, privateKey) + registryAddress, err = t.DeployRegistry(subnetName, rpcURL, privateKey) } } return alreadyDeployed, messengerAddress, registryAddress, err } func (t *Deployer) DeployMessenger( - teleporterInstallDir string, - version string, subnetName string, rpcURL string, privateKey string, @@ -322,8 +316,6 @@ func (t *Deployer) DeployMessenger( } func (t *Deployer) DeployRegistry( - teleporterInstallDir string, - version string, subnetName string, rpcURL string, privateKey string, @@ -410,9 +402,13 @@ func DeployAndFundRelayer( } endpoint := network.BlockchainEndpoint(blockchainID) td := Deployer{} - alreadyDeployed, messengerAddress, registryAddress, err := td.Deploy( + if err := td.DownloadAssets( app.GetTeleporterBinDir(), teleporterVersion, + ); err != nil { + return false, "", "", err + } + alreadyDeployed, messengerAddress, registryAddress, err := td.Deploy( subnetName, endpoint, privKeyStr, From 0b4de001212828a7839d7eb3f5d3956dd4d63dbf Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Wed, 12 Jun 2024 14:01:36 -0300 Subject: [PATCH 81/87] asset download reincorporated into deploy cmd --- cmd/teleportercmd/deploy.go | 9 +++++++-- pkg/teleporter/teleporter.go | 1 - 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/cmd/teleportercmd/deploy.go b/cmd/teleportercmd/deploy.go index 34a4cd88c..ba9c5518b 100644 --- a/cmd/teleportercmd/deploy.go +++ b/cmd/teleportercmd/deploy.go @@ -271,9 +271,14 @@ func CallDeploy(_ []string, flags DeployFlags) error { ); err != nil { return err } + } else { + if err := td.DownloadAssets( + app.GetTeleporterBinDir(), + teleporterVersion, + ); err != nil { + return err + } } - //app.GetTeleporterBinDir(), - //teleporterVersion, alreadyDeployed, teleporterMessengerAddress, teleporterRegistryAddress, err := td.Deploy( teleporterSubnetDesc, rpcURL, diff --git a/pkg/teleporter/teleporter.go b/pkg/teleporter/teleporter.go index bc78d800a..aa0579e10 100644 --- a/pkg/teleporter/teleporter.go +++ b/pkg/teleporter/teleporter.go @@ -284,7 +284,6 @@ func (t *Deployer) DeployMessenger( return true, t.messengerContractAddress, nil } // get teleporter deployer balance - fmt.Println("PEPE", t.messengerDeployerAddress) messengerDeployerBalance, err := evm.GetAddressBalance( client, t.messengerDeployerAddress, From 09978deacd6e70abecab955a09ae259bb28d9767 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Wed, 12 Jun 2024 14:33:05 -0300 Subject: [PATCH 82/87] added arbitrary teleporter binaries to local deploy --- cmd/subnetcmd/deploy.go | 17 ++++++++++++++--- pkg/subnet/local.go | 33 +++++++++++++++++++++++++++------ pkg/teleporter/teleporter.go | 9 +-------- 3 files changed, 42 insertions(+), 17 deletions(-) diff --git a/cmd/subnetcmd/deploy.go b/cmd/subnetcmd/deploy.go index dbe61906d..d71d65b4f 100644 --- a/cmd/subnetcmd/deploy.go +++ b/cmd/subnetcmd/deploy.go @@ -53,8 +53,8 @@ var ( mainnetChainID uint32 skipCreatePrompt bool avagoBinaryPath string - skipLocalTeleporter bool subnetOnly bool + teleporterEsp subnet.TeleporterEsp errMutuallyExlusiveControlKeys = errors.New("--control-keys and --same-control-key are mutually exclusive") ErrMutuallyExlusiveKeyLedger = errors.New("key source flags --key, --ledger/--ledger-addrs are mutually exclusive") @@ -95,8 +95,13 @@ so you can take your locally tested Subnet and deploy it on Fuji or Mainnet.`, cmd.Flags().StringVarP(&subnetIDStr, "subnet-id", "u", "", "do not create a subnet, deploy the blockchain into the given subnet id") cmd.Flags().Uint32Var(&mainnetChainID, "mainnet-chain-id", 0, "use different ChainID for mainnet deployment") cmd.Flags().StringVar(&avagoBinaryPath, "avalanchego-path", "", "use this avalanchego binary path") - cmd.Flags().BoolVar(&skipLocalTeleporter, "skip-local-teleporter", false, "skip local teleporter deploy to a local network") cmd.Flags().BoolVar(&subnetOnly, "subnet-only", false, "only create a subnet") + cmd.Flags().BoolVar(&teleporterEsp.SkipDeploy, "skip-teleporter-deploy", false, "skip automatic teleporter deploy") + cmd.Flags().StringVar(&teleporterEsp.Version, "teleporter-version", "latest", "teleporter version to deploy") + cmd.Flags().StringVar(&teleporterEsp.MessengerContractAddressPath, "teleporter-messenger-contract-address-path", "", "path to a teleporter messenger contract address file") + cmd.Flags().StringVar(&teleporterEsp.MessengerDeployerAddressPath, "teleporter-messenger-deployer-address-path", "", "path to a teleporter messenger deployer address file") + cmd.Flags().StringVar(&teleporterEsp.MessengerDeployerTxPath, "teleporter-messenger-deployer-tx-path", "", "path to a teleporter messenger deployer tx file") + cmd.Flags().StringVar(&teleporterEsp.RegistryBydecodePath, "teleporter-registry-bytecode-path", "", "path to a teleporter registry bytecode file") return cmd } @@ -265,6 +270,12 @@ func deploySubnet(cmd *cobra.Command, args []string) error { return err } + if teleporterEsp.MessengerContractAddressPath != "" || teleporterEsp.MessengerDeployerAddressPath != "" || teleporterEsp.MessengerDeployerTxPath != "" || teleporterEsp.RegistryBydecodePath != "" { + if teleporterEsp.MessengerContractAddressPath == "" || teleporterEsp.MessengerDeployerAddressPath == "" || teleporterEsp.MessengerDeployerTxPath == "" || teleporterEsp.RegistryBydecodePath == "" { + return fmt.Errorf("if setting any teleporter asset path, you must set all teleporter asset paths") + } + } + chain := chains[0] sidecar, err := app.LoadSidecar(chain) @@ -358,7 +369,7 @@ func deploySubnet(cmd *cobra.Command, args []string) error { } deployer := subnet.NewLocalDeployer(app, userProvidedAvagoVersion, avagoBinaryPath, vmBin) - deployInfo, err := deployer.DeployToLocalNetwork(chain, chainGenesis, genesisPath, skipLocalTeleporter, subnetIDStr) + deployInfo, err := deployer.DeployToLocalNetwork(chain, chainGenesis, genesisPath, teleporterEsp, subnetIDStr) if err != nil { if deployer.BackendStartedHere() { if innerErr := binutils.KillgRPCServerProcess(app); innerErr != nil { diff --git a/pkg/subnet/local.go b/pkg/subnet/local.go index eb9c9afb9..e17b431b3 100644 --- a/pkg/subnet/local.go +++ b/pkg/subnet/local.go @@ -90,6 +90,15 @@ type getGRPCClientFunc func(...binutils.GRPCClientOpOption) (client.Client, erro type setDefaultSnapshotFunc func(string, bool, string, bool) (bool, error) +type TeleporterEsp struct { + SkipDeploy bool + Version string + MessengerContractAddressPath string + MessengerDeployerAddressPath string + MessengerDeployerTxPath string + RegistryBydecodePath string +} + type DeployInfo struct { SubnetID ids.ID BlockchainID ids.ID @@ -100,11 +109,11 @@ type DeployInfo struct { // DeployToLocalNetwork does the heavy lifting: // * it checks the gRPC is running, if not, it starts it // * kicks off the actual deployment -func (d *LocalDeployer) DeployToLocalNetwork(chain string, chainGenesis []byte, genesisPath string, skipTeleporter bool, subnetIDStr string) (*DeployInfo, error) { +func (d *LocalDeployer) DeployToLocalNetwork(chain string, chainGenesis []byte, genesisPath string, teleporterEsp TeleporterEsp, subnetIDStr string) (*DeployInfo, error) { if err := d.StartServer(); err != nil { return nil, err } - return d.doDeploy(chain, chainGenesis, genesisPath, skipTeleporter, subnetIDStr) + return d.doDeploy(chain, chainGenesis, genesisPath, teleporterEsp, subnetIDStr) } func getAssetID(wallet primary.Wallet, tokenName string, tokenSymbol string, maxSupply uint64) (ids.ID, error) { @@ -370,7 +379,7 @@ func (d *LocalDeployer) BackendStartedHere() bool { // - deploy a new blockchain for the given VM ID, genesis, and available subnet ID // - waits completion of operation // - show status -func (d *LocalDeployer) doDeploy(chain string, chainGenesis []byte, genesisPath string, skipTeleporter bool, subnetIDStr string) (*DeployInfo, error) { +func (d *LocalDeployer) doDeploy(chain string, chainGenesis []byte, genesisPath string, teleporterEsp TeleporterEsp, subnetIDStr string) (*DeployInfo, error) { needsRestart, avalancheGoBinPath, err := d.SetupLocalEnv() if err != nil { return nil, err @@ -564,7 +573,7 @@ func (d *LocalDeployer) doDeploy(chain string, chainGenesis []byte, genesisPath teleporterMessengerAddress string teleporterRegistryAddress string ) - if sc.TeleporterReady && !skipTeleporter { + if sc.TeleporterReady && !teleporterEsp.SkipDeploy { network := models.NewLocalNetwork() // get relayer address relayerAddress, relayerPrivateKey, err := teleporter.GetRelayerKeyInfo(d.app.GetKeyPath(constants.AWMRelayerKeyName)) @@ -578,9 +587,21 @@ func (d *LocalDeployer) doDeploy(chain string, chainGenesis []byte, genesisPath } // deploy C-Chain ux.Logger.PrintToUser("") + // sc.TeleporterVersion, + td := teleporter.Deployer{} + if teleporterEsp.MessengerContractAddressPath != "" { + if err := td.SetAssetsFromPaths( + teleporterEsp.MessengerContractAddressPath, + teleporterEsp.MessengerDeployerAddressPath, + teleporterEsp.MessengerDeployerTxPath, + teleporterEsp.RegistryBydecodePath, + ); err != nil { + return nil, err + } + } alreadyDeployed, cchainTeleporterMessengerAddress, cchainTeleporterRegistryAddress, err := teleporter.DeployAndFundRelayer( d.app, - sc.TeleporterVersion, + &td, network, "c-chain", "C", @@ -630,7 +651,7 @@ func (d *LocalDeployer) doDeploy(chain string, chainGenesis []byte, genesisPath } _, teleporterMessengerAddress, teleporterRegistryAddress, err = teleporter.DeployAndFundRelayer( d.app, - sc.TeleporterVersion, + &td, network, chain, blockchainID, diff --git a/pkg/teleporter/teleporter.go b/pkg/teleporter/teleporter.go index aa0579e10..72b30cbd8 100644 --- a/pkg/teleporter/teleporter.go +++ b/pkg/teleporter/teleporter.go @@ -389,7 +389,7 @@ func SetProposerVM( func DeployAndFundRelayer( app *application.Avalanche, - teleporterVersion string, + td *Deployer, network models.Network, subnetName string, blockchainID string, @@ -400,13 +400,6 @@ func DeployAndFundRelayer( return false, "", "", err } endpoint := network.BlockchainEndpoint(blockchainID) - td := Deployer{} - if err := td.DownloadAssets( - app.GetTeleporterBinDir(), - teleporterVersion, - ); err != nil { - return false, "", "", err - } alreadyDeployed, messengerAddress, registryAddress, err := td.Deploy( subnetName, endpoint, From 2b5af0fefa84be9b8f920ab3f43fbb8b5f8486fd Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Wed, 12 Jun 2024 14:44:07 -0300 Subject: [PATCH 83/87] add automatic download of assets if no files are specified --- pkg/subnet/local.go | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/pkg/subnet/local.go b/pkg/subnet/local.go index e17b431b3..019a76cc4 100644 --- a/pkg/subnet/local.go +++ b/pkg/subnet/local.go @@ -587,7 +587,6 @@ func (d *LocalDeployer) doDeploy(chain string, chainGenesis []byte, genesisPath } // deploy C-Chain ux.Logger.PrintToUser("") - // sc.TeleporterVersion, td := teleporter.Deployer{} if teleporterEsp.MessengerContractAddressPath != "" { if err := td.SetAssetsFromPaths( @@ -598,6 +597,25 @@ func (d *LocalDeployer) doDeploy(chain string, chainGenesis []byte, genesisPath ); err != nil { return nil, err } + } else { + teleporterVersion := "" + if teleporterEsp.Version != "" && teleporterEsp.Version != "latest" { + teleporterVersion = teleporterEsp.Version + } else if sc.TeleporterVersion != "" { + teleporterVersion = sc.TeleporterVersion + } else { + teleporterInfo, err := teleporter.GetInfo(d.app) + if err != nil { + return nil, err + } + teleporterVersion = teleporterInfo.Version + } + if err := td.DownloadAssets( + d.app.GetTeleporterBinDir(), + teleporterVersion, + ); err != nil { + return nil, err + } } alreadyDeployed, cchainTeleporterMessengerAddress, cchainTeleporterRegistryAddress, err := teleporter.DeployAndFundRelayer( d.app, From 9e507fca4712af1bc4cfff9e7699e714cd4b5a63 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Wed, 12 Jun 2024 15:00:18 -0300 Subject: [PATCH 84/87] lint --- cmd/teleportercmd/deploy.go | 10 ++++++---- pkg/subnet/local.go | 7 ++++--- pkg/subnet/local_test.go | 5 ++++- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/cmd/teleportercmd/deploy.go b/cmd/teleportercmd/deploy.go index ba9c5518b..e6b995a9c 100644 --- a/cmd/teleportercmd/deploy.go +++ b/cmd/teleportercmd/deploy.go @@ -242,14 +242,16 @@ func CallDeploy(_ []string, flags DeployFlags) error { privateKey = genesisPrivateKey } } - if flags.Version != "" && flags.Version != "latest" { - teleporterVersion = flags.Version - } else if flags.MessengerContractAddressPath != "" || flags.MessengerDeployerAddressPath != "" || flags.MessengerDeployerTxPath != "" || flags.RegistryBydecodePath != "" { + switch { + case flags.MessengerContractAddressPath != "" || flags.MessengerDeployerAddressPath != "" || flags.MessengerDeployerTxPath != "" || flags.RegistryBydecodePath != "": teleporterVersion = "" if flags.MessengerContractAddressPath == "" || flags.MessengerDeployerAddressPath == "" || flags.MessengerDeployerTxPath == "" || flags.RegistryBydecodePath == "" { return fmt.Errorf("if setting any teleporter asset path, you must set all teleporter asset paths") } - } else { + case flags.Version != "" && flags.Version != "latest": + teleporterVersion = flags.Version + case teleporterVersion != "": + default: teleporterInfo, err := teleporter.GetInfo(app) if err != nil { return err diff --git a/pkg/subnet/local.go b/pkg/subnet/local.go index 019a76cc4..2fa47be6a 100644 --- a/pkg/subnet/local.go +++ b/pkg/subnet/local.go @@ -599,11 +599,12 @@ func (d *LocalDeployer) doDeploy(chain string, chainGenesis []byte, genesisPath } } else { teleporterVersion := "" - if teleporterEsp.Version != "" && teleporterEsp.Version != "latest" { + switch { + case teleporterEsp.Version != "" && teleporterEsp.Version != "latest": teleporterVersion = teleporterEsp.Version - } else if sc.TeleporterVersion != "" { + case sc.TeleporterVersion != "": teleporterVersion = sc.TeleporterVersion - } else { + default: teleporterInfo, err := teleporter.GetInfo(d.app) if err != nil { return nil, err diff --git a/pkg/subnet/local_test.go b/pkg/subnet/local_test.go index cc2d4e5f4..0aaf9eb70 100644 --- a/pkg/subnet/local_test.go +++ b/pkg/subnet/local_test.go @@ -140,7 +140,10 @@ func TestDeployToLocal(t *testing.T) { err = os.WriteFile(testSidecar.Name(), []byte(sidecar), constants.DefaultPerms755) require.NoError(err) // test actual deploy - deployInfo, err := testDeployer.DeployToLocalNetwork(testChainName, []byte(genesis), testGenesis.Name(), true, "") + teleporterEsp := TeleporterEsp{ + SkipDeploy: true, + } + deployInfo, err := testDeployer.DeployToLocalNetwork(testChainName, []byte(genesis), testGenesis.Name(), teleporterEsp, "") require.NoError(err) require.Equal(testSubnetID2, deployInfo.SubnetID.String()) require.Equal(testBlockChainID2, deployInfo.BlockchainID.String()) From 4dac1f0b1a8576c6f134e430a1887e6347122c17 Mon Sep 17 00:00:00 2001 From: Felipe Madero Date: Wed, 12 Jun 2024 15:06:38 -0300 Subject: [PATCH 85/87] add back again a flag to be deprecated --- cmd/subnetcmd/deploy.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/subnetcmd/deploy.go b/cmd/subnetcmd/deploy.go index d71d65b4f..2f988cd74 100644 --- a/cmd/subnetcmd/deploy.go +++ b/cmd/subnetcmd/deploy.go @@ -96,6 +96,7 @@ so you can take your locally tested Subnet and deploy it on Fuji or Mainnet.`, cmd.Flags().Uint32Var(&mainnetChainID, "mainnet-chain-id", 0, "use different ChainID for mainnet deployment") cmd.Flags().StringVar(&avagoBinaryPath, "avalanchego-path", "", "use this avalanchego binary path") cmd.Flags().BoolVar(&subnetOnly, "subnet-only", false, "only create a subnet") + cmd.Flags().BoolVar(&teleporterEsp.SkipDeploy, "skip-local-teleporter", false, "skip automatic teleporter deploy on local networks [to be deprecated]") cmd.Flags().BoolVar(&teleporterEsp.SkipDeploy, "skip-teleporter-deploy", false, "skip automatic teleporter deploy") cmd.Flags().StringVar(&teleporterEsp.Version, "teleporter-version", "latest", "teleporter version to deploy") cmd.Flags().StringVar(&teleporterEsp.MessengerContractAddressPath, "teleporter-messenger-contract-address-path", "", "path to a teleporter messenger contract address file") From 81f47dfbc6337e7e5428a3a2bafe34e4a0012acc Mon Sep 17 00:00:00 2001 From: felipemadero Date: Tue, 18 Jun 2024 20:24:26 -0300 Subject: [PATCH 86/87] Use registry release (#1958) * download registry bytecode * deploy registry binary * nit --- cmd/teleportercmd/msg.go | 10 +- pkg/contract/contract.go | 95 +++++++++++--- pkg/teleporter/teleporter.go | 239 ++++++++++++++++------------------- 3 files changed, 196 insertions(+), 148 deletions(-) diff --git a/cmd/teleportercmd/msg.go b/cmd/teleportercmd/msg.go index 840977f0f..22b6e303d 100644 --- a/cmd/teleportercmd/msg.go +++ b/cmd/teleportercmd/msg.go @@ -23,8 +23,14 @@ import ( ) var ( - msgSupportedNetworkOptions = []networkoptions.NetworkOption{networkoptions.Local, networkoptions.Cluster, networkoptions.Fuji, networkoptions.Mainnet, networkoptions.Devnet} - globalNetworkFlags networkoptions.NetworkFlags + msgSupportedNetworkOptions = []networkoptions.NetworkOption{ + networkoptions.Local, + networkoptions.Cluster, + networkoptions.Fuji, + networkoptions.Mainnet, + networkoptions.Devnet, + } + globalNetworkFlags networkoptions.NetworkFlags ) // avalanche teleporter msg diff --git a/pkg/contract/contract.go b/pkg/contract/contract.go index f9bdbd55c..c54644497 100644 --- a/pkg/contract/contract.go +++ b/pkg/contract/contract.go @@ -26,23 +26,43 @@ func removeSurroundingParenthesis(s string) (string, error) { return s, nil } +func removeSurroundingBrackets(s string) (string, error) { + s = strings.TrimSpace(s) + if len(s) > 0 { + if string(s[0]) != "[" || string(s[len(s)-1]) != "]" { + return "", fmt.Errorf("expected esp %q to be surrounded by parenthesis", s) + } + s = s[1 : len(s)-1] + } + return s, nil +} + func getWords(s string) []string { words := []string{} word := "" insideParenthesis := false + insideBrackets := false for _, rune := range s { c := string(rune) if insideParenthesis { + word += c if c == ")" { words = append(words, word) word = "" insideParenthesis = false - } else { - word += c } continue } - if c == " " || c == "," || c == "(" { + if insideBrackets { + word += c + if c == "]" { + words = append(words, word) + word = "" + insideBrackets = false + } + continue + } + if c == " " || c == "," || c == "(" || c == "[" { if word != "" { words = append(words, word) word = "" @@ -53,7 +73,9 @@ func getWords(s string) []string { } if c == "(" { insideParenthesis = true - continue + } + if c == "[" { + insideBrackets = true } word += c } @@ -66,24 +88,59 @@ func getWords(s string) []string { func getMap( types []string, params ...interface{}, -) []map[string]interface{} { +) ([]map[string]interface{}, error) { r := []map[string]interface{}{} for i, t := range types { - spaceIndex := strings.Index(t, " ") - commaIndex := strings.Index(t, ",") m := map[string]interface{}{} - if spaceIndex != -1 || commaIndex != -1 { - // complex type - m["components"] = getMap(getWords(t), params[i]) + switch { + case string(t[0]) == "(": + // struct type + var err error + t, err = removeSurroundingParenthesis(t) + if err != nil { + return nil, err + } + m["components"], err = getMap(getWords(t), params[i]) + if err != nil { + return nil, err + } m["internaltype"] = "tuple" m["type"] = "tuple" m["name"] = "" - } else { + case string(t[0]) == "[": + // TODO: add more types + // slice struct type + var err error + t, err = removeSurroundingBrackets(t) + if err != nil { + return nil, err + } + if string(t[0]) == "(" { + t, err = removeSurroundingParenthesis(t) + if err != nil { + return nil, err + } + m["components"], err = getMap(getWords(t), params[i]) + if err != nil { + return nil, err + } + m["internaltype"] = "tuple[]" + m["type"] = "tuple[]" + m["name"] = "" + } else { + m["internaltype"] = fmt.Sprintf("%s[]", t) + m["type"] = fmt.Sprintf("%s[]", t) + m["name"] = "" + } + default: name := "" if len(params) == 1 { - rt := reflect.TypeOf(params[0]) + rt := reflect.ValueOf(params[0]) + if rt.Kind() == reflect.Slice && rt.Len() > 0 { + rt = rt.Index(0) + } if rt.Kind() == reflect.Struct && rt.NumField() == len(types) { - name = rt.Field(i).Name + name = rt.Type().Field(i).Name } } m["internaltype"] = t @@ -92,7 +149,7 @@ func getMap( } r = append(r, m) } - return r + return r, nil } func ParseMethodEsp( @@ -128,8 +185,14 @@ func ParseMethodEsp( } inputTypes := getWords(methodInputs) outputTypes := getWords(methodOutputs) - inputs := getMap(inputTypes, params...) - outputs := getMap(outputTypes) + inputs, err := getMap(inputTypes, params...) + if err != nil { + return "", "", err + } + outputs, err := getMap(outputTypes) + if err != nil { + return "", "", err + } abiMap := []map[string]interface{}{ { "inputs": inputs, diff --git a/pkg/teleporter/teleporter.go b/pkg/teleporter/teleporter.go index d28211d7f..957ec9ee6 100644 --- a/pkg/teleporter/teleporter.go +++ b/pkg/teleporter/teleporter.go @@ -7,73 +7,75 @@ import ( "math/big" "os" "path/filepath" - "time" "github.com/ava-labs/avalanche-cli/pkg/application" "github.com/ava-labs/avalanche-cli/pkg/binutils" "github.com/ava-labs/avalanche-cli/pkg/constants" + "github.com/ava-labs/avalanche-cli/pkg/contract" "github.com/ava-labs/avalanche-cli/pkg/evm" "github.com/ava-labs/avalanche-cli/pkg/key" "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" - "github.com/ava-labs/subnet-evm/accounts/abi/bind" - "github.com/ava-labs/subnet-evm/core/types" - "github.com/ava-labs/subnet-evm/ethclient" - teleporterRegistry "github.com/ava-labs/teleporter/abi-bindings/go/Teleporter/upgrades/TeleporterRegistry" "github.com/ethereum/go-ethereum/common" ) const ( - // TODO: use abi without any download? - teleporterReleaseURL = "https://github.com/ava-labs/teleporter/releases/download/%s/" - teleporterMessengerContractAddressURLFmt = teleporterReleaseURL + "/TeleporterMessenger_Contract_Address_%s.txt" - teleporterMessengerDeployerAddressURLFmt = teleporterReleaseURL + "/TeleporterMessenger_Deployer_Address_%s.txt" - teleporterMessengerDeployerTxURLFmt = teleporterReleaseURL + "/TeleporterMessenger_Deployment_Transaction_%s.txt" + releaseURL = "https://github.com/ava-labs/teleporter/releases/download/%s/" + messengerContractAddressURLFmt = releaseURL + "/TeleporterMessenger_Contract_Address_%s.txt" + messengerDeployerAddressURLFmt = releaseURL + "/TeleporterMessenger_Deployer_Address_%s.txt" + messengerDeployerTxURLFmt = releaseURL + "/TeleporterMessenger_Deployment_Transaction_%s.txt" + registryBytecodeURLFmt = releaseURL + "/TeleporterRegistry_Bytecode_%s.txt" ) var ( - teleporterMessengerDeployerRequiredBalance = big.NewInt(0). - Mul(big.NewInt(1e18), big.NewInt(10)) + messengerDeployerRequiredBalance = big.NewInt(0). + Mul(big.NewInt(1e18), big.NewInt(10)) // 10 AVAX TeleporterPrefundedAddressBalance = big.NewInt(0). Mul(big.NewInt(1e18), big.NewInt(600)) // 600 AVAX ) -func getTeleporterURLs(version string) (string, string, string) { - teleporterMessengerContractAddressURL := fmt.Sprintf( - teleporterMessengerContractAddressURLFmt, +func getTeleporterURLs(version string) (string, string, string, string) { + messengerContractAddressURL := fmt.Sprintf( + messengerContractAddressURLFmt, version, version, ) - teleporterMessengerDeployerAddressURL := fmt.Sprintf( - teleporterMessengerDeployerAddressURLFmt, + messengerDeployerAddressURL := fmt.Sprintf( + messengerDeployerAddressURLFmt, version, version, ) - teleporterMessengerDeployerTxURL := fmt.Sprintf( - teleporterMessengerDeployerTxURLFmt, + messengerDeployerTxURL := fmt.Sprintf( + messengerDeployerTxURLFmt, version, version, ) - return teleporterMessengerContractAddressURL, teleporterMessengerDeployerAddressURL, teleporterMessengerDeployerTxURL + registryBydecodeURL := fmt.Sprintf( + registryBytecodeURLFmt, + version, + version, + ) + return messengerContractAddressURL, messengerDeployerAddressURL, messengerDeployerTxURL, registryBydecodeURL } type Deployer struct { - teleporterMessengerContractAddress string - teleporterMessengerDeployerAddress string - teleporterMessengerDeployerTx string + messengerContractAddress string + messengerDeployerAddress string + messengerDeployerTx string + registryBydecode string } func (t *Deployer) GetAssets( teleporterInstallDir string, version string, -) (string, string, string, error) { +) (string, string, string, string, error) { if err := t.DownloadAssets(teleporterInstallDir, version); err != nil { - return "", "", "", err + return "", "", "", "", err } - return t.teleporterMessengerContractAddress, t.teleporterMessengerDeployerAddress, t.teleporterMessengerDeployerTx, nil + return t.messengerContractAddress, t.messengerDeployerAddress, t.messengerDeployerTx, t.registryBydecode, nil } func (t *Deployer) DownloadAssets( @@ -82,71 +84,90 @@ func (t *Deployer) DownloadAssets( ) error { var err error binDir := filepath.Join(teleporterInstallDir, version) - teleporterMessengerContractAddressURL, teleporterMessengerDeployerAddressURL, teleporterMessengerDeployerTxURL := getTeleporterURLs( + messengerContractAddressURL, messengerDeployerAddressURL, messengerDeployerTxURL, registryBydecodeURL := getTeleporterURLs( version, ) - teleporterMessengerContractAddressPath := filepath.Join( + messengerContractAddressPath := filepath.Join( + binDir, + filepath.Base(messengerContractAddressURL), + ) + messengerDeployerAddressPath := filepath.Join( binDir, - filepath.Base(teleporterMessengerContractAddressURL), + filepath.Base(messengerDeployerAddressURL), ) - teleporterMessengerDeployerAddressPath := filepath.Join( + messengerDeployerTxPath := filepath.Join( binDir, - filepath.Base(teleporterMessengerDeployerAddressURL), + filepath.Base(messengerDeployerTxURL), ) - teleporterMessengerDeployerTxPath := filepath.Join( + registryBytecodePath := filepath.Join( binDir, - filepath.Base(teleporterMessengerDeployerTxURL), + filepath.Base(registryBydecodeURL), ) - if t.teleporterMessengerContractAddress == "" { - var teleporterMessengerContractAddressBytes []byte - if utils.FileExists(teleporterMessengerContractAddressPath) { - teleporterMessengerContractAddressBytes, err = os.ReadFile( - teleporterMessengerContractAddressPath, + if t.messengerContractAddress == "" { + var messengerContractAddressBytes []byte + if utils.FileExists(messengerContractAddressPath) { + messengerContractAddressBytes, err = os.ReadFile( + messengerContractAddressPath, ) if err != nil { return err } } else { // get target teleporter messenger contract address - teleporterMessengerContractAddressBytes, err = utils.DownloadWithTee(teleporterMessengerContractAddressURL, teleporterMessengerContractAddressPath) + messengerContractAddressBytes, err = utils.DownloadWithTee(messengerContractAddressURL, messengerContractAddressPath) if err != nil { return err } } - t.teleporterMessengerContractAddress = string(teleporterMessengerContractAddressBytes) + t.messengerContractAddress = string(messengerContractAddressBytes) } - if t.teleporterMessengerDeployerAddress == "" { - var teleporterMessengerDeployerAddressBytes []byte - if utils.FileExists(teleporterMessengerDeployerAddressPath) { - teleporterMessengerDeployerAddressBytes, err = os.ReadFile( - teleporterMessengerDeployerAddressPath, + if t.messengerDeployerAddress == "" { + var messengerDeployerAddressBytes []byte + if utils.FileExists(messengerDeployerAddressPath) { + messengerDeployerAddressBytes, err = os.ReadFile( + messengerDeployerAddressPath, ) if err != nil { return err } } else { // get teleporter deployer address - teleporterMessengerDeployerAddressBytes, err = utils.DownloadWithTee(teleporterMessengerDeployerAddressURL, teleporterMessengerDeployerAddressPath) + messengerDeployerAddressBytes, err = utils.DownloadWithTee(messengerDeployerAddressURL, messengerDeployerAddressPath) + if err != nil { + return err + } + } + t.messengerDeployerAddress = string(messengerDeployerAddressBytes) + } + if t.messengerDeployerTx == "" { + var messengerDeployerTxBytes []byte + if utils.FileExists(messengerDeployerTxPath) { + messengerDeployerTxBytes, err = os.ReadFile(messengerDeployerTxPath) + if err != nil { + return err + } + } else { + messengerDeployerTxBytes, err = utils.DownloadWithTee(messengerDeployerTxURL, messengerDeployerTxPath) if err != nil { return err } } - t.teleporterMessengerDeployerAddress = string(teleporterMessengerDeployerAddressBytes) + t.messengerDeployerTx = string(messengerDeployerTxBytes) } - if t.teleporterMessengerDeployerTx == "" { - var teleporterMessengerDeployerTxBytes []byte - if utils.FileExists(teleporterMessengerDeployerTxPath) { - teleporterMessengerDeployerTxBytes, err = os.ReadFile(teleporterMessengerDeployerTxPath) + if t.registryBydecode == "" { + var registryBytecodeBytes []byte + if utils.FileExists(registryBytecodePath) { + registryBytecodeBytes, err = os.ReadFile(registryBytecodePath) if err != nil { return err } } else { - teleporterMessengerDeployerTxBytes, err = utils.DownloadWithTee(teleporterMessengerDeployerTxURL, teleporterMessengerDeployerTxPath) + registryBytecodeBytes, err = utils.DownloadWithTee(registryBydecodeURL, registryBytecodePath) if err != nil { return err } } - t.teleporterMessengerDeployerTx = string(teleporterMessengerDeployerTxBytes) + t.registryBydecode = string(registryBytecodeBytes) } return nil } @@ -156,7 +177,7 @@ func (t *Deployer) Deploy( version string, subnetName string, rpcURL string, - prefundedPrivateKey string, + privateKey string, deployMessenger bool, deployRegistry bool, ) (bool, string, string, error) { @@ -172,12 +193,12 @@ func (t *Deployer) Deploy( version, subnetName, rpcURL, - prefundedPrivateKey, + privateKey, ) } if err == nil && deployRegistry { if !deployMessenger || !alreadyDeployed { - registryAddress, err = t.DeployRegistry(teleporterInstallDir, version, subnetName, rpcURL, prefundedPrivateKey) + registryAddress, err = t.DeployRegistry(teleporterInstallDir, version, subnetName, rpcURL, privateKey) } } return alreadyDeployed, messengerAddress, registryAddress, err @@ -188,7 +209,7 @@ func (t *Deployer) DeployMessenger( version string, subnetName string, rpcURL string, - prefundedPrivateKey string, + privateKey string, ) (bool, string, error) { if err := t.DownloadAssets(teleporterInstallDir, version); err != nil { return false, "", err @@ -198,41 +219,41 @@ func (t *Deployer) DeployMessenger( if err != nil { return false, "", err } - if teleporterMessengerAlreadyDeployed, err := evm.ContractAlreadyDeployed(client, t.teleporterMessengerContractAddress); err != nil { + if messengerAlreadyDeployed, err := evm.ContractAlreadyDeployed(client, t.messengerContractAddress); err != nil { return false, "", fmt.Errorf("failure making a request to %s: %w", rpcURL, err) - } else if teleporterMessengerAlreadyDeployed { + } else if messengerAlreadyDeployed { ux.Logger.PrintToUser("Teleporter Messenger has already been deployed to %s", subnetName) - return true, t.teleporterMessengerContractAddress, nil + return true, t.messengerContractAddress, nil } // get teleporter deployer balance - teleporterMessengerDeployerBalance, err := evm.GetAddressBalance( + messengerDeployerBalance, err := evm.GetAddressBalance( client, - t.teleporterMessengerDeployerAddress, + t.messengerDeployerAddress, ) if err != nil { return false, "", err } - if teleporterMessengerDeployerBalance.Cmp(teleporterMessengerDeployerRequiredBalance) < 0 { + if messengerDeployerBalance.Cmp(messengerDeployerRequiredBalance) < 0 { toFund := big.NewInt(0). - Sub(teleporterMessengerDeployerRequiredBalance, teleporterMessengerDeployerBalance) + Sub(messengerDeployerRequiredBalance, messengerDeployerBalance) if err := evm.FundAddress( client, - prefundedPrivateKey, - t.teleporterMessengerDeployerAddress, + privateKey, + t.messengerDeployerAddress, toFund, ); err != nil { return false, "", err } } - if err := evm.IssueTx(client, t.teleporterMessengerDeployerTx); err != nil { + if err := evm.IssueTx(client, t.messengerDeployerTx); err != nil { return false, "", err } ux.Logger.PrintToUser( "Teleporter Messenger successfully deployed to %s (%s)", subnetName, - t.teleporterMessengerContractAddress, + t.messengerContractAddress, ) - return false, t.teleporterMessengerContractAddress, nil + return false, t.messengerContractAddress, nil } func (t *Deployer) DeployRegistry( @@ -240,80 +261,38 @@ func (t *Deployer) DeployRegistry( version string, subnetName string, rpcURL string, - prefundedPrivateKey string, + privateKey string, ) (string, error) { if err := t.DownloadAssets(teleporterInstallDir, version); err != nil { return "", err } - teleporterMessengerContractAddress := common.HexToAddress(t.teleporterMessengerContractAddress) - teleporterRegistryConstructorInput := []teleporterRegistry.ProtocolRegistryEntry{ + messengerContractAddress := common.HexToAddress(t.messengerContractAddress) + type ProtocolRegistryEntry struct { + Version *big.Int + ProtocolAddress common.Address + } + constructorInput := []ProtocolRegistryEntry{ { Version: big.NewInt(1), - ProtocolAddress: teleporterMessengerContractAddress, + ProtocolAddress: messengerContractAddress, }, } - client, err := evm.GetClient(rpcURL) - if err != nil { - return "", err - } - defer client.Close() - txOpts, err := evm.GetTxOptsWithSigner(client, prefundedPrivateKey) - if err != nil { - return "", err - } - teleporterRegistryAddress, tx, _, err := DeployTeleporterRegistry( - txOpts, - client, - teleporterRegistryConstructorInput, + registryAddress, err := contract.DeployContract( + rpcURL, + privateKey, + []byte(t.registryBydecode), + "([(uint256, address)])", + constructorInput, ) if err != nil { return "", err } - if _, success, err := evm.WaitForTransaction(client, tx); err != nil { - return "", err - } else if !success { - return "", fmt.Errorf("failed receipt status deploying teleporter registry") - } ux.Logger.PrintToUser( "Teleporter Registry successfully deployed to %s (%s)", subnetName, - teleporterRegistryAddress, + registryAddress, ) - return teleporterRegistryAddress.String(), nil -} - -func DeployTeleporterRegistry( - txOpts *bind.TransactOpts, - client ethclient.Client, - teleporterRegistryConstructorInput []teleporterRegistry.ProtocolRegistryEntry, -) (common.Address, *types.Transaction, *teleporterRegistry.TeleporterRegistry, error) { - const ( - repeatsOnFailure = 3 - sleepBetweenRepeats = 1 * time.Second - ) - var ( - addr common.Address - tx *types.Transaction - registry *teleporterRegistry.TeleporterRegistry - err error - ) - for i := 0; i < repeatsOnFailure; i++ { - ctx, cancel := utils.GetAPILargeContext() - defer cancel() - txOpts.Context = ctx - addr, tx, registry, err = teleporterRegistry.DeployTeleporterRegistry( - txOpts, - client, - teleporterRegistryConstructorInput, - ) - if err == nil { - break - } - err = fmt.Errorf("failure deploying teleporter registry on %#v: %w", client, err) - ux.Logger.RedXToUser("%s", err) - time.Sleep(sleepBetweenRepeats) - } - return addr, tx, registry, err + return registryAddress.Hex(), nil } func getPrivateKey( @@ -366,7 +345,7 @@ func DeployAndFundRelayer( } endpoint := network.BlockchainEndpoint(blockchainID) td := Deployer{} - alreadyDeployed, teleporterMessengerAddress, teleporterRegistryAddress, err := td.Deploy( + alreadyDeployed, messengerAddress, registryAddress, err := td.Deploy( app.GetTeleporterBinDir(), teleporterVersion, subnetName, @@ -393,7 +372,7 @@ func DeployAndFundRelayer( return false, "", "", err } } - return alreadyDeployed, teleporterMessengerAddress, teleporterRegistryAddress, err + return alreadyDeployed, messengerAddress, registryAddress, err } func getTeleporterKeyInfo( @@ -434,7 +413,7 @@ func GetInfo( return nil, err } deployer := Deployer{} - _, ti.MessengerDeployerAddress, _, err = deployer.GetAssets( + _, ti.MessengerDeployerAddress, _, _, err = deployer.GetAssets( app.GetTeleporterBinDir(), ti.Version, ) From 54341c3f5af24070bf2ea4792ca3fad3d5aeb86a Mon Sep 17 00:00:00 2001 From: felipemadero Date: Thu, 20 Jun 2024 13:05:53 -0300 Subject: [PATCH 87/87] Teleporter msg using contract (#1979) * add skel to send cross chain message and to check if message was received * add function to check if message was received on destination * remove unneded send cross chain message param * add options to better encode the message, and to set the destination address * start adding private key control * add private key options * refactor private key digging into separate functions * use new privatekey gattering functions in teleporter deploy * improving * msg working * pass slice example if [()] * using contract method * working * lint --- cmd/teleportercmd/deploy.go | 76 +++------- cmd/teleportercmd/helpers.go | 135 ++++++++++++++++- cmd/teleportercmd/msg.go | 217 +++++++++++++--------------- cmd/teleportercmd/startRelayer.go | 5 +- pkg/bridge/deploy.go | 3 +- pkg/bridge/operate.go | 29 ++-- pkg/contract/contract.go | 232 ++++++++++++++++++++---------- pkg/evm/evm.go | 9 +- pkg/teleporter/operate.go | 137 ++++++++++++++++++ 9 files changed, 577 insertions(+), 266 deletions(-) create mode 100644 pkg/teleporter/operate.go diff --git a/cmd/teleportercmd/deploy.go b/cmd/teleportercmd/deploy.go index e6b995a9c..2b24efdb9 100644 --- a/cmd/teleportercmd/deploy.go +++ b/cmd/teleportercmd/deploy.go @@ -10,10 +10,8 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/cobrautils" "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/networkoptions" - "github.com/ava-labs/avalanche-cli/pkg/prompts" "github.com/ava-labs/avalanche-cli/pkg/subnet" "github.com/ava-labs/avalanche-cli/pkg/teleporter" - "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanchego/ids" "github.com/spf13/cobra" @@ -35,6 +33,7 @@ type DeployFlags struct { MessengerDeployerAddressPath string MessengerDeployerTxPath string RegistryBydecodePath string + PrivateKeyFlags PrivateKeyFlags } const ( @@ -64,9 +63,9 @@ func newDeployCmd() *cobra.Command { cmd.Flags().StringVar(&deployFlags.SubnetName, "subnet", "", "deploy teleporter into the given CLI subnet") cmd.Flags().StringVar(&deployFlags.BlockchainID, "blockchain-id", "", "deploy teleporter into the given blockchain ID/Alias") cmd.Flags().BoolVar(&deployFlags.CChain, "c-chain", false, "deploy teleporter into C-Chain") - cmd.Flags().StringVar(&deployFlags.PrivateKey, "private-key", "", "private key to use to fund teleporter deploy)") - cmd.Flags().StringVar(&deployFlags.KeyName, "key", "", "CLI stored key to use to fund teleporter deploy)") - cmd.Flags().BoolVar(&deployFlags.GenesisKey, "genesis-key", false, "use genesis aidrop key to fund teleporter deploy") + cmd.Flags().StringVar(&deployFlags.PrivateKeyFlags.PrivateKey, "private-key", "", "private key to use to fund teleporter deploy)") + cmd.Flags().StringVar(&deployFlags.PrivateKeyFlags.KeyName, "key", "", "CLI stored key to use to fund teleporter deploy)") + cmd.Flags().BoolVar(&deployFlags.PrivateKeyFlags.GenesisKey, "genesis-key", false, "use genesis aidrop key to fund teleporter deploy") cmd.Flags().BoolVar(&deployFlags.DeployMessenger, "deploy-messenger", true, "deploy Teleporter Messenger") cmd.Flags().BoolVar(&deployFlags.DeployRegistry, "deploy-registry", true, "deploy Teleporter Registry") cmd.Flags().StringVar(&deployFlags.RPCURL, "rpc-url", "", "use the given RPC URL to connect to the subnet") @@ -141,7 +140,7 @@ func CallDeploy(_ []string, flags DeployFlags) error { var ( blockchainID string teleporterSubnetDesc string - privateKey = flags.PrivateKey + privateKey string teleporterVersion string ) switch { @@ -177,69 +176,28 @@ func CallDeploy(_ []string, flags DeployFlags) error { teleporterSubnetDesc = cChainName blockchainID = cChainAlias } - var chainID ids.ID - if flags.CChain || !network.StandardPublicEndpoint() { - chainID, err = utils.GetChainID(network.Endpoint, blockchainID) - if err != nil { - return err - } - } else { - chainID, err = ids.FromString(blockchainID) - if err != nil { - return err - } - } - createChainTx, err := utils.GetBlockchainTx(network.Endpoint, chainID) - if err != nil { - return err - } - if !utils.ByteSliceIsSubnetEvmGenesis(createChainTx.GenesisData) { - return fmt.Errorf("teleporter can only be deployed to Subnet-EVM based vms") - } - if flags.KeyName != "" { - k, err := app.GetKey(flags.KeyName, network, false) - if err != nil { - return err - } - privateKey = k.PrivKeyHex() - } - _, genesisAddress, genesisPrivateKey, err := subnet.GetSubnetAirdropKeyInfo(app, network, flags.SubnetName, createChainTx.GenesisData) + genesisAddress, genesisPrivateKey, err := getEVMSubnetPrefundedKey( + network, + flags.SubnetName, + flags.CChain, + flags.BlockchainID, + ) if err != nil { return err } - if flags.GenesisKey { - privateKey = genesisPrivateKey - } if privateKey == "" { - cliKeyOpt := "Get private key from an existing stored key (created from avalanche key create or avalanche key import)" - customKeyOpt := "Custom" - genesisKeyOpt := fmt.Sprintf("Use the private key of the Genesis Aidrop address %s", genesisAddress) - keyOptions := []string{cliKeyOpt, customKeyOpt} - if genesisPrivateKey != "" { - keyOptions = []string{genesisKeyOpt, cliKeyOpt, customKeyOpt} - } - keyOption, err := app.Prompt.CaptureList("Which private key do you want to use to pay fees?", keyOptions) + privateKey, err = getPrivateKeyFromFlags( + deployFlags.PrivateKeyFlags, + genesisPrivateKey, + ) if err != nil { return err } - switch keyOption { - case cliKeyOpt: - keyName, err := prompts.CaptureKeyName(app.Prompt, "pay fees", app.GetKeyDir(), true) - if err != nil { - return err - } - k, err := app.GetKey(keyName, network, false) - if err != nil { - return err - } - privateKey = k.PrivKeyHex() - case customKeyOpt: - privateKey, err = app.Prompt.CaptureString("Private Key") + if privateKey == "" { + privateKey, err = promptPrivateKey("deploy teleporter", genesisAddress, genesisPrivateKey) if err != nil { return err } - case genesisKeyOpt: - privateKey = genesisPrivateKey } } switch { diff --git a/cmd/teleportercmd/helpers.go b/cmd/teleportercmd/helpers.go index 5da74f259..ce8ce47db 100644 --- a/cmd/teleportercmd/helpers.go +++ b/cmd/teleportercmd/helpers.go @@ -1,11 +1,144 @@ -// Copyright (C) 2022, Ava Labs, Inc. All rights reserved. +// Copyright (C) 2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. package teleportercmd import ( + "fmt" "strings" + + "github.com/ava-labs/avalanche-cli/cmd/subnetcmd" + "github.com/ava-labs/avalanche-cli/pkg/models" + "github.com/ava-labs/avalanche-cli/pkg/prompts" + "github.com/ava-labs/avalanche-cli/pkg/subnet" + "github.com/ava-labs/avalanche-cli/pkg/utils" + "github.com/ava-labs/avalanchego/ids" ) +type PrivateKeyFlags struct { + PrivateKey string + KeyName string + GenesisKey bool +} + +func getPrivateKeyFromFlags( + flags PrivateKeyFlags, + genesisPrivateKey string, +) (string, error) { + privateKey := flags.PrivateKey + if flags.KeyName != "" { + k, err := app.GetKey(flags.KeyName, models.NewLocalNetwork(), false) + if err != nil { + return "", err + } + privateKey = k.PrivKeyHex() + } + if flags.GenesisKey { + privateKey = genesisPrivateKey + } + return privateKey, nil +} + +func getEVMSubnetPrefundedKey( + network models.Network, + subnetName string, + isCChain bool, + blockchainID string, +) (string, string, error) { + if blockchainID == "" { + if isCChain { + blockchainID = "C" + } else { + sc, err := app.LoadSidecar(subnetName) + if err != nil { + return "", "", fmt.Errorf("failed to load sidecar: %w", err) + } + if b, _, err := subnetcmd.HasSubnetEVMGenesis(subnetName); err != nil { + return "", "", err + } else if !b { + return "", "", fmt.Errorf("getPrefundedKey only works on EVM based vms") + } + if sc.Networks[network.Name()].BlockchainID == ids.Empty { + return "", "", fmt.Errorf("subnet has not been deployed to %s", network.Name()) + } + blockchainID = sc.Networks[network.Name()].BlockchainID.String() + } + } + var ( + err error + chainID ids.ID + ) + if isCChain || !network.StandardPublicEndpoint() { + chainID, err = utils.GetChainID(network.Endpoint, blockchainID) + if err != nil { + return "", "", err + } + } else { + chainID, err = ids.FromString(blockchainID) + if err != nil { + return "", "", err + } + } + createChainTx, err := utils.GetBlockchainTx(network.Endpoint, chainID) + if err != nil { + return "", "", err + } + if !utils.ByteSliceIsSubnetEvmGenesis(createChainTx.GenesisData) { + return "", "", fmt.Errorf("getPrefundedKey only works on EVM based vms") + } + _, genesisAddress, genesisPrivateKey, err := subnet.GetSubnetAirdropKeyInfo( + app, + network, + subnetName, + createChainTx.GenesisData, + ) + if err != nil { + return "", "", err + } + return genesisAddress, genesisPrivateKey, nil +} + +func promptPrivateKey( + goal string, + genesisAddress string, + genesisPrivateKey string, +) (string, error) { + privateKey := "" + cliKeyOpt := "Get private key from an existing stored key (created from avalanche key create or avalanche key import)" + customKeyOpt := "Custom" + genesisKeyOpt := fmt.Sprintf("Use the private key of the Genesis Aidrop address %s", genesisAddress) + keyOptions := []string{cliKeyOpt, customKeyOpt} + if genesisPrivateKey != "" { + keyOptions = []string{genesisKeyOpt, cliKeyOpt, customKeyOpt} + } + keyOption, err := app.Prompt.CaptureList( + fmt.Sprintf("Which private key do you want to use to %s?", goal), + keyOptions, + ) + if err != nil { + return "", err + } + switch keyOption { + case cliKeyOpt: + keyName, err := prompts.CaptureKeyName(app.Prompt, goal, app.GetKeyDir(), true) + if err != nil { + return "", err + } + k, err := app.GetKey(keyName, models.NewLocalNetwork(), false) + if err != nil { + return "", err + } + privateKey = k.PrivKeyHex() + case customKeyOpt: + privateKey, err = app.Prompt.CaptureString("Private Key") + if err != nil { + return "", err + } + case genesisKeyOpt: + privateKey = genesisPrivateKey + } + return privateKey, nil +} + func isCChain(subnetName string) bool { return strings.ToLower(subnetName) == "c-chain" || strings.ToLower(subnetName) == "cchain" } diff --git a/cmd/teleportercmd/msg.go b/cmd/teleportercmd/msg.go index 22b6e303d..308082f6f 100644 --- a/cmd/teleportercmd/msg.go +++ b/cmd/teleportercmd/msg.go @@ -1,36 +1,40 @@ -// Copyright (C) 2022, Ava Labs, Inc. All rights reserved. +// Copyright (C) 2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. package teleportercmd import ( - "context" - "encoding/hex" "fmt" - "math/big" "time" + cmdflags "github.com/ava-labs/avalanche-cli/cmd/flags" "github.com/ava-labs/avalanche-cli/cmd/teleportercmd/bridgecmd" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" + "github.com/ava-labs/avalanche-cli/pkg/contract" "github.com/ava-labs/avalanche-cli/pkg/evm" "github.com/ava-labs/avalanche-cli/pkg/networkoptions" + "github.com/ava-labs/avalanche-cli/pkg/prompts" + "github.com/ava-labs/avalanche-cli/pkg/teleporter" "github.com/ava-labs/avalanche-cli/pkg/ux" "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/subnet-evm/core/types" - teleportermessenger "github.com/ava-labs/teleporter/abi-bindings/go/Teleporter/TeleporterMessenger" "github.com/ethereum/go-ethereum/common" "github.com/spf13/cobra" ) +type MsgFlags struct { + Network networkoptions.NetworkFlags + DestinationAddress string + HexEncodedMessage bool + PrivateKeyFlags PrivateKeyFlags +} + var ( msgSupportedNetworkOptions = []networkoptions.NetworkOption{ networkoptions.Local, - networkoptions.Cluster, - networkoptions.Fuji, - networkoptions.Mainnet, networkoptions.Devnet, + networkoptions.Fuji, } - globalNetworkFlags networkoptions.NetworkFlags + msgFlags MsgFlags ) // avalanche teleporter msg @@ -42,7 +46,12 @@ func newMsgCmd() *cobra.Command { RunE: msg, Args: cobrautils.ExactArgs(3), } - networkoptions.AddNetworkFlagsToCmd(cmd, &globalNetworkFlags, true, msgSupportedNetworkOptions) + networkoptions.AddNetworkFlagsToCmd(cmd, &msgFlags.Network, true, msgSupportedNetworkOptions) + cmd.Flags().BoolVar(&msgFlags.HexEncodedMessage, "hex-encoded", false, "given message is hex encoded") + cmd.Flags().StringVar(&msgFlags.DestinationAddress, "destination-address", "", "deliver the message to the given contract destination address") + cmd.Flags().StringVar(&msgFlags.PrivateKeyFlags.PrivateKey, "private-key", "", "private key to use as message originator and to pay source blockchain fees") + cmd.Flags().StringVar(&msgFlags.PrivateKeyFlags.KeyName, "key", "", "CLI stored key to use to use as message originator and to pay source blockchain fees") + cmd.Flags().BoolVar(&msgFlags.PrivateKeyFlags.GenesisKey, "genesis-key", false, "use genesis aidrop key to use as message originator and to pay source blockchain fees") return cmd } @@ -51,6 +60,14 @@ func msg(_ *cobra.Command, args []string) error { destSubnetName := args[1] message := args[2] + if !cmdflags.EnsureMutuallyExclusive([]bool{ + msgFlags.PrivateKeyFlags.PrivateKey != "", + msgFlags.PrivateKeyFlags.KeyName != "", + msgFlags.PrivateKeyFlags.GenesisKey, + }) { + return fmt.Errorf("--private-key, --key and --genesis-key are mutually exclusive flags") + } + subnetNameToGetNetworkFrom := "" if !isCChain(sourceSubnetName) { subnetNameToGetNetworkFrom = sourceSubnetName @@ -61,7 +78,7 @@ func msg(_ *cobra.Command, args []string) error { network, err := networkoptions.GetNetworkFromCmdLineFlags( app, "", - globalNetworkFlags, + msgFlags.Network, true, false, msgSupportedNetworkOptions, @@ -71,87 +88,78 @@ func msg(_ *cobra.Command, args []string) error { return err } - _, _, sourceChainID, sourceMessengerAddress, _, sourceKey, err := bridgecmd.GetSubnetParams( + genesisAddress, genesisPrivateKey, err := getEVMSubnetPrefundedKey( network, sourceSubnetName, isCChain(sourceSubnetName), + "", ) if err != nil { return err } - _, _, destChainID, destMessengerAddress, _, _, err := bridgecmd.GetSubnetParams( - network, - destSubnetName, - isCChain(destSubnetName), + privateKey, err := getPrivateKeyFromFlags( + msgFlags.PrivateKeyFlags, + genesisPrivateKey, ) if err != nil { return err } - - if sourceMessengerAddress != destMessengerAddress { - return fmt.Errorf("different teleporter messenger addresses among subnets: %s vs %s", sourceMessengerAddress, destMessengerAddress) + if privateKey == "" { + privateKey, err = promptPrivateKey("send the message", genesisAddress, genesisPrivateKey) + if err != nil { + return err + } } - ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) - defer cancel() - - // get clients + messengers - sourceClient, err := evm.GetClient(network.BlockchainEndpoint(sourceChainID.String())) - if err != nil { - return err - } - sourceMessenger, err := teleportermessenger.NewTeleporterMessenger(common.HexToAddress(sourceMessengerAddress), sourceClient) - if err != nil { - return err - } - destWebSocketClient, err := evm.GetClient(network.BlockchainWSEndpoint(destChainID.String())) + _, _, sourceBlockchainID, sourceMessengerAddress, _, _, err := bridgecmd.GetSubnetParams( + network, + sourceSubnetName, + isCChain(sourceSubnetName), + ) if err != nil { return err } - destMessenger, err := teleportermessenger.NewTeleporterMessenger(common.HexToAddress(destMessengerAddress), destWebSocketClient) + _, _, destBlockchainID, destMessengerAddress, _, _, err := bridgecmd.GetSubnetParams( + network, + destSubnetName, + isCChain(destSubnetName), + ) if err != nil { return err } - // subscribe to get new heads from destination - destHeadsCh := make(chan *types.Header, 10) - destHeadsSubscription, err := destWebSocketClient.SubscribeNewHead(ctx, destHeadsCh) - if err != nil { - return err + if sourceMessengerAddress != destMessengerAddress { + return fmt.Errorf("different teleporter messenger addresses among subnets: %s vs %s", sourceMessengerAddress, destMessengerAddress) } - defer destHeadsSubscription.Unsubscribe() - // send tx to the teleporter contract at the source - sourceAddress := common.HexToAddress(sourceKey.C()) - msgInput := teleportermessenger.TeleporterMessageInput{ - DestinationBlockchainID: destChainID, - DestinationAddress: sourceAddress, - FeeInfo: teleportermessenger.TeleporterFeeInfo{ - FeeTokenAddress: sourceAddress, - Amount: big.NewInt(0), - }, - RequiredGasLimit: big.NewInt(1), - AllowedRelayerAddresses: []common.Address{}, - Message: []byte(message), - } - ux.Logger.PrintToUser("Delivering message %q from source subnet %q (%s)", message, sourceSubnetName, sourceChainID) - txOpts, err := evm.GetTxOptsWithSigner(sourceClient, sourceKey.PrivKeyHex()) - if err != nil { - return err + encodedMessage := []byte(message) + if msgFlags.HexEncodedMessage { + encodedMessage = common.FromHex(message) } - txOpts.Context = ctx - tx, err := sourceMessenger.SendCrossChainMessage(txOpts, msgInput) - if err != nil { - return err + destAddr := common.Address{} + if msgFlags.DestinationAddress != "" { + if err := prompts.ValidateAddress(msgFlags.DestinationAddress); err != nil { + return fmt.Errorf("failure validating address %s: %w", msgFlags.DestinationAddress, err) + } + destAddr = common.HexToAddress(msgFlags.DestinationAddress) } - sourceReceipt, b, err := evm.WaitForTransaction(sourceClient, tx) + // send tx to the teleporter contract at the source + ux.Logger.PrintToUser("Delivering message %q from source subnet %q (%s)", message, sourceSubnetName, sourceBlockchainID) + tx, receipt, err := teleporter.SendCrossChainMessage( + network.BlockchainEndpoint(sourceBlockchainID.String()), + common.HexToAddress(sourceMessengerAddress), + privateKey, + destBlockchainID, + destAddr, + encodedMessage, + ) if err != nil { return err } - if !b { + if err == contract.ErrFailedReceiptStatus { txHash := tx.Hash().String() ux.Logger.PrintToUser("error: source receipt status for tx %s is not ReceiptStatusSuccessful", txHash) - trace, err := evm.GetTrace(network.BlockchainEndpoint(sourceChainID.String()), txHash) + trace, err := evm.GetTrace(network.BlockchainEndpoint(sourceBlockchainID.String()), txHash) if err != nil { ux.Logger.PrintToUser("error obtaining tx trace: %s", err) ux.Logger.PrintToUser("") @@ -162,73 +170,40 @@ func msg(_ *cobra.Command, args []string) error { } return fmt.Errorf("source receipt status for tx %s is not ReceiptStatusSuccessful", txHash) } - sourceEvent, err := evm.GetEventFromLogs(sourceReceipt.Logs, sourceMessenger.ParseSendCrossChainMessage) + + event, err := evm.GetEventFromLogs(receipt.Logs, teleporter.ParseSendCrossChainMessage) if err != nil { return err } - if destChainID != ids.ID(sourceEvent.DestinationBlockchainID[:]) { - return fmt.Errorf("invalid destination blockchain id at source event, expected %s, got %s", destChainID, ids.ID(sourceEvent.DestinationBlockchainID[:])) + if destBlockchainID != ids.ID(event.DestinationBlockchainID[:]) { + return fmt.Errorf("invalid destination blockchain id at source event, expected %s, got %s", destBlockchainID, ids.ID(event.DestinationBlockchainID[:])) } - if message != string(sourceEvent.Message.Message) { - return fmt.Errorf("invalid message content at source event, expected %s, got %s", message, string(sourceEvent.Message.Message)) + if message != string(event.Message.Message) { + return fmt.Errorf("invalid message content at source event, expected %s, got %s", message, string(event.Message.Message)) } // receive and process head from destination - ux.Logger.PrintToUser("Waiting for message to be received on destination subnet %q (%s)", destSubnetName, destChainID) - var head *types.Header - select { - case head = <-destHeadsCh: - case <-ctx.Done(): - return ctx.Err() - } - if sourceChainID == destChainID { - // we have another block - select { - case head = <-destHeadsCh: - case <-ctx.Done(): - return ctx.Err() + ux.Logger.PrintToUser("Waiting for message to be delivered to destination subnet %q (%s)", destSubnetName, destBlockchainID) + + arrivalCheckInterval := 100 * time.Millisecond + arrivalCheckTimeout := 10 * time.Second + t0 := time.Now() + for { + if b, err := teleporter.MessageReceived( + network.BlockchainEndpoint(destBlockchainID.String()), + common.HexToAddress(destMessengerAddress), + event.MessageID, + ); err != nil { + return err + } else if b { + break } - } - blockNumber := head.Number - block, err := destWebSocketClient.BlockByNumber(ctx, blockNumber) - if err != nil { - return err - } - if len(block.Transactions()) != 1 { - return fmt.Errorf("expected to have only one transaction on new block at destination") - } - destReceipt, err := destWebSocketClient.TransactionReceipt(ctx, block.Transactions()[0].Hash()) - if err != nil { - return err - } - if destReceipt.Status != types.ReceiptStatusSuccessful { - txHash := block.Transactions()[0].Hash().String() - ux.Logger.PrintToUser("error: dest receipt status for tx %s is not ReceiptStatusSuccessful", txHash) - trace, err := evm.GetTrace(network.BlockchainEndpoint(destChainID.String()), txHash) - if err != nil { - ux.Logger.PrintToUser("error obtaining tx trace: %s", err) - ux.Logger.PrintToUser("") - } else { - ux.Logger.PrintToUser("") - ux.Logger.PrintToUser("trace: %#v", trace) - ux.Logger.PrintToUser("") + elapsed := time.Since(t0) + if elapsed > arrivalCheckTimeout { + return fmt.Errorf("timeout waiting for message to be teleported") } - return fmt.Errorf("dest receipt status for tx %s is not ReceiptStatusSuccessful", txHash) - } - destEvent, err := evm.GetEventFromLogs(destReceipt.Logs, destMessenger.ParseReceiveCrossChainMessage) - if err != nil { - return err - } - - if sourceChainID != ids.ID(destEvent.SourceBlockchainID[:]) { - return fmt.Errorf("invalid source blockchain id at dest event, expected %s, got %s", sourceChainID, ids.ID(destEvent.SourceBlockchainID[:])) - } - if message != string(destEvent.Message.Message) { - return fmt.Errorf("invalid message content at source event, expected %s, got %s", message, string(destEvent.Message.Message)) - } - if sourceEvent.MessageID != destEvent.MessageID { - return fmt.Errorf("unexpected difference between message ID at source and dest events: %s vs %s", hex.EncodeToString(sourceEvent.MessageID[:]), hex.EncodeToString(destEvent.MessageID[:])) + time.Sleep(arrivalCheckInterval) } ux.Logger.PrintToUser("Message successfully Teleported!") diff --git a/cmd/teleportercmd/startRelayer.go b/cmd/teleportercmd/startRelayer.go index 4846c7915..98252fac6 100644 --- a/cmd/teleportercmd/startRelayer.go +++ b/cmd/teleportercmd/startRelayer.go @@ -17,7 +17,10 @@ import ( "github.com/spf13/cobra" ) -var startRelayerNetworkOptions = []networkoptions.NetworkOption{networkoptions.Local, networkoptions.Cluster} +var ( + startRelayerNetworkOptions = []networkoptions.NetworkOption{networkoptions.Local, networkoptions.Cluster} + globalNetworkFlags networkoptions.NetworkFlags +) // avalanche teleporter relayer start func newStartRelayerCmd() *cobra.Command { diff --git a/pkg/bridge/deploy.go b/pkg/bridge/deploy.go index 07fd251f6..4af5c8b92 100644 --- a/pkg/bridge/deploy.go +++ b/pkg/bridge/deploy.go @@ -34,7 +34,7 @@ func RegisterERC20Spoke( feeInfo := TeleporterFeeInfo{ Amount: big.NewInt(0), } - return contract.TxToMethod( + _, _, err := contract.TxToMethod( rpcURL, privateKey, spokeAddress, @@ -42,6 +42,7 @@ func RegisterERC20Spoke( "registerWithHub((address, uint256))", feeInfo, ) + return err } func DeployERC20Spoke( diff --git a/pkg/bridge/operate.go b/pkg/bridge/operate.go index 03d8bfc3f..801a64b35 100644 --- a/pkg/bridge/operate.go +++ b/pkg/bridge/operate.go @@ -4,6 +4,7 @@ package bridge import ( _ "embed" + "fmt" "math/big" "github.com/ava-labs/avalanche-cli/pkg/contract" @@ -49,7 +50,10 @@ func ERC20TokenHubGetTokenAddress( if err != nil { return common.Address{}, err } - tokenAddress := out[0].(common.Address) + tokenAddress, b := out[0].(common.Address) + if !b { + return common.Address{}, fmt.Errorf("error at token call, expected common.Address, got %T", out[0]) + } return tokenAddress, nil } @@ -65,7 +69,10 @@ func NativeTokenHubGetTokenAddress( if err != nil { return common.Address{}, err } - tokenAddress := out[0].(common.Address) + tokenAddress, b := out[0].(common.Address) + if !b { + return common.Address{}, fmt.Errorf("error at wrappedToken call, expected common.Address, got %T", out[0]) + } return tokenAddress, nil } @@ -81,7 +88,10 @@ func ERC20TokenSpokeGetTokenHubAddress( if err != nil { return common.Address{}, err } - tokenHubAddress := out[0].(common.Address) + tokenHubAddress, b := out[0].(common.Address) + if !b { + return common.Address{}, fmt.Errorf("error at tokenHubAddress call, expected common.Address, got %T", out[0]) + } return tokenHubAddress, nil } @@ -108,7 +118,7 @@ func ERC20TokenHubSend( if err != nil { return err } - if err := contract.TxToMethod( + if _, _, err := contract.TxToMethod( rpcURL, privateKey, tokenAddress, @@ -129,7 +139,7 @@ func ERC20TokenHubSend( RequiredGasLimit: big.NewInt(250000), MultiHopFallback: common.Address{}, } - return contract.TxToMethod( + _, _, err = contract.TxToMethod( rpcURL, privateKey, hubAddress, @@ -138,6 +148,7 @@ func ERC20TokenHubSend( params, amount, ) + return err } func NativeTokenHubSend( @@ -173,7 +184,7 @@ func NativeTokenHubSend( RequiredGasLimit: big.NewInt(250000), MultiHopFallback: common.Address{}, } - return contract.TxToMethod( + _, _, err = contract.TxToMethod( rpcURL, privateKey, hubAddress, @@ -181,6 +192,7 @@ func NativeTokenHubSend( "send((bytes32, address, address, address, uint256, uint256, uint256, address))", params, ) + return err } func ERC20TokenSpokeSend( @@ -192,7 +204,7 @@ func ERC20TokenSpokeSend( amountRecipient common.Address, amount *big.Int, ) error { - if err := contract.TxToMethod( + if _, _, err := contract.TxToMethod( rpcURL, privateKey, spokeAddress, @@ -223,7 +235,7 @@ func ERC20TokenSpokeSend( RequiredGasLimit: big.NewInt(250000), MultiHopFallback: common.Address{}, } - return contract.TxToMethod( + _, _, err := contract.TxToMethod( rpcURL, privateKey, spokeAddress, @@ -232,4 +244,5 @@ func ERC20TokenSpokeSend( params, amount, ) + return err } diff --git a/pkg/contract/contract.go b/pkg/contract/contract.go index c54644497..77f07b4a5 100644 --- a/pkg/contract/contract.go +++ b/pkg/contract/contract.go @@ -11,10 +11,14 @@ import ( "strings" "github.com/ava-labs/avalanche-cli/pkg/evm" + "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/subnet-evm/accounts/abi/bind" + "github.com/ava-labs/subnet-evm/core/types" "github.com/ethereum/go-ethereum/common" ) +var ErrFailedReceiptStatus = fmt.Errorf("failed receipt status") + func removeSurroundingParenthesis(s string) (string, error) { s = strings.TrimSpace(s) if len(s) > 0 { @@ -40,16 +44,21 @@ func removeSurroundingBrackets(s string) (string, error) { func getWords(s string) []string { words := []string{} word := "" - insideParenthesis := false + parenthesisCount := 0 insideBrackets := false for _, rune := range s { c := string(rune) - if insideParenthesis { + if parenthesisCount > 0 { word += c + if c == "(" { + parenthesisCount++ + } if c == ")" { - words = append(words, word) - word = "" - insideParenthesis = false + parenthesisCount-- + if parenthesisCount == 0 { + words = append(words, word) + word = "" + } } continue } @@ -72,7 +81,7 @@ func getWords(s string) []string { continue } if c == "(" { - insideParenthesis = true + parenthesisCount++ } if c == "[" { insideBrackets = true @@ -87,10 +96,48 @@ func getWords(s string) []string { func getMap( types []string, - params ...interface{}, + params interface{}, ) ([]map[string]interface{}, error) { r := []map[string]interface{}{} for i, t := range types { + var ( + param interface{} + name string + structName string + ) + rt := reflect.ValueOf(params) + if rt.Kind() == reflect.Ptr { + rt = rt.Elem() + } + if rt.Kind() == reflect.Slice { + if rt.Len() != len(types) { + if rt.Len() == 1 { + return getMap(types, rt.Index(0).Interface()) + } else { + return nil, fmt.Errorf( + "inconsistency in slice len between method esp %q and given params %#v: expected %d got %d", + types, + params, + len(types), + rt.Len(), + ) + } + } + param = rt.Index(i).Interface() + } else if rt.Kind() == reflect.Struct { + if rt.NumField() < len(types) { + return nil, fmt.Errorf( + "inconsistency in struct len between method esp %q and given params %#v: expected %d got %d", + types, + params, + len(types), + rt.NumField(), + ) + } + name = rt.Type().Field(i).Name + structName = rt.Type().Field(i).Type.Name() + param = rt.Field(i).Interface() + } m := map[string]interface{}{} switch { case string(t[0]) == "(": @@ -100,16 +147,18 @@ func getMap( if err != nil { return nil, err } - m["components"], err = getMap(getWords(t), params[i]) + m["components"], err = getMap(getWords(t), param) if err != nil { return nil, err } - m["internaltype"] = "tuple" + if structName != "" { + m["internalType"] = "struct " + structName + } else { + m["internalType"] = "tuple" + } m["type"] = "tuple" - m["name"] = "" + m["name"] = name case string(t[0]) == "[": - // TODO: add more types - // slice struct type var err error t, err = removeSurroundingBrackets(t) if err != nil { @@ -120,30 +169,30 @@ func getMap( if err != nil { return nil, err } - m["components"], err = getMap(getWords(t), params[i]) + rt := reflect.ValueOf(param) + if rt.Kind() != reflect.Slice { + return nil, fmt.Errorf("expected param for field %d of esp %q to be an slice", i, types) + } + param = reflect.Zero(rt.Type().Elem()).Interface() + structName = rt.Type().Elem().Name() + m["components"], err = getMap(getWords(t), param) if err != nil { return nil, err } - m["internaltype"] = "tuple[]" + if structName != "" { + m["internalType"] = "struct " + structName + "[]" + } else { + m["internalType"] = "tuple[]" + } m["type"] = "tuple[]" - m["name"] = "" + m["name"] = name } else { - m["internaltype"] = fmt.Sprintf("%s[]", t) + m["internalType"] = fmt.Sprintf("%s[]", t) m["type"] = fmt.Sprintf("%s[]", t) - m["name"] = "" + m["name"] = name } default: - name := "" - if len(params) == 1 { - rt := reflect.ValueOf(params[0]) - if rt.Kind() == reflect.Slice && rt.Len() > 0 { - rt = rt.Index(0) - } - if rt.Kind() == reflect.Struct && rt.NumField() == len(types) { - name = rt.Type().Field(i).Name - } - } - m["internaltype"] = t + m["internalType"] = t m["type"] = t m["name"] = name } @@ -152,71 +201,86 @@ func getMap( return r, nil } -func ParseMethodEsp( - methodEsp string, +func ParseEsp( + esp string, + indexedFields []int, constructor bool, + event bool, paid bool, view bool, params ...interface{}, ) (string, string, error) { - index := strings.Index(methodEsp, "(") + index := strings.Index(esp, "(") if index == -1 { - return methodEsp, "", nil + return esp, "", nil } - methodName := methodEsp[:index] - methodTypes := methodEsp[index:] - methodInputs := "" - methodOutputs := "" - index = strings.Index(methodTypes, "->") + name := esp[:index] + types := esp[index:] + inputs := "" + outputs := "" + index = strings.Index(types, "->") if index == -1 { - methodInputs = methodTypes + inputs = types } else { - methodInputs = methodTypes[:index] - methodOutputs = methodTypes[index+2:] + inputs = types[:index] + outputs = types[index+2:] } var err error - methodInputs, err = removeSurroundingParenthesis(methodInputs) + inputs, err = removeSurroundingParenthesis(inputs) if err != nil { return "", "", err } - methodOutputs, err = removeSurroundingParenthesis(methodOutputs) + outputs, err = removeSurroundingParenthesis(outputs) if err != nil { return "", "", err } - inputTypes := getWords(methodInputs) - outputTypes := getWords(methodOutputs) - inputs, err := getMap(inputTypes, params...) + inputTypes := getWords(inputs) + outputTypes := getWords(outputs) + inputsMaps, err := getMap(inputTypes, params) if err != nil { return "", "", err } - outputs, err := getMap(outputTypes) + outputsMaps, err := getMap(outputTypes, nil) if err != nil { return "", "", err } + if event { + for i := range inputsMaps { + if utils.Belongs(indexedFields, i) { + inputsMaps[i]["indexed"] = true + } + } + } abiMap := []map[string]interface{}{ { - "inputs": inputs, - "stateMutability": "nonpayable", - "type": "function", + "inputs": inputsMaps, }, } - if !constructor { - abiMap[0]["outputs"] = outputs - abiMap[0]["name"] = methodName - } else { - abiMap[0]["type"] = "constructor" - } - if paid { + switch { + case paid: abiMap[0]["stateMutability"] = "payable" - } - if view { + case view: abiMap[0]["stateMutability"] = "view" + default: + abiMap[0]["stateMutability"] = "nonpayable" + } + switch { + case constructor: + abiMap[0]["type"] = "constructor" + case event: + abiMap[0]["type"] = "event" + abiMap[0]["name"] = name + delete(abiMap[0], "stateMutability") + default: + abiMap[0]["type"] = "function" + abiMap[0]["outputs"] = outputsMaps + abiMap[0]["name"] = name } abiBytes, err := json.MarshalIndent(abiMap, "", " ") if err != nil { return "", "", err } - return methodName, string(abiBytes), nil + return name, string(abiBytes), nil } func TxToMethod( @@ -226,39 +290,40 @@ func TxToMethod( payment *big.Int, methodEsp string, params ...interface{}, -) error { - methodName, methodABI, err := ParseMethodEsp(methodEsp, false, payment != nil, false, params...) +) (*types.Transaction, *types.Receipt, error) { + methodName, methodABI, err := ParseEsp(methodEsp, nil, false, false, payment != nil, false, params...) if err != nil { - return err + return nil, nil, err } metadata := &bind.MetaData{ ABI: methodABI, } abi, err := metadata.GetAbi() if err != nil { - return err + return nil, nil, err } client, err := evm.GetClient(rpcURL) if err != nil { - return err + return nil, nil, err } defer client.Close() contract := bind.NewBoundContract(contractAddress, *abi, client, client, client) txOpts, err := evm.GetTxOptsWithSigner(client, privateKey) if err != nil { - return err + return nil, nil, err } txOpts.Value = payment tx, err := contract.Transact(txOpts, methodName, params...) if err != nil { - return err + return nil, nil, err } - if _, success, err := evm.WaitForTransaction(client, tx); err != nil { - return err + receipt, success, err := evm.WaitForTransaction(client, tx) + if err != nil { + return tx, nil, err } else if !success { - return fmt.Errorf("failed receipt status deploying contract") + return tx, receipt, ErrFailedReceiptStatus } - return nil + return tx, receipt, nil } func CallToMethod( @@ -267,7 +332,7 @@ func CallToMethod( methodEsp string, params ...interface{}, ) ([]interface{}, error) { - methodName, methodABI, err := ParseMethodEsp(methodEsp, false, false, true, params...) + methodName, methodABI, err := ParseEsp(methodEsp, nil, false, false, false, true, params...) if err != nil { return nil, err } @@ -299,7 +364,7 @@ func DeployContract( methodEsp string, params ...interface{}, ) (common.Address, error) { - _, methodABI, err := ParseMethodEsp(methodEsp, true, false, false, params...) + _, methodABI, err := ParseEsp(methodEsp, nil, true, false, false, false, params...) if err != nil { return common.Address{}, err } @@ -328,7 +393,28 @@ func DeployContract( if _, success, err := evm.WaitForTransaction(client, tx); err != nil { return common.Address{}, err } else if !success { - return common.Address{}, fmt.Errorf("failed receipt status deploying contract") + return common.Address{}, ErrFailedReceiptStatus } return address, nil } + +func UnpackLog( + eventEsp string, + indexedFields []int, + log types.Log, + event interface{}, +) error { + eventName, eventABI, err := ParseEsp(eventEsp, indexedFields, false, true, false, false, event) + if err != nil { + return err + } + metadata := &bind.MetaData{ + ABI: eventABI, + } + abi, err := metadata.GetAbi() + if err != nil { + return err + } + contract := bind.NewBoundContract(common.Address{}, *abi, nil, nil, nil) + return contract.UnpackLog(event, eventName, log) +} diff --git a/pkg/evm/evm.go b/pkg/evm/evm.go index 72d115b8e..92ade8440 100644 --- a/pkg/evm/evm.go +++ b/pkg/evm/evm.go @@ -338,13 +338,18 @@ func WaitForTransaction( // Returns the first log in 'logs' that is successfully parsed by 'parser' func GetEventFromLogs[T any](logs []*types.Log, parser func(log types.Log) (T, error)) (T, error) { - for _, log := range logs { + cumErrMsg := "" + for i, log := range logs { event, err := parser(*log) if err == nil { return event, nil } + if cumErrMsg != "" { + cumErrMsg += "; " + } + cumErrMsg += fmt.Sprintf("log %d -> %s", i, err.Error()) } - return *new(T), fmt.Errorf("failed to find %T event in receipt logs", *new(T)) + return *new(T), fmt.Errorf("failed to find %T event in receipt logs: [%s]", *new(T), cumErrMsg) } func GetRPCClient(rpcURL string) (*rpc.Client, error) { diff --git a/pkg/teleporter/operate.go b/pkg/teleporter/operate.go new file mode 100644 index 000000000..e037cfbfc --- /dev/null +++ b/pkg/teleporter/operate.go @@ -0,0 +1,137 @@ +// Copyright (C) 2022, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +package teleporter + +import ( + _ "embed" + "fmt" + "math/big" + + "github.com/ava-labs/avalanche-cli/pkg/contract" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/subnet-evm/core/types" + "github.com/ethereum/go-ethereum/common" +) + +func GetNextMessageID( + rpcURL string, + messengerAddress common.Address, + destinationBlockchainID ids.ID, +) (ids.ID, error) { + out, err := contract.CallToMethod( + rpcURL, + messengerAddress, + "getNextMessageID(bytes32)->(bytes32)", + destinationBlockchainID, + ) + if err != nil { + return ids.Empty, err + } + received, b := out[0].([32]byte) + if !b { + return ids.Empty, fmt.Errorf("error at getNextMessageID call, expected ids.ID, got %T", out[0]) + } + return received, nil +} + +func MessageReceived( + rpcURL string, + messengerAddress common.Address, + messageID ids.ID, +) (bool, error) { + out, err := contract.CallToMethod( + rpcURL, + messengerAddress, + "messageReceived(bytes32)->(bool)", + messageID, + ) + if err != nil { + return false, err + } + received, b := out[0].(bool) + if !b { + return false, fmt.Errorf("error at messageReceived call, expected bool, got %T", out[0]) + } + return received, nil +} + +func SendCrossChainMessage( + rpcURL string, + messengerAddress common.Address, + privateKey string, + destinationBlockchainID ids.ID, + destinationAddress common.Address, + message []byte, +) (*types.Transaction, *types.Receipt, error) { + type FeeInfo struct { + FeeTokenAddress common.Address + Amount *big.Int + } + type Params struct { + DestinationBlockchainID [32]byte + DestinationAddress common.Address + FeeInfo FeeInfo + RequiredGasLimit *big.Int + AllowedRelayerAddresses []common.Address + Message []byte + } + params := Params{ + DestinationBlockchainID: destinationBlockchainID, + DestinationAddress: destinationAddress, + FeeInfo: FeeInfo{ + FeeTokenAddress: common.Address{}, + Amount: big.NewInt(0), + }, + RequiredGasLimit: big.NewInt(1), + AllowedRelayerAddresses: []common.Address{}, + Message: message, + } + return contract.TxToMethod( + rpcURL, + privateKey, + messengerAddress, + nil, + "sendCrossChainMessage((bytes32, address, (address, uint256), uint256, [address], bytes))->(bytes32)", + params, + ) +} + +// events + +type TeleporterMessageReceipt struct { + ReceivedMessageNonce *big.Int + RelayerRewardAddress common.Address +} +type TeleporterFeeInfo struct { + FeeTokenAddress common.Address + Amount *big.Int +} +type TeleporterMessage struct { + MessageNonce *big.Int + OriginSenderAddress common.Address + DestinationBlockchainID [32]byte + DestinationAddress common.Address + RequiredGasLimit *big.Int + AllowedRelayerAddresses []common.Address + Receipts []TeleporterMessageReceipt + Message []byte +} +type TeleporterMessengerSendCrossChainMessage struct { + MessageID [32]byte + DestinationBlockchainID [32]byte + Message TeleporterMessage + FeeInfo TeleporterFeeInfo +} + +func ParseSendCrossChainMessage(log types.Log) (*TeleporterMessengerSendCrossChainMessage, error) { + event := new(TeleporterMessengerSendCrossChainMessage) + if err := contract.UnpackLog( + "SendCrossChainMessage(bytes32,bytes32,(uint256,address,bytes32,address,uint256,[address],[(uint256,address)],bytes),(address,uint256))", + []int{0, 1}, + log, + event, + ); err != nil { + return nil, err + } + return event, nil +}