Skip to content

Commit

Permalink
fix(evm)!: endblocker handle message with token (axelarnetwork#1904)
Browse files Browse the repository at this point in the history
* fix(evm)!: endblocker handle message with token

* address comment
  • Loading branch information
haiyizxx authored Mar 15, 2023
1 parent adf79e9 commit 619be7d
Show file tree
Hide file tree
Showing 5 changed files with 227 additions and 99 deletions.
12 changes: 6 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ require (
github.com/tendermint/tm-db v0.6.7
golang.org/x/crypto v0.5.0
golang.org/x/exp v0.0.0-20221018221608-02f3b879a704
golang.org/x/mod v0.8.0
golang.org/x/mod v0.9.0
golang.org/x/sync v0.1.0
golang.org/x/text v0.7.0
golang.org/x/tools v0.6.0
golang.org/x/text v0.8.0
golang.org/x/tools v0.7.0
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2
google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef
google.golang.org/grpc v1.52.0
Expand Down Expand Up @@ -140,9 +140,9 @@ require (
github.com/tyler-smith/go-bip39 v1.0.2 // indirect
github.com/zondax/hid v0.9.0 // indirect
go.etcd.io/bbolt v1.3.6 // indirect
golang.org/x/net v0.6.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/term v0.5.0 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/term v0.6.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
Expand Down
24 changes: 12 additions & 12 deletions go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

110 changes: 77 additions & 33 deletions x/evm/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -567,44 +567,89 @@ func handleConfirmedEvents(ctx sdk.Context, bk types.BaseKeeper, n types.Nexus,
}
}

func validateMessage(ctx sdk.Context, ck types.ChainKeeper, n types.Nexus, m types.MultisigKeeper, chain nexus.Chain, msg nexus.GeneralMessage) (sdk.Int, multisig.KeyID, error) {
chainID := funcs.MustOk(ck.GetChainID(ctx))

func validateMessage(ctx sdk.Context, ck types.ChainKeeper, n types.Nexus, m types.MultisigKeeper, chain nexus.Chain, msg nexus.GeneralMessage) error {
// TODO refactor to do these checks earlier so we don't fail in the end blocker
keyID, ok := m.GetCurrentKeyID(ctx, chain.Name)
_, ok := m.GetCurrentKeyID(ctx, chain.Name)
if !ok {
return chainID, keyID, fmt.Errorf("current key not set")
return fmt.Errorf("current key not set")
}

if !n.IsChainActivated(ctx, chain) {
return chainID, keyID, fmt.Errorf("destination chain de-activated")
return fmt.Errorf("destination chain de-activated")
}

if _, ok := ck.GetGatewayAddress(ctx); !ok {
return fmt.Errorf("destination chain gateway not deployed yet")
}

if !common.IsHexAddress(msg.GetDestinationAddress()) {
return chainID, keyID, fmt.Errorf("invalid contract address")
return fmt.Errorf("invalid contract address")
}

if _, ok := ck.GetGatewayAddress(ctx); !ok {
return chainID, keyID, fmt.Errorf("destination chain gateway not deployed yet")
switch msg.Type() {
case nexus.TypeGeneralMessage:
return nil
case nexus.TypeGeneralMessageWithToken:
token := ck.GetERC20TokenByAsset(ctx, msg.Asset.GetDenom())
if !token.Is(types.Confirmed) {
return fmt.Errorf("asset %s not confirmed on destination chain", msg.Asset.GetDenom())
}
return nil
default:
return fmt.Errorf("unrecognized message type %d", msg.Type())
}
return chainID, keyID, nil
}

func handleMessage(ctx sdk.Context, ck types.ChainKeeper, n types.Nexus, m types.MultisigKeeper, chain nexus.Chain, msg nexus.GeneralMessage) (types.CommandID, error) {
chainID, keyID, err := validateMessage(ctx, ck, n, m, chain, msg)
if err != nil {
return types.CommandID{}, err
}
func handleMessage(ctx sdk.Context, ck types.ChainKeeper, chainID sdk.Int, keyID multisig.KeyID, msg nexus.GeneralMessage) {

dummyTxID := common.BytesToHash(make([]byte, common.HashLength))

cmd := types.NewApproveContractCallCommandGeneric(chainID, keyID, common.HexToAddress(msg.GetDestinationAddress()), common.BytesToHash(msg.PayloadHash), dummyTxID, msg.GetSourceChain(), msg.GetSourceAddress(), 0, msg.ID)
funcs.MustNoErr(ck.EnqueueCommand(ctx, cmd))

return cmd.ID, nil
events.Emit(ctx, &types.ContractCallApproved{
Chain: msg.GetSourceChain(),
EventID: types.EventID(msg.ID),
CommandID: cmd.ID,
Sender: msg.GetSourceAddress(),
DestinationChain: msg.GetDestinationChain(),
ContractAddress: msg.GetDestinationAddress(),
PayloadHash: types.Hash(common.BytesToHash(msg.PayloadHash)),
})

ck.Logger(ctx).Debug("completed handling general message",
types.AttributeKeyChain, msg.GetDestinationChain(),
types.AttributeKeyMessageID, msg.ID,
types.AttributeKeyCommandsID, cmd.ID,
)
}

func handleMessages(ctx sdk.Context, bk types.BaseKeeper, n types.Nexus, m types.MultisigKeeper) {
func handleMessageWithToken(ctx sdk.Context, ck types.ChainKeeper, chainID sdk.Int, keyID multisig.KeyID, msg nexus.GeneralMessage) {
dummyTxID := common.BytesToHash(make([]byte, common.HashLength))
token := ck.GetERC20TokenByAsset(ctx, msg.Asset.GetDenom())

cmd := types.NewApproveContractCallWithMintGeneric(chainID, keyID, dummyTxID, msg, token.GetDetails().Symbol)
funcs.MustNoErr(ck.EnqueueCommand(ctx, cmd))

events.Emit(ctx, &types.ContractCallWithMintApproved{
Chain: msg.GetSourceChain(),
EventID: types.EventID(msg.ID),
CommandID: cmd.ID,
Sender: msg.GetSourceAddress(),
DestinationChain: msg.GetDestinationChain(),
ContractAddress: msg.GetDestinationAddress(),
PayloadHash: types.Hash(common.BytesToHash(msg.PayloadHash)),
Asset: *msg.Asset,
})

ck.Logger(ctx).Debug("completed handling general message with token",
types.AttributeKeyChain, msg.GetDestinationChain(),
types.AttributeKeyMessageID, msg.ID,
types.AttributeKeyCommandsID, cmd.ID,
)
}

func handleMessages(ctx sdk.Context, bk types.BaseKeeper, n types.Nexus, m types.MultisigKeeper) {
for _, chain := range slices.Filter(n.GetChains(ctx), types.IsEVMChain) {
ck := funcs.Must(bk.ForChain(ctx, chain.Name))
endBlockerLimit := ck.GetParams(ctx).EndBlockerLimit
Expand All @@ -615,26 +660,25 @@ func handleMessages(ctx sdk.Context, bk types.BaseKeeper, n types.Nexus, m types
for _, msg := range msgs {
success := false
_ = utils.RunCached(ctx, bk, func(ctx sdk.Context) (bool, error) {
cmdID, err := handleMessage(ctx, ck, n, m, chain, msg)
if err != nil {
if err := validateMessage(ctx, ck, n, m, chain, msg); err != nil {
bk.Logger(ctx).Info(fmt.Sprintf("failed validating message: %s", err.Error()),
types.AttributeKeyChain, msg.GetDestinationChain(),
types.AttributeKeyMessageID, msg.ID,
)
return false, err
}

events.Emit(ctx, &types.ContractCallApproved{
Chain: msg.GetSourceChain(),
EventID: types.EventID(msg.ID),
CommandID: cmdID,
Sender: msg.GetSourceAddress(),
DestinationChain: msg.GetDestinationChain(),
ContractAddress: msg.GetDestinationAddress(),
PayloadHash: types.Hash(common.BytesToHash(msg.PayloadHash)),
})
chainID := funcs.MustOk(ck.GetChainID(ctx))
keyID := funcs.MustOk(m.GetCurrentKeyID(ctx, chain.Name))

ck.Logger(ctx).Debug("completed handling general message",
types.AttributeKeyChain, chain.Name.String(),
types.AttributeKeyMessageID, msg.ID,
types.AttributeKeyCommandsID, cmdID,
)
switch msg.Type() {
case nexus.TypeGeneralMessage:
handleMessage(ctx, ck, chainID, keyID, msg)
case nexus.TypeGeneralMessageWithToken:
handleMessageWithToken(ctx, ck, chainID, keyID, msg)
default:
panic(fmt.Sprintf("unrecognized message type %d", msg.Type()))
}

success = true
return true, nil
Expand Down
Loading

0 comments on commit 619be7d

Please sign in to comment.