Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(e2e): add support for dynamically resolving erc20 addresses #2783

Merged
merged 3 commits into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions cmd/zetae2e/config/clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ type E2EClients struct {
ZevmAuth *bind.TransactOpts
}

// zetaChainClients contains all the RPC clients and gRPC clients for ZetaChain
type zetaChainClients struct {
// ZetaChainClients contains all the RPC clients and gRPC clients for ZetaChain
type ZetaChainClients struct {
AuthorityClient authoritytypes.QueryClient
CctxClient crosschaintypes.QueryClient
FungibleClient fungibletypes.QueryClient
Expand Down Expand Up @@ -73,7 +73,7 @@ func getClientsFromConfig(ctx context.Context, conf config.Config, account confi
if err != nil {
return E2EClients{}, fmt.Errorf("failed to get evm client: %w", err)
}
zetaChainClients, err := getZetaClients(
zetaChainClients, err := GetZetaClients(
conf.RPCs.ZetaCoreGRPC,
)
if err != nil {
Expand Down Expand Up @@ -152,14 +152,14 @@ func getEVMClient(
return evmClient, evmAuth, nil
}

// getZetaClients get zeta clients
func getZetaClients(rpc string) (
zetaChainClients,
// GetZetaClients get zeta clients
func GetZetaClients(rpc string) (
ZetaChainClients,
error,
) {
grpcConn, err := grpc.Dial(rpc, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
return zetaChainClients{}, err
return ZetaChainClients{}, err
}

authorityClient := authoritytypes.NewQueryClient(grpcConn)
Expand All @@ -170,7 +170,7 @@ func getZetaClients(rpc string) (
observerClient := observertypes.NewQueryClient(grpcConn)
lightclientClient := lightclienttypes.NewQueryClient(grpcConn)

return zetaChainClients{
return ZetaChainClients{
AuthorityClient: authorityClient,
CctxClient: cctxClient,
FungibleClient: fungibleClient,
Expand Down
70 changes: 59 additions & 11 deletions cmd/zetae2e/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,14 @@ import (
"github.com/zeta-chain/zetacore/e2e/config"
"github.com/zeta-chain/zetacore/e2e/e2etests"
"github.com/zeta-chain/zetacore/e2e/runner"
fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types"
observertypes "github.com/zeta-chain/zetacore/x/observer/types"
)

const flagVerbose = "verbose"
const flagConfig = "config"
const flagERC20ChainName = "erc20-chain-name"
const flagERC20Symbol = "erc20-symbol"

// NewRunCmd returns the run command
// which runs the E2E from a config file describing the tests, networks, and accounts
Expand All @@ -41,6 +45,9 @@ For example: zetae2e run deposit:1000 withdraw: --config config.yml`,
os.Exit(1)
}

cmd.Flags().String(flagERC20ChainName, "", "chain_name from /zeta-chain/observer/supportedChains")
gartnera marked this conversation as resolved.
Show resolved Hide resolved
cmd.Flags().String(flagERC20Symbol, "", "symbol from /zeta-chain/fungible/foreign_coins")

// Retain the verbose flag
cmd.Flags().Bool(flagVerbose, false, "set to true to enable verbose logging")

Expand All @@ -67,6 +74,16 @@ func runE2ETest(cmd *cobra.Command, args []string) error {
// initialize logger
logger := runner.NewLogger(verbose, color.FgHiCyan, "e2e")

// update config with dynamic ERC20
erc20ChainName, _ := cmd.Flags().GetString(flagERC20ChainName)
gartnera marked this conversation as resolved.
Show resolved Hide resolved
erc20Symbol, _ := cmd.Flags().GetString(flagERC20Symbol)
if erc20ChainName != "" && erc20Symbol != "" {
err := updateConfigWithDynamicERC20(cmd.Context(), &conf, erc20ChainName, erc20Symbol)
if err != nil {
return err
}
}

// set config
app.SetConfig()

Expand Down Expand Up @@ -99,11 +116,6 @@ func runE2ETest(cmd *cobra.Command, args []string) error {
testRunner.CctxTimeout = 60 * time.Minute
testRunner.ReceiptTimeout = 60 * time.Minute

balancesBefore, err := testRunner.GetAccountBalances(true)
if err != nil {
return err
}

// parse test names and arguments from cmd args and run them
userTestsConfigs, err := parseCmdArgsToE2ETestRunConfig(args)
if err != nil {
Expand All @@ -119,15 +131,9 @@ func runE2ETest(cmd *cobra.Command, args []string) error {
return err
}

balancesAfter, err := testRunner.GetAccountBalances(true)
if err != nil {
return err
}

// Print tests completion info
logger.Print("tests finished successfully in %s", time.Since(testStartTime).String())
testRunner.Logger.SetColor(color.FgHiRed)
testRunner.PrintTotalDiff(runner.GetAccountBalancesDiff(balancesBefore, balancesAfter))
testRunner.Logger.SetColor(color.FgHiGreen)
testRunner.PrintTestReports(reports)

Expand Down Expand Up @@ -157,3 +163,45 @@ func parseCmdArgsToE2ETestRunConfig(args []string) ([]runner.E2ETestRunConfig, e
}
return tests, nil
}

// updateConfigWithDynamicERC20 loads ERC20 addresses via gRPC given CLI flags
func updateConfigWithDynamicERC20(ctx context.Context, conf *config.Config, erc20ChainName, erc20Symbol string) error {
gartnera marked this conversation as resolved.
Show resolved Hide resolved
clients, err := zetae2econfig.GetZetaClients(conf.RPCs.ZetaCoreGRPC)
if err != nil {
return fmt.Errorf("get zeta clients: %w", err)
}

supportedChainsRes, err := clients.ObserverClient.SupportedChains(ctx, &observertypes.QuerySupportedChains{})
if err != nil {
return fmt.Errorf("get chain params: %w", err)
}

chainID := int64(0)
for _, chain := range supportedChainsRes.Chains {
if chain.Name == erc20ChainName {
chainID = chain.ChainId
break
}
}
if chainID == 0 {
return fmt.Errorf("chain %s not found", erc20ChainName)
}

foreignCoinsRes, err := clients.FungibleClient.ForeignCoinsAll(ctx, &fungibletypes.QueryAllForeignCoinsRequest{})
if err != nil {
return fmt.Errorf("get foreign coins: %w", err)
}

for _, coin := range foreignCoinsRes.ForeignCoins {
if coin.ForeignChainId != chainID {
continue
}
// sometimes symbol is USDT, sometimes it's like USDT.SEPOLIA
gartnera marked this conversation as resolved.
Show resolved Hide resolved
if strings.Contains(coin.Symbol, erc20Symbol) {
conf.Contracts.EVM.ERC20 = config.DoubleQuotedString(coin.Asset)
conf.Contracts.ZEVM.ERC20ZRC20Addr = config.DoubleQuotedString(coin.Zrc20ContractAddress)
return nil
}
}
return fmt.Errorf("erc20 %s not found on %s", erc20Symbol, erc20ChainName)
}
20 changes: 15 additions & 5 deletions e2e/runner/balances.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ import (
"github.com/btcsuite/btcutil"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/pkg/errors"
"github.com/zeta-chain/protocol-contracts/v2/pkg/zrc20.sol"
)

var errNilZRC20 = errors.New("zrc20 contract is nil")

// AccountBalances is a struct that contains the balances of the accounts used in the E2E test
type AccountBalances struct {
ZetaETH *big.Int
Expand All @@ -31,6 +34,13 @@ type AccountBalancesDiff struct {
ERC20 *big.Int
}

func (r *E2ERunner) getZRC20BalanceSafe(z *zrc20.ZRC20) (*big.Int, error) {
if z == nil {
return new(big.Int), errNilZRC20
}
return z.BalanceOf(&bind.CallOpts{}, r.EVMAddress())
}

// GetAccountBalances returns the account balances of the accounts used in the E2E test
func (r *E2ERunner) GetAccountBalances(skipBTC bool) (AccountBalances, error) {
// zevm
Expand All @@ -42,21 +52,21 @@ func (r *E2ERunner) GetAccountBalances(skipBTC bool) (AccountBalances, error) {
if err != nil {
return AccountBalances{}, err
}
zetaEth, err := r.ETHZRC20.BalanceOf(&bind.CallOpts{}, r.EVMAddress())
zetaEth, err := r.getZRC20BalanceSafe(r.ETHZRC20)
if err != nil {
return AccountBalances{}, err
}
zetaErc20, err := r.ERC20ZRC20.BalanceOf(&bind.CallOpts{}, r.EVMAddress())
zetaErc20, err := r.getZRC20BalanceSafe(r.ERC20ZRC20)
if err != nil {
return AccountBalances{}, err
}
zetaBtc, err := r.BTCZRC20.BalanceOf(&bind.CallOpts{}, r.EVMAddress())
zetaBtc, err := r.getZRC20BalanceSafe(r.BTCZRC20)
if err != nil {
return AccountBalances{}, err
}
zetaSol, err := r.SOLZRC20.BalanceOf(&bind.CallOpts{}, r.EVMAddress())
zetaSol, err := r.getZRC20BalanceSafe(r.SOLZRC20)
if err != nil {
return AccountBalances{}, err
r.Logger.Error("get SOL balance: %v", err)
}

// evm
Expand Down
2 changes: 1 addition & 1 deletion e2e/runner/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func (r *E2ERunner) PrintTestReports(tr TestReports) {
if err != nil {
r.Logger.Print("Error rendering test report: %s", err)
}
r.Logger.PrintNoPrefix(table, "")
r.Logger.PrintNoPrefix(table)
}

// NetworkReport is a struct that contains the report for the network used after running e2e tests
Expand Down
Loading