Skip to content

Commit

Permalink
refactor(e2e): setup zrc20 in one transaction
Browse files Browse the repository at this point in the history
  • Loading branch information
gartnera committed Oct 31, 2024
1 parent 6ef5c57 commit f244f94
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 115 deletions.
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())
}

// 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
}

// 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

0 comments on commit f244f94

Please sign in to comment.