Skip to content

Commit

Permalink
refactor(e2e): use strict event typing (#3079)
Browse files Browse the repository at this point in the history
* refactor(e2e): use strict event typing

* use stricter interface on OfType functions
  • Loading branch information
gartnera authored Nov 1, 2024
1 parent 6eb85e3 commit a35a571
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 124 deletions.
10 changes: 4 additions & 6 deletions e2e/e2etests/test_migrate_chain_support.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,12 +167,10 @@ func TestMigrateChainSupport(r *runner.E2ERunner, _ []string) {
))
require.NoError(r, err)

// retrieve zrc20 and cctx from event
whitelistCCTXIndex, err := txserver.FetchAttributeFromTxResponse(res, "whitelist_cctx_index")
require.NoError(r, err)

erc20zrc20Addr, err := txserver.FetchAttributeFromTxResponse(res, "zrc20_address")
require.NoError(r, err)
event, ok := txserver.EventOfType[*crosschaintypes.EventERC20Whitelist](res.Events)
require.True(r, ok, "no EventERC20Whitelist in %s", res.TxHash)
erc20zrc20Addr := event.Zrc20Address
whitelistCCTXIndex := event.WhitelistCctxIndex

// wait for the whitelist cctx to be mined
newRunner.WaitForMinedCCTXFromIndex(whitelistCCTXIndex)
Expand Down
9 changes: 4 additions & 5 deletions e2e/e2etests/test_migrate_erc20_custody_funds.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,17 @@ func TestMigrateERC20CustodyFunds(r *runner.E2ERunner, _ []string) {
res, err := r.ZetaTxServer.BroadcastTx(utils.AdminPolicyName, msg)
require.NoError(r, err)

// fetch cctx index from tx response
cctxIndex, err := txserver.FetchAttributeFromTxResponse(res, "cctx_index")
require.NoError(r, err)
event, ok := txserver.EventOfType[*crosschaintypes.EventERC20CustodyFundsMigration](res.Events)
require.True(r, ok, "no EventERC20CustodyFundsMigration in %s", res.TxHash)

cctxRes, err := r.CctxClient.Cctx(r.Ctx, &crosschaintypes.QueryGetCctxRequest{Index: cctxIndex})
cctxRes, err := r.CctxClient.Cctx(r.Ctx, &crosschaintypes.QueryGetCctxRequest{Index: event.CctxIndex})
require.NoError(r, err)

cctx := cctxRes.CrossChainTx
r.Logger.CCTX(*cctx, "migration")

// wait for the cctx to be mined
r.WaitForMinedCCTXFromIndex(cctxIndex)
r.WaitForMinedCCTXFromIndex(event.CctxIndex)

// check ERC20 balance on new address
newAddrBalance, err := r.ERC20.BalanceOf(&bind.CallOpts{}, newAddr)
Expand Down
22 changes: 12 additions & 10 deletions e2e/e2etests/test_pause_erc20_custody.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,19 @@ func TestPauseERC20Custody(r *runner.E2ERunner, _ []string) {
res, err := r.ZetaTxServer.BroadcastTx(utils.AdminPolicyName, msg)
require.NoError(r, err)

// fetch cctx index from tx response
cctxIndex, err := txserver.FetchAttributeFromTxResponse(res, "cctx_index")
require.NoError(r, err)
event, ok := txserver.EventOfType[*crosschaintypes.EventERC20CustodyPausing](res.Events)
require.True(r, ok, "no EventERC20CustodyPausing in %s", res.TxHash)

require.True(r, event.Pause, "should be paused")

cctxRes, err := r.CctxClient.Cctx(r.Ctx, &crosschaintypes.QueryGetCctxRequest{Index: cctxIndex})
cctxRes, err := r.CctxClient.Cctx(r.Ctx, &crosschaintypes.QueryGetCctxRequest{Index: event.CctxIndex})
require.NoError(r, err)

cctx := cctxRes.CrossChainTx
r.Logger.CCTX(*cctx, "pausing")

// wait for the cctx to be mined
r.WaitForMinedCCTXFromIndex(cctxIndex)
r.WaitForMinedCCTXFromIndex(event.CctxIndex)

// check ERC20 custody contract is paused
paused, err = r.ERC20Custody.Paused(&bind.CallOpts{})
Expand All @@ -61,18 +62,19 @@ func TestPauseERC20Custody(r *runner.E2ERunner, _ []string) {
res, err = r.ZetaTxServer.BroadcastTx(utils.AdminPolicyName, msg)
require.NoError(r, err)

// fetch cctx index from tx response
cctxIndex, err = txserver.FetchAttributeFromTxResponse(res, "cctx_index")
require.NoError(r, err)
event, ok = txserver.EventOfType[*crosschaintypes.EventERC20CustodyPausing](res.Events)
require.True(r, ok, "no EventERC20CustodyPausing in %s", res.TxHash)

require.False(r, event.Pause, "should be unpaused")

cctxRes, err = r.CctxClient.Cctx(r.Ctx, &crosschaintypes.QueryGetCctxRequest{Index: cctxIndex})
cctxRes, err = r.CctxClient.Cctx(r.Ctx, &crosschaintypes.QueryGetCctxRequest{Index: event.CctxIndex})
require.NoError(r, err)

cctx = cctxRes.CrossChainTx
r.Logger.CCTX(*cctx, "unpausing")

// wait for the cctx to be mined
r.WaitForMinedCCTXFromIndex(cctxIndex)
r.WaitForMinedCCTXFromIndex(event.CctxIndex)

// check ERC20 custody contract is unpaused
paused, err = r.ERC20Custody.Paused(&bind.CallOpts{})
Expand Down
10 changes: 4 additions & 6 deletions e2e/e2etests/test_whitelist_erc20.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,10 @@ func TestWhitelistERC20(r *runner.E2ERunner, _ []string) {
))
require.NoError(r, err)

// retrieve zrc20 and cctx from event
whitelistCCTXIndex, err := txserver.FetchAttributeFromTxResponse(res, "whitelist_cctx_index")
require.NoError(r, err)

erc20zrc20Addr, err := txserver.FetchAttributeFromTxResponse(res, "zrc20_address")
require.NoError(r, err)
event, ok := txserver.EventOfType[*crosschaintypes.EventERC20Whitelist](res.Events)
require.True(r, ok, "no EventERC20Whitelist in %s", res.TxHash)
erc20zrc20Addr := event.Zrc20Address
whitelistCCTXIndex := event.WhitelistCctxIndex

err = r.ZetaTxServer.InitializeLiquidityCaps(erc20zrc20Addr)
require.NoError(r, err)
Expand Down
12 changes: 6 additions & 6 deletions e2e/runner/v2_migration.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,9 @@ func (r *E2ERunner) migrateERC20CustodyFunds() {
res, err := r.ZetaTxServer.BroadcastTx(utils.AdminPolicyName, msgPausing)
require.NoError(r, err)

// fetch cctx index from tx response
cctxIndex, err := txserver.FetchAttributeFromTxResponse(res, "cctx_index")
require.NoError(r, err)
migrationEvent, ok := txserver.EventOfType[*crosschaintypes.EventERC20CustodyFundsMigration](res.Events)
require.True(r, ok, "no EventERC20CustodyFundsMigration in %s", res.TxHash)
cctxIndex := migrationEvent.CctxIndex

cctxRes, err := r.CctxClient.Cctx(r.Ctx, &crosschaintypes.QueryGetCctxRequest{Index: cctxIndex})
require.NoError(r, err)
Expand Down Expand Up @@ -188,9 +188,9 @@ func (r *E2ERunner) migrateERC20CustodyFunds() {
res, err = r.ZetaTxServer.BroadcastTx(utils.AdminPolicyName, msgMigration)
require.NoError(r, err)

// fetch cctx index from tx response
cctxIndex, err = txserver.FetchAttributeFromTxResponse(res, "cctx_index")
require.NoError(r, err)
migrationEvent, ok = txserver.EventOfType[*crosschaintypes.EventERC20CustodyFundsMigration](res.Events)
require.True(r, ok, "no EventERC20CustodyFundsMigration in %s", res.TxHash)
cctxIndex = migrationEvent.CctxIndex

cctxRes, err = r.CctxClient.Cctx(r.Ctx, &crosschaintypes.QueryGetCctxRequest{Index: cctxIndex})
require.NoError(r, err)
Expand Down
128 changes: 37 additions & 91 deletions e2e/txserver/zeta_tx_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package txserver
import (
"context"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"math/big"
Expand Down Expand Up @@ -33,6 +32,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"
"github.com/cosmos/gogoproto/proto"
"github.com/samber/lo"
"github.com/zeta-chain/ethermint/crypto/hd"
etherminttypes "github.com/zeta-chain/ethermint/types"
Expand Down Expand Up @@ -358,59 +358,25 @@ func (zts ZetaTxServer) DeploySystemContracts(
return SystemContractAddresses{}, fmt.Errorf("failed to deploy system contracts: %s", err.Error())
}

systemContractAddress, err := FetchAttributeFromTxResponse(res, "system_contract")
if err != nil {
return SystemContractAddresses{}, fmt.Errorf(
"failed to fetch system contract address: %s; rawlog %s",
err.Error(),
res.RawLog,
)
deployedEvent, ok := EventOfType[*fungibletypes.EventSystemContractsDeployed](res.Events)
if !ok {
return SystemContractAddresses{}, fmt.Errorf("no EventSystemContractsDeployed in %s", res.TxHash)
}

// get system contract
_, err = zts.BroadcastTx(
accountAdmin,
fungibletypes.NewMsgUpdateSystemContract(addrAdmin.String(), systemContractAddress),
fungibletypes.NewMsgUpdateSystemContract(addrAdmin.String(), deployedEvent.SystemContract),
)
if err != nil {
return SystemContractAddresses{}, fmt.Errorf("failed to set system contract: %s", err.Error())
}

// get uniswap contract addresses
uniswapV2FactoryAddr, err := FetchAttributeFromTxResponse(res, "uniswap_v2_factory")
if err != nil {
return SystemContractAddresses{}, fmt.Errorf("failed to fetch uniswap v2 factory address: %s", err.Error())
}
uniswapV2RouterAddr, err := FetchAttributeFromTxResponse(res, "uniswap_v2_router")
if err != nil {
return SystemContractAddresses{}, fmt.Errorf("failed to fetch uniswap v2 router address: %s", err.Error())
}

// get zevm connector address
zevmConnectorAddr, err := FetchAttributeFromTxResponse(res, "connector_zevm")
if err != nil {
return SystemContractAddresses{}, fmt.Errorf(
"failed to fetch zevm connector address: %s, txResponse: %s",
err.Error(),
res.String(),
)
}

// get wzeta address
wzetaAddr, err := FetchAttributeFromTxResponse(res, "wzeta")
if err != nil {
return SystemContractAddresses{}, fmt.Errorf(
"failed to fetch wzeta address: %s, txResponse: %s",
err.Error(),
res.String(),
)
}

return SystemContractAddresses{
UniswapV2FactoryAddr: uniswapV2FactoryAddr,
UniswapV2RouterAddr: uniswapV2RouterAddr,
ZEVMConnectorAddr: zevmConnectorAddr,
WZETAAddr: wzetaAddr,
UniswapV2FactoryAddr: deployedEvent.UniswapV2Factory,
UniswapV2RouterAddr: deployedEvent.UniswapV2Router,
ZEVMConnectorAddr: deployedEvent.ConnectorZevm,
WZETAAddr: deployedEvent.Wzeta,
}, nil
}

Expand Down Expand Up @@ -521,14 +487,10 @@ func (zts ZetaTxServer) DeployZRC20s(
return "", fmt.Errorf("deploy zrc20s: %w", err)
}

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
})
deployedEvents, ok := EventsOfType[*fungibletypes.EventZRC20Deployed](res.Events)
if !ok {
return "", fmt.Errorf("no EventZRC20Deployed in %s", res.TxHash)
}

zrc20Addrs := lo.Map(deployedEvents, func(ev *fungibletypes.EventZRC20Deployed, _ int) string {
return ev.Contract
Expand Down Expand Up @@ -699,48 +661,32 @@ func newFactory(clientCtx client.Context) tx.Factory {
WithFees("100000000000000000azeta")
}

type messageLog struct {
Events []event `json:"events"`
}

type event struct {
Type string `json:"type"`
Attributes []attribute `json:"attributes"`
}

type attribute struct {
Key string `json:"key"`
Value string `json:"value"`
}

// FetchAttributeFromTxResponse fetches the attribute from the tx response
func FetchAttributeFromTxResponse(res *sdktypes.TxResponse, key string) (string, error) {
var logs []messageLog
err := json.Unmarshal([]byte(res.RawLog), &logs)
if err != nil {
return "", fmt.Errorf("failed to unmarshal logs: %s, logs content: %s", err.Error(), res.RawLog)
// EventsOfType gets events of a specified type
func EventsOfType[T proto.Message](events []abci.Event) ([]T, bool) {
var filteredEvents []T
for _, ev := range events {
pEvent, err := sdktypes.ParseTypedEvent(ev)
if err != nil {
continue
}
if typedEvent, ok := pEvent.(T); ok {
filteredEvents = append(filteredEvents, typedEvent)
}
}
return filteredEvents, len(filteredEvents) > 0
}

var attributes []string
for _, log := range logs {
for _, event := range log.Events {
for _, attr := range event.Attributes {
attributes = append(attributes, attr.Key)
if strings.EqualFold(attr.Key, key) {
address := attr.Value

if len(address) < 2 {
return "", fmt.Errorf("invalid address: %s", address)
}

// trim the quotes
address = address[1 : len(address)-1]

return address, nil
}
}
// EventOfType gets one event of a specific type
func EventOfType[T proto.Message](events []abci.Event) (T, bool) {
var event T
for _, ev := range events {
pEvent, err := sdktypes.ParseTypedEvent(ev)
if err != nil {
continue
}
if typedEvent, ok := pEvent.(T); ok {
return typedEvent, true
}
}

return "", fmt.Errorf("attribute %s not found, attributes: %+v", key, attributes)
return event, false
}

0 comments on commit a35a571

Please sign in to comment.