Skip to content

Legacy V1 ZetaSent reverts trap WZETA on ConnectorZEVM #4600

Description

@kingpinXD

Summary

A direct user EOA call to ConnectorZEVM.send(...) on ZEVM lands with InboundParams.Sender set to the connector address itself, not the user EOA. When the outbound fails, the V1 revert path picks revertReceiver = InboundParams.Sender = ConnectorZEVM and calls ZetaConnectorZEVM.onRevert(zetaTxSenderAddress = ConnectorZEVM, ...). The connector's onRevert wraps the native ZETA into WZETA and transferFroms it to itself, so the user's refund is trapped on the connector contract.

Root cause

  • x/crosschain/keeper/evm_hooks.go:59-63 sets emittingContract := *msg.To, which is the connector address for a direct EOA call.
  • x/crosschain/keeper/evm_hooks.go:295 writes emittingContract.Hex() into MsgVoteInbound.Sender instead of using the ZetaSent event's own ZetaTxSenderAddress field (correctly set on-chain to msg.sender of the connector call).
  • x/crosschain/types/cctx.go:151 gates the RevertOptions.GetEVMRevertAddress() override to V2 only, so V1 has no user-supplied override path.

Fix

Replace emittingContract.Hex() with the event's ZetaTxSenderAddress.Hex() in ProcessZetaSentEvent (evm_hooks.go:295). The same emittingContract-as-Sender pattern exists in ProcessZRC20WithdrawalEvent (evm_hooks.go:207-226) and should be patched in parallel, using the corresponding event-side from field.

Add an e2e regression on LegacyWithdrawZeta asserting InboundParams.Sender == TxOrigin and zero WZETA delta on ConnectorZEVM post-revert.

Reachability

V1 is still wired in ProcessLogs (evm_hooks.go:103); V2 ZETA flows are gated off at v2_zevm_inbound.go:200-204, so V1 is the only live ZETA cross-chain path. Failure modes that reach the revert leg include restricted-address compliance, insufficient locked balance on the destination connector, dust limits, and paused chain params.

Recovery for trapped balances

Admin policy group 2 can patch the connector via MsgUpdateContractBytecode and sweep accumulated WZETA back to a treasury or to the historic cctx TxOrigin.

Severity

Medium. Self-victimizing (no third-party drain primitive), governance-recoverable, but reachable in production today on the only live legacy ZETA path.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions