Submitted by berndartmueller
The EOA is set as the beneficiary of a failed and refunded inbound ERC-20 deposit cctx, instead of a potential intermediary contract. Funds can be stolen from this intermediary contract.
Additionally, but less severe, the zContexts origin is also set to the EOA.
Observers watch external EVM chains for the Deposited event emitted by the ERC20Custody.deposit function on ERC-20 token deposits. Specifically, these logs are processed by calling the GetInboundVoteMsgForDepositedEvent function in the following instances:
However, in line 123, the MsgVoteOnObservedInboundTx messages Sender is set to the transaction signer EOA address (sender) instead of the caller (msg.sender) of the ERC20Custody.deposit function.
It is very likely that an intermediary contract deployed on a supported EVM chain is interacting with the ERC20Custody contract. In this case, the EOA interacting with this contract and subsequently initiating the deposit of the ERC-20 tokens will be set as the Sender address.
If the cctx fails and a refund to the source chain is sent, this EOA will be the receiver of the funds. Depending on the business logic of the intermediary contract, this allows an EOA to steal its funds.
An inbound cctx can fail for various reasons, but most importantly, the error has to originate from node/x/fungible/keeper/deposits.go#L52-L85. For example, if the liquidity cap of the deposited asset is reached and the types.ErrForeignCoinCapReached error is returned, the cctx is considered failed and a refund is initiated.
Given the following simple Solidity contract on Ethereum Mainnet that intends to keep user funds in escrow and some time later, allows the owner of the contract to bridge the aggregated escrowed funds to ZetaChain.
The owner calls the bridge function. The EOA address will be set as the Sender of the MsgVoteOnObservedInboundTx message.
If the inbound cctx fails and a refund is initiated, the EOA will receive all the funds. Consequently, the owner is able to steal the escrowed user funds from this contract:
Consider adding the msg.sender of the ERC20Custody.deposit function as an additional event parameter to the Deposited event. This parameter can then be used to set the Sender of the MsgVoteOnObservedInboundTx message.
lumtis (ZetaChain) confirmed
