When reverting a cross chain tx with ERC20/native token as coinType, gas will always be underpaid due to inconsistent handling of median gasPrice #516
Labels
bug
Something isn't working
downgraded by judge
Judge downgraded the risk level of this issue
edited-by-warden
grade-b
Q-06
QA (Quality Assurance)
Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax
sponsor confirmed
Sponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity")
sufficient quality report
This report is of sufficient quality
Lines of code
https://github.com/code-423n4/2023-11-zetachain/blob/b237708ed5e86f12c4bddabddfd42f001e81941a/repos/node/x/crosschain/keeper/gas_payment.go#L151
https://github.com/code-423n4/2023-11-zetachain/blob/b237708ed5e86f12c4bddabddfd42f001e81941a/repos/node/x/crosschain/keeper/gas_payment.go#L106
https://github.com/code-423n4/2023-11-zetachain/blob/b237708ed5e86f12c4bddabddfd42f001e81941a/repos/node/x/crosschain/keeper/gas_payment.go#L285
Vulnerability details
Impact
Median gas price is inconsistently handled in gas_payment.go. For the same external chain, a sender will be charged twice as much median gas price if cointType is zeta, while a sender will be charged the exact median gas price if cointType is native gas coin or ERC20.
Proof of Concept
In gas_payment.go, outboundtx gas payment is calculated based on gasLimit and gas price. gas price is based on median gas price of the external chain. However, gas price is inconsistenly handled between different coinTypes.
When coinType is zetacoin, the gas price is fetched in
PayGasInZetaAndUpdateCctx()
. It getsgasPrice
forchainID
throughk.GetMedianGasPriceInUint()
. The resultinggasPrice
is then doubled throughgasPrice = gasPrice.MulUint64(2)
. ThisgasPrice
is then used to calculate actual gas token balance to charge.However, when coinType is ERC20 token or native gas token,
gasPrice
forchainId
is fetched throughk.ChainGasParams(ctx, chainID)
, which under the hood calls the sameGetMedianGasPriceInUint()
that directly returnsgasPrice
. However,gasPrice
is then directly used to be multiplied bygasLimit
without doubling the price as in zetacoin flow. For the same chainId,gasPrice
is inconsistently priced. This results in gas to be underpaid when the crosschain tx coinType is ERC20 token or native gas token.(https://github.com/code-423n4/2023-11-zetachain/blob/b237708ed5e86f12c4bddabddfd42f001e81941a/repos/node/x/crosschain/keeper/gas_payment.go#L285)
(https://github.com/code-423n4/2023-11-zetachain/blob/b237708ed5e86f12c4bddabddfd42f001e81941a/repos/node/x/crosschain/keeper/gas_payment.go#L147)
(https://github.com/code-423n4/2023-11-zetachain/blob/b237708ed5e86f12c4bddabddfd42f001e81941a/repos/node/x/crosschain/keeper/gas_payment.go#L75)
Same median gas price is fetched for target chainId, however, only when the cctx coinType is zeta coin, the fetched price will be doubled. When the coinType is erc20 or gas native token, gas will be underpaid.
Tools Used
Manual review
Recommended Mitigation Steps
Consider unifying the
gasPrice
handling between three different coin types.Assessed type
Error
The text was updated successfully, but these errors were encountered: