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

refactor(e2e): setup zrc20 in one transaction #3077

Merged
merged 1 commit into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
6 changes: 5 additions & 1 deletion cmd/zetae2e/local/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,11 @@ func localE2ETest(cmd *cobra.Command, _ []string) {
// set the authority client to the zeta tx server to be able to query message permissions
deployerRunner.ZetaTxServer.SetAuthorityClient(deployerRunner.AuthorityClient)

// run setup steps that do not require tss
if !skipSetup {
noError(deployerRunner.FundEmissionsPool())
}
gartnera marked this conversation as resolved.
Show resolved Hide resolved

// wait for keygen to be completed
// if setup is skipped, we assume that the keygen is already completed
if !skipSetup {
Expand Down Expand Up @@ -229,7 +234,6 @@ func localE2ETest(cmd *cobra.Command, _ []string) {
if testSolana {
deployerRunner.SetupSolana(conf.AdditionalAccounts.UserSolana.SolanaPrivateKey.String())
}
noError(deployerRunner.FundEmissionsPool())

deployerRunner.MintERC20OnEvm(1000000)

Expand Down
2 changes: 1 addition & 1 deletion e2e/e2etests/test_whitelist_erc20.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func TestWhitelistERC20(r *runner.E2ERunner, _ []string) {
erc20zrc20Addr, err := txserver.FetchAttributeFromTxResponse(res, "zrc20_address")
require.NoError(r, err)

err = r.ZetaTxServer.InitializeLiquidityCap(erc20zrc20Addr)
err = r.ZetaTxServer.InitializeLiquidityCaps(erc20zrc20Addr)
require.NoError(r, err)

// ensure CCTX created
Expand Down
222 changes: 109 additions & 113 deletions e2e/txserver/zeta_tx_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"strings"
"time"

abci "github.com/cometbft/cometbft/abci/types"
rpchttp "github.com/cometbft/cometbft/rpc/client/http"
coretypes "github.com/cometbft/cometbft/rpc/core/types"
"github.com/cosmos/cosmos-sdk/client"
Expand All @@ -32,7 +33,7 @@ import (
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
ethcommon "github.com/ethereum/go-ethereum/common"
"github.com/samber/lo"
"github.com/zeta-chain/ethermint/crypto/hd"
etherminttypes "github.com/zeta-chain/ethermint/types"
evmtypes "github.com/zeta-chain/ethermint/x/evm/types"
Expand Down Expand Up @@ -192,7 +193,7 @@ func (zts ZetaTxServer) GetAccountMnemonic(index int) string {

// BroadcastTx broadcasts a tx to ZetaChain with the provided msg from the account
// and waiting for blockTime for tx to be included in the block
func (zts ZetaTxServer) BroadcastTx(account string, msg sdktypes.Msg) (*sdktypes.TxResponse, error) {
func (zts ZetaTxServer) BroadcastTx(account string, msgs ...sdktypes.Msg) (*sdktypes.TxResponse, error) {
// Find number and sequence and set it
acc, err := zts.clientCtx.Keyring.Key(account)
if err != nil {
Expand All @@ -208,10 +209,13 @@ func (zts ZetaTxServer) BroadcastTx(account string, msg sdktypes.Msg) (*sdktypes
}
zts.txFactory = zts.txFactory.WithAccountNumber(accountNumber).WithSequence(accountSeq)

txBuilder, err := zts.txFactory.BuildUnsignedTx(msg)
txBuilder, err := zts.txFactory.BuildUnsignedTx(msgs...)
if err != nil {
return nil, err
}
// increase gas and fees if multiple messages are provided
txBuilder.SetGasLimit(zts.txFactory.Gas() * uint64(len(msgs)))
txBuilder.SetFeeAmount(zts.txFactory.Fees().MulInt(sdktypes.NewInt(int64(len(msgs)))))

// Sign tx
err = tx.Sign(zts.txFactory, account, txBuilder, true)
Expand All @@ -237,6 +241,9 @@ func broadcastWithBlockTimeout(zts ZetaTxServer, txBytes []byte) (*sdktypes.TxRe
TxHash: res.TxHash,
}, err
}
if res.Code != 0 {
return res, fmt.Errorf("broadcast failed: %s", res.RawLog)
}

exitAfter := time.After(zts.blockTimeout)
hash, err := hex.DecodeString(res.TxHash)
Expand All @@ -261,6 +268,9 @@ func mkTxResult(
clientCtx client.Context,
resTx *coretypes.ResultTx,
) (*sdktypes.TxResponse, error) {
if resTx.TxResult.Code != 0 {
return nil, fmt.Errorf("tx failed: %s", resTx.TxResult.Log)
}
txb, err := clientCtx.TxConfig.TxDecoder()(resTx.Tx)
if err != nil {
return nil, err
Expand Down Expand Up @@ -442,105 +452,102 @@ func (zts ZetaTxServer) DeployZRC20s(
deployerAddr = addrOperational.String()
}

deploy := func(msg *fungibletypes.MsgDeployFungibleCoinZRC20) (string, error) {
// noop
if skipChain(msg.ForeignChainId) {
return "", nil
}

res, err := zts.BroadcastTx(deployerAccount, msg)
if err != nil {
return "", fmt.Errorf("failed to deploy eth zrc20: %w", err)
}

addr, err := fetchZRC20FromDeployResponse(res)
if err != nil {
return "", fmt.Errorf("unable to fetch zrc20 from deploy response: %w", err)
}

if err := zts.InitializeLiquidityCap(addr); err != nil {
return "", fmt.Errorf("unable to initialize liquidity cap: %w", err)
}

return addr, nil
}
deployMsgs := []*fungibletypes.MsgDeployFungibleCoinZRC20{
fungibletypes.NewMsgDeployFungibleCoinZRC20(
deployerAddr,
"",
chains.GoerliLocalnet.ChainId,
18,
"ETH",
"gETH",
coin.CoinType_Gas,
100000,
),
fungibletypes.NewMsgDeployFungibleCoinZRC20(
deployerAddr,
"",
chains.BitcoinRegtest.ChainId,
8,
"BTC",
"tBTC",
coin.CoinType_Gas,
100000,
),
fungibletypes.NewMsgDeployFungibleCoinZRC20(
deployerAddr,
"",
chains.SolanaLocalnet.ChainId,
9,
"Solana",
"SOL",
coin.CoinType_Gas,
100000,
),
fungibletypes.NewMsgDeployFungibleCoinZRC20(
deployerAddr,
"",
chains.TONLocalnet.ChainId,
9,
"TON",
"TON",
coin.CoinType_Gas,
100_000,
),
fungibletypes.NewMsgDeployFungibleCoinZRC20(
deployerAddr,
erc20Addr,
chains.GoerliLocalnet.ChainId,
6,
"USDT",
"USDT",
coin.CoinType_ERC20,
100000,
),
}

// apply skipChain filter and convert to sdk.Msg
deployMsgsIface := lo.FilterMap(
deployMsgs,
func(msg *fungibletypes.MsgDeployFungibleCoinZRC20, _ int) (sdktypes.Msg, bool) {
if skipChain(msg.ForeignChainId) {
return nil, false
}
return msg, true
},
)

// deploy eth zrc20
_, err = deploy(fungibletypes.NewMsgDeployFungibleCoinZRC20(
deployerAddr,
"",
chains.GoerliLocalnet.ChainId,
18,
"ETH",
"gETH",
coin.CoinType_Gas,
100000,
))
res, err := zts.BroadcastTx(deployerAccount, deployMsgsIface...)
if err != nil {
return "", fmt.Errorf("failed to deploy eth zrc20: %s", err.Error())
return "", fmt.Errorf("deploy zrc20s: %w", err)
}

// deploy btc zrc20
_, err = deploy(fungibletypes.NewMsgDeployFungibleCoinZRC20(
deployerAddr,
"",
chains.BitcoinRegtest.ChainId,
8,
"BTC",
"tBTC",
coin.CoinType_Gas,
100000,
))
if err != nil {
return "", fmt.Errorf("failed to deploy btc zrc20: %s", err.Error())
}
deployedEvents := lo.FilterMap(res.Events, func(ev abci.Event, _ int) (*fungibletypes.EventZRC20Deployed, bool) {
pEvent, err := sdktypes.ParseTypedEvent(ev)
if err != nil {
return nil, false
}
deployedEvent, ok := pEvent.(*fungibletypes.EventZRC20Deployed)
return deployedEvent, ok
})

// deploy sol zrc20
_, err = deploy(fungibletypes.NewMsgDeployFungibleCoinZRC20(
deployerAddr,
"",
chains.SolanaLocalnet.ChainId,
9,
"Solana",
"SOL",
coin.CoinType_Gas,
100000,
))
if err != nil {
return "", fmt.Errorf("failed to deploy sol zrc20: %s", err.Error())
}
zrc20Addrs := lo.Map(deployedEvents, func(ev *fungibletypes.EventZRC20Deployed, _ int) string {
return ev.Contract
})

// deploy ton zrc20
_, err = deploy(fungibletypes.NewMsgDeployFungibleCoinZRC20(
deployerAddr,
"",
chains.TONLocalnet.ChainId,
9,
"TON",
"TON",
coin.CoinType_Gas,
100_000,
))
err = zts.InitializeLiquidityCaps(zrc20Addrs...)
if err != nil {
return "", fmt.Errorf("failed to deploy ton zrc20: %w", err)
return "", fmt.Errorf("initialize liquidity cap: %w", err)
}

// deploy erc20 zrc20
erc20zrc20Addr, err := deploy(fungibletypes.NewMsgDeployFungibleCoinZRC20(
deployerAddr,
erc20Addr,
chains.GoerliLocalnet.ChainId,
6,
"USDT",
"USDT",
coin.CoinType_ERC20,
100000,
))
if err != nil {
return "", fmt.Errorf("failed to deploy erc20 zrc20: %s", err.Error())
// find erc20 zrc20
erc20zrc20, ok := lo.Find(deployedEvents, func(ev *fungibletypes.EventZRC20Deployed) bool {
return ev.ChainId == chains.GoerliLocalnet.ChainId && ev.CoinType == coin.CoinType_ERC20
})
if !ok {
return "", fmt.Errorf("unable to find erc20 zrc20")
}

return erc20zrc20Addr, nil
return erc20zrc20.Contract, nil
gartnera marked this conversation as resolved.
Show resolved Hide resolved
}

// FundEmissionsPool funds the emissions pool with the given amount
Expand Down Expand Up @@ -588,31 +595,20 @@ func (zts *ZetaTxServer) SetAuthorityClient(authorityClient authoritytypes.Query
zts.authorityClient = authorityClient
}

// InitializeLiquidityCap initializes the liquidity cap for the given coin with a large value
func (zts ZetaTxServer) InitializeLiquidityCap(zrc20 string) error {
// InitializeLiquidityCaps initializes the liquidity cap for the given coin with a large value
func (zts ZetaTxServer) InitializeLiquidityCaps(zrc20s ...string) error {
liquidityCap := sdktypes.NewUint(1e18).MulUint64(1e12)

msg := fungibletypes.NewMsgUpdateZRC20LiquidityCap(
zts.MustGetAccountAddressFromName(utils.OperationalPolicyName),
zrc20,
liquidityCap,
)
_, err := zts.BroadcastTx(utils.OperationalPolicyName, msg)
return err
}

// fetchZRC20FromDeployResponse fetches the zrc20 address from the response
func fetchZRC20FromDeployResponse(res *sdktypes.TxResponse) (string, error) {
// fetch the erc20 zrc20 contract address and remove the quotes
zrc20Addr, err := FetchAttributeFromTxResponse(res, "Contract")
if err != nil {
return "", fmt.Errorf("failed to fetch zrc20 contract address: %s, %s", err.Error(), res.String())
}
if !ethcommon.IsHexAddress(zrc20Addr) {
return "", fmt.Errorf("invalid address in event: %s", zrc20Addr)
msgs := make([]sdktypes.Msg, len(zrc20s))
for i, zrc20 := range zrc20s {
msgs[i] = fungibletypes.NewMsgUpdateZRC20LiquidityCap(
zts.MustGetAccountAddressFromName(utils.OperationalPolicyName),
zrc20,
liquidityCap,
)
}

return zrc20Addr, nil
_, err := zts.BroadcastTx(utils.OperationalPolicyName, msgs...)
return err
}

// fetchMessagePermissions fetches the message permissions for a given message
Expand Down
Loading