code-423n4 / 2023-11-zetachain-findings

0 stars 0 forks source link

Arbitrary destination gas limit for `CoinType_Zeta` cctxs results in paying lower gas fees #401

Open c4-bot-6 opened 11 months ago

c4-bot-6 commented 11 months ago

Lines of code

https://github.com/code-423n4/2023-11-zetachain/blob/b237708ed5e86f12c4bddabddfd42f001e81941a/repos/node/zetaclient/evm_signer.go#L375-L378

Vulnerability details

Impact

Gas fees are underpaid for Zeta token cctx's.

Proof of Concept

Outbound cctx's are processed, collectively signed, and ultimately sent to the receiver chain by the observers via the TryProcessOutTx function.

The gas limit used for the transaction is specified in the cctx's OutboundTxParams.OutboundTxGasLimit and validated in lines 375-382 to ensure the limit is in reasonable bounds and to prevent the transaction from failing due to insufficient gas.

Specifically, a lower limit of 100k is enforced in lines 375-378:

374: gasLimit := send.GetCurrentOutTxParam().OutboundTxGasLimit
375: if gasLimit < 100_000 {
376:    gasLimit = 100_000
377:    logger.Warn().Msgf("gasLimit %d is too low; set to %d", send.GetCurrentOutTxParam().OutboundTxGasLimit, gasLimit)
378: }

The fees for such outbound cctxs are paid and deducted from the transfer amount (InboundTxParams.Amount) by calling the PayGasAndUpdateCctx function in the following instances:

Cctx's with the coin type CoinType_Gas or CoinType_ERC20 have the OutboundTxGasLimit gas limit overwritten by a hardcoded value, see lines 121 and 246.

However, cctx's that transfer Zeta tokens, i.e., with the coin type CoinType_Zeta, do not have the gas limit overwritten, instead it is set to the value that was specified by the sender of the cctx. For example, by calling the ZetaConnectorEth.send function. This gas limit can be arbitrarily set and will be picked up by the observers and included in the MsgVoteOnObservedInboundTx message.

As a result, user's can set the gas limit to the lowest possible value, 1 (0 is not possible due to Uniswap's getAmountIn preventing zero amounts) so that the calculated gas fee for the outbound transaction is almost zero.

Once observers process the outbound transaction, the gas limit (set by the user to 1) is overwritten with the lower bound of 100k and broadcasted to the receiver chain.

Consequently, user's can avoid paying the adequate gas fees for outbound Zeta token transactions and the TSS address will have to pay the gas fees instead.

For completeness it should be mentioned that a protocol fee of currently 2e18 Zeta tokens is charged. This offsets the insufficient gas fees paid by the user to some extent, however, it defeats the purpose of the gas fees and misuses the protocol fee.

Tools Used

Manual review

Recommended mitigation steps

Consider enforcing the minimum gas limit of 100k already in the PayGasInZetaAndUpdateCctx function in line 288.

Assessed type

Invalid Validation

c4-pre-sort commented 11 months ago

DadeKuma marked the issue as duplicate of #240

c4-pre-sort commented 11 months ago

DadeKuma marked the issue as sufficient quality report

c4-judge commented 10 months ago

0xean marked the issue as duplicate of #406

c4-judge commented 10 months ago

0xean marked the issue as satisfactory

c4-judge commented 10 months ago

0xean marked the issue as not a duplicate

c4-judge commented 10 months ago

0xean marked the issue as primary issue

c4-judge commented 10 months ago

0xean marked the issue as selected for report