From 841c566dd207b43f1ece8988b71cbccffa2214c7 Mon Sep 17 00:00:00 2001 From: Michael Kaplan Date: Mon, 7 Oct 2024 18:38:35 -0400 Subject: [PATCH 1/6] Fix home key initialization --- .../tokentransferrercmd/deploy.go | 79 +++++++++++-------- 1 file changed, 44 insertions(+), 35 deletions(-) diff --git a/cmd/interchaincmd/tokentransferrercmd/deploy.go b/cmd/interchaincmd/tokentransferrercmd/deploy.go index 33b56095a..b46504825 100644 --- a/cmd/interchaincmd/tokentransferrercmd/deploy.go +++ b/cmd/interchaincmd/tokentransferrercmd/deploy.go @@ -9,10 +9,12 @@ import ( "time" cmdflags "github.com/ava-labs/avalanche-cli/cmd/flags" + "github.com/ava-labs/avalanche-cli/pkg/application" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" "github.com/ava-labs/avalanche-cli/pkg/constants" "github.com/ava-labs/avalanche-cli/pkg/contract" "github.com/ava-labs/avalanche-cli/pkg/ictt" + "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/networkoptions" "github.com/ava-labs/avalanche-cli/pkg/precompiles" "github.com/ava-labs/avalanche-cli/pkg/prompts" @@ -101,6 +103,43 @@ func deploy(_ *cobra.Command, args []string) error { return CallDeploy(args, deployFlags) } +func getHomeKeyAndAddress(app *application.Avalanche, network models.Network, homeFlags HomeFlags) (string, string, error) { + // First check if there is a genesis key able to be used. + genesisAddress, genesisPrivateKey, err := contract.GetEVMSubnetPrefundedKey( + app, + network, + homeFlags.chainFlags, + ) + if err != nil { + return "", "", err + } + + // Propmt for the key to be used. + // Note that this key must have enough funds to cover gas cost on the + // home chain, and also enough of the token on the home chain to collateralize + // the remote chain if it is a native token remote. + homeKey, err := prompts.PromptPrivateKey( + app.Prompt, + "pay for home deployment fees, and collateralization (if necessary)", + app.GetKeyDir(), + app.GetKey, + genesisAddress, + genesisPrivateKey, + ) + if err != nil { + return "", "", err + } + + // Calculate the address for the key. + pk, err := crypto.HexToECDSA(homeKey) + if err != nil { + return "", "", err + } + homeKeyAddress := crypto.PubkeyToAddress(pk.PublicKey).Hex() + + return homeKey, homeKeyAddress, nil +} + func CallDeploy(_ []string, flags DeployFlags) error { if !ictt.FoundryIsInstalled() { if err := ictt.InstallFoundry(); err != nil { @@ -304,41 +343,11 @@ func CallDeploy(_ []string, flags DeployFlags) error { } } - var ( - homeKey string - homeKeyAddress string - ) - if flags.homeFlags.homeAddress == "" { - genesisAddress, genesisPrivateKey, err := contract.GetEVMSubnetPrefundedKey( - app, - network, - flags.homeFlags.chainFlags, - ) - if err != nil { - return err - } - homeKey, err = flags.homeFlags.privateKeyFlags.GetPrivateKey(app, genesisPrivateKey) - if err != nil { - return err - } - if homeKey == "" { - homeKey, err = prompts.PromptPrivateKey( - app.Prompt, - "pay for home deploy fees", - app.GetKeyDir(), - app.GetKey, - genesisAddress, - genesisPrivateKey, - ) - if err != nil { - return err - } - } - pk, err := crypto.HexToECDSA(homeKey) - if err != nil { - return err - } - homeKeyAddress = crypto.PubkeyToAddress(pk.PublicKey).Hex() + // Get the key to be used to deploy the token home contract and collateralize the remote + // in the case that it is a native token remote. + homeKey, homeKeyAddress, err := getHomeKeyAndAddress(app, network, flags.homeFlags) + if err != nil { + return err } // Home Contract Validations From 6d318fc01aaa731d084765179e2b7fa07cc40ac6 Mon Sep 17 00:00:00 2001 From: Michael Kaplan Date: Tue, 8 Oct 2024 12:24:31 -0400 Subject: [PATCH 2/6] Balance fetch logs --- cmd/keycmd/list.go | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/cmd/keycmd/list.go b/cmd/keycmd/list.go index 568878e1b..613d5a0ec 100644 --- a/cmd/keycmd/list.go +++ b/cmd/keycmd/list.go @@ -22,6 +22,7 @@ import ( "github.com/ava-labs/coreth/ethclient" "github.com/ethereum/go-ethereum/common" goethereumethclient "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/log" "github.com/liyue201/erc20-go/erc20" "github.com/olekukonko/tablewriter" "github.com/spf13/cobra" @@ -558,28 +559,32 @@ func getEvmBasedChainAddrInfo( if err != nil { return addressInfos, err } + + // Ignore contract address access errors as those may depend on network 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)) - if err != nil { - return addressInfos, err - } - formattedBalance, err := formatCChainBalance(balance) - if err != nil { - return addressInfos, err - } - info := addressInfo{ - kind: kind, - name: name, - chain: chainName, - token: fmt.Sprintf("%s (%s.)", tokenSymbol, tokenAddress[:6]), - address: cChainAddr, - balance: formattedBalance, - network: network.Name(), - } - addressInfos = append(addressInfos, info) + if err != nil { + continue + } + + log.Info("Getting balance for token", "token", tokenSymbol, "address", tokenAddress, "url", cGethClient.URL) + 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: chainName, + token: fmt.Sprintf("%s (%s.)", tokenSymbol, tokenAddress[:6]), + address: cChainAddr, + balance: formattedBalance, + network: network.Name(), } + addressInfos = append(addressInfos, info) } } return addressInfos, nil From 5798dd8a766811e2065b0c6a05afc1959b617784 Mon Sep 17 00:00:00 2001 From: Michael Kaplan Date: Tue, 8 Oct 2024 12:25:08 -0400 Subject: [PATCH 3/6] Balance fetch logs --- cmd/keycmd/list.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/keycmd/list.go b/cmd/keycmd/list.go index 613d5a0ec..a33f82747 100644 --- a/cmd/keycmd/list.go +++ b/cmd/keycmd/list.go @@ -566,7 +566,7 @@ func getEvmBasedChainAddrInfo( continue } - log.Info("Getting balance for token", "token", tokenSymbol, "address", tokenAddress, "url", cGethClient.URL) + log.Info("Getting balance for token", "token", tokenSymbol, "address", tokenAddress) balance, err := token.BalanceOf(nil, common.HexToAddress(cChainAddr)) if err != nil { return addressInfos, err From 0256a8f873a850788bce1305c51a29203db3aba7 Mon Sep 17 00:00:00 2001 From: Michael Kaplan Date: Tue, 8 Oct 2024 12:39:18 -0400 Subject: [PATCH 4/6] Proper balance formatting --- cmd/keycmd/list.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/cmd/keycmd/list.go b/cmd/keycmd/list.go index a33f82747..8a448c0b1 100644 --- a/cmd/keycmd/list.go +++ b/cmd/keycmd/list.go @@ -22,7 +22,6 @@ import ( "github.com/ava-labs/coreth/ethclient" "github.com/ethereum/go-ethereum/common" goethereumethclient "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/log" "github.com/liyue201/erc20-go/erc20" "github.com/olekukonko/tablewriter" "github.com/spf13/cobra" @@ -566,15 +565,22 @@ func getEvmBasedChainAddrInfo( continue } - log.Info("Getting balance for token", "token", tokenSymbol, "address", tokenAddress) + // Get the raw balance for the given token. balance, err := token.BalanceOf(nil, common.HexToAddress(cChainAddr)) if err != nil { return addressInfos, err } - formattedBalance, err := formatCChainBalance(balance) + + // Get the decimal count for the token to format the balance. + // Note: decimals() is not officially part of the IERC20 interface, but is a common extension. + decimals, err := token.Decimals(nil) if err != nil { return addressInfos, err } + + // Format the balance to a human-readable string. + formattedBalance := utils.FormatAmount(balance, decimals) + info := addressInfo{ kind: kind, name: name, From 56555721c6597c5d1c8506bfb88df4207be4c0d0 Mon Sep 17 00:00:00 2001 From: Michael Kaplan Date: Tue, 8 Oct 2024 14:27:58 -0400 Subject: [PATCH 5/6] Native token remote flow fixes --- .../tokentransferrercmd/deploy.go | 20 ++++++++++++------- pkg/ictt/deploy.go | 4 +++- pkg/ictt/operate.go | 2 ++ 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/cmd/interchaincmd/tokentransferrercmd/deploy.go b/cmd/interchaincmd/tokentransferrercmd/deploy.go index b46504825..cded2f221 100644 --- a/cmd/interchaincmd/tokentransferrercmd/deploy.go +++ b/cmd/interchaincmd/tokentransferrercmd/deploy.go @@ -492,7 +492,6 @@ func CallDeploy(_ []string, flags DeployFlags) error { if err := ictt.BuildContracts(app); err != nil { return err } - ux.Logger.PrintToUser("") // Home Deploy icttSrcDir, err := ictt.RepoDir(app) @@ -676,8 +675,10 @@ func CallDeploy(_ []string, flags DeployFlags) error { return err } } + ux.Logger.PrintToUser("Remote Deployed to %s", remoteRPCEndpoint) + ux.Logger.PrintToUser("Remote Address: %s", remoteAddress) - if err := ictt.RegisterERC20Remote( + if err := ictt.RegisterRemote( remoteRPCEndpoint, remoteKey, remoteAddress, @@ -688,6 +689,7 @@ func CallDeploy(_ []string, flags DeployFlags) error { checkInterval := 100 * time.Millisecond checkTimeout := 10 * time.Second t0 := time.Now() + var collateralNeeded *big.Int for { registeredRemote, err := ictt.TokenHomeGetRegisteredRemote( homeRPCEndpoint, @@ -699,6 +701,7 @@ func CallDeploy(_ []string, flags DeployFlags) error { return err } if registeredRemote.Registered { + collateralNeeded = registeredRemote.CollateralNeeded break } elapsed := time.Since(t0) @@ -708,19 +711,21 @@ func CallDeploy(_ []string, flags DeployFlags) error { time.Sleep(checkInterval) } - if flags.remoteFlags.native { + // Collateralize the remote contract on the home contract if necessary + if collateralNeeded.Cmp(big.NewInt(0)) != 0 { err = ictt.TokenHomeAddCollateral( homeRPCEndpoint, homeAddress, homeKey, remoteBlockchainID, remoteAddress, - remoteSupply, + collateralNeeded, ) if err != nil { return err } + // Check that the remote is collateralized on the home contract now. registeredRemote, err := ictt.TokenHomeGetRegisteredRemote( homeRPCEndpoint, homeAddress, @@ -733,7 +738,10 @@ func CallDeploy(_ []string, flags DeployFlags) error { if registeredRemote.CollateralNeeded.Cmp(big.NewInt(0)) != 0 { return fmt.Errorf("failure setting collateral in home endpoint: remaining collateral=%d", registeredRemote.CollateralNeeded) } + } + if flags.remoteFlags.native { + ux.Logger.PrintToUser("Enabling native token remote contract to mint native tokens") if err := precompiles.SetEnabled( remoteRPCEndpoint, precompiles.NativeMinterPrecompile, @@ -743,6 +751,7 @@ func CallDeploy(_ []string, flags DeployFlags) error { return err } + // Send a single token unit to report that the remote is collateralized. err = ictt.Send( homeRPCEndpoint, homeAddress, @@ -794,8 +803,5 @@ func CallDeploy(_ []string, flags DeployFlags) error { } } - ux.Logger.PrintToUser("Remote Deployed to %s", remoteRPCEndpoint) - ux.Logger.PrintToUser("Remote Address: %s", remoteAddress) - return nil } diff --git a/pkg/ictt/deploy.go b/pkg/ictt/deploy.go index 93433d444..657de44fd 100644 --- a/pkg/ictt/deploy.go +++ b/pkg/ictt/deploy.go @@ -10,6 +10,7 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/contract" "github.com/ava-labs/avalanche-cli/pkg/utils" + "github.com/ava-labs/avalanche-cli/pkg/ux" "github.com/ethereum/go-ethereum/common" ) @@ -26,11 +27,12 @@ type TokenRemoteSettings struct { TokenHomeDecimals uint8 } -func RegisterERC20Remote( +func RegisterRemote( rpcURL string, privateKey string, remoteAddress common.Address, ) error { + ux.Logger.PrintToUser("Registering remote contract with home contract") feeInfo := TeleporterFeeInfo{ Amount: big.NewInt(0), } diff --git a/pkg/ictt/operate.go b/pkg/ictt/operate.go index 6b173e8b5..02689dc85 100644 --- a/pkg/ictt/operate.go +++ b/pkg/ictt/operate.go @@ -8,6 +8,7 @@ import ( "math/big" "github.com/ava-labs/avalanche-cli/pkg/contract" + "github.com/ava-labs/avalanche-cli/pkg/ux" "github.com/ava-labs/avalanchego/ids" "github.com/ethereum/go-ethereum/common" ) @@ -458,6 +459,7 @@ func TokenHomeAddCollateral( remoteAddress common.Address, amount *big.Int, ) error { + ux.Logger.PrintToUser("Collateralizing remote contract on the home chain") endpointKind, err := GetEndpointKind( rpcURL, homeAddress, From b7a4461e84f60f910e4de60e72b6981fcbc03b54 Mon Sep 17 00:00:00 2001 From: Michael Kaplan Date: Tue, 8 Oct 2024 14:43:50 -0400 Subject: [PATCH 6/6] Only use decimals if not using Gwei --- cmd/keycmd/list.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cmd/keycmd/list.go b/cmd/keycmd/list.go index 8a448c0b1..7170e7f2d 100644 --- a/cmd/keycmd/list.go +++ b/cmd/keycmd/list.go @@ -579,7 +579,12 @@ func getEvmBasedChainAddrInfo( } // Format the balance to a human-readable string. - formattedBalance := utils.FormatAmount(balance, decimals) + var formattedBalance string + if useGwei { + formattedBalance = fmt.Sprintf("%d", balance) + } else { + formattedBalance = utils.FormatAmount(balance, decimals) + } info := addressInfo{ kind: kind,