sherlock-audit / 2024-08-tokamak-network-judging

1 stars 0 forks source link

jsmi - `L11CrossDomainMessenger::sendMessage()` doesn't check `_minGasLimit`. #74

Open sherlock-admin4 opened 1 month ago

sherlock-admin4 commented 1 month ago

jsmi

Medium

L11CrossDomainMessenger::sendMessage() doesn't check _minGasLimit.

Summary

Users can set _minGasLimit arbitrarily high and sendMessage() doesn't check it's validity.

Vulnerability Detail

Calling sendMessage(), users have to prepay gas fee for the transaction of the other chain. Users can set _minGasLimit arbitrarily high and sendMessage() doesn't check it's validity. So users set _minGasLimit arbitrarily high while they don't pay for it by ETH or native token.

The relavant code of CrossDomainMessenger::sendMessage() is the following.

    function sendMessage(address _target, bytes calldata _message, uint32 _minGasLimit) external payable {
        // Triggers a message to the other messenger. Note that the amount of gas provided to the
        // message is the amount of gas requested by the user PLUS the base gas value. We want to
        // guarantee the property that the call to the target contract will always have at least
        // the minimum gas limit specified by the user.
        _sendMessage({
            _to: address(otherMessenger),
            _gasLimit: baseGas(_message, _minGasLimit),
            _value: msg.value,
            _data: abi.encodeWithSelector(
                this.relayMessage.selector, messageNonce(), msg.sender, _target, msg.value, _minGasLimit, _message
            )
        });

        emit SentMessage(_target, msg.sender, _message, messageNonce(), _minGasLimit);
        emit SentMessageExtension1(msg.sender, msg.value);

        unchecked {
            ++msgNonce;
        }
    }

As shown above, the function doesn't check _minGasLimit against msg.value and also doesn't transfer native tokens of _minGasLimit to the contract. Therefore, the user can set _minGasLimit arbitrarily high while they don't pay for it at all.

POC:

  1. User calls CrossDomainMessenger::sendMessage() while set _minGasLimit arbitrarily high for heavy transaction on other chain. But user doesn't pay for it by ETH or native token at the same time.
  2. The protocol doesn't check _minGasLimit. And op node will relay the transaction to the other chain while pay gas fee by itself.

Impact

User can call sendMessage() on L2 and executes the transaction on L1 without paying any gas fee. In ethereum(L1), the gas fee is very expensive. So it causes the protocol to lose much funds. Loss of funds for the protocol.

Code Snippet

Tool used

Manual Review

Recommendation

It is recommended to check the validity of _minGasLimit.