L1 TO L2 ERC20 TOKEN TRANSFER CAN BE DoS IN THE `FxERC20ChildTunnel` CONTRACT SINCE A MALICIOUS USER CAN SET THE `fxRootTunnel` ADDRESS TO AN INVALID ADDRESS
Audit: 2023-12-autonolas-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-12-autonolas/blob/main/governance/contracts/bridges/FxERC20ChildTunnel.sol#L70-L74
https://github.com/code-423n4/2023-12-autonolas/blob/main/governance/contracts/bridges/FxERC20RootTunnel.sol#L72-L80


# Vulnerability details

## Impact

The `FxERC20ChildTunnel` is a smart contract which is used for the L2 token management. The `FxERC20ChildTunnel` contract inherits from the `FxBaseChildTunnel` contract. The `FxBaseChildTunnel` contract has the `validateSender` modifier which requires the `sender` of the function which the modifier is used in, to match the `fxRootTunnel` address. The `fxRootTunnel` address is set in an external function as shown below:

    function setFxRootTunnel(address _fxRootTunnel) external virtual {
        require(fxRootTunnel == address(0x0), "FxBaseChildTunnel: ROOT_TUNNEL_ALREADY_SET");
        fxRootTunnel = _fxRootTunnel;
    }

The `FxERC20ChildTunnel._processMessageFromRoot` function uses the `validateSender` modifier as shown below:

    function _processMessageFromRoot(
        uint256 /* stateId */,
        address sender, //@audit-info - sender here is the rootMessageSender address
        bytes memory message //@audit-info - message is the encoded message from the root
    ) internal override validateSender(sender) {

Hence to process the token message from L1 the `sender` address should be validated to be equal to the `fxRootTunnel` address. But the issue here is that the `setFxRootTunnel` is not called in the `FxERC20ChildTunnel.constructor` function. Hence as a result the `setFxRootTunnel` function should be called externally to set the `fxRootTunnel` address. As a result a malicious user can front-run the `setFxRootTunnel` transaction and set an invalid `fxRootTunnel` address.

This will prompt the `validateSender` modifier to always revert. As a result the L2 `FxERC20ChildTunnel` contract will not be able to process the `token message from L1` since the transaction will revert. Furthermore the `fxRootTunnel` will not be able to be updated after it has been set at least once. This is because of the `fxRootTunnel == address(0x0)` check performed in the `setFxRootTunnel` function as shown below:

    function setFxRootTunnel(address _fxRootTunnel) external virtual {
        require(fxRootTunnel == address(0x0), "FxBaseChildTunnel: ROOT_TUNNEL_ALREADY_SET");
        fxRootTunnel = _fxRootTunnel;
    }

As a result this will prompt the L1-L2 ERC20 token transfer transactions to fail if a malicious user front-runs the `setFxRootTunnel` transactoin and sets up an invalid address as the `fxRootTunnel`.

The same issue is evident in the `FxERC20RootTunnel._processMessageFromChild` function. The `_processMessageFromChild` function is called by the `FxBaseRootTunnel.receiveMessage` function. The `FxERC20RootTunnel` implements the `FxBaseRootTunnel` abstract contract. The `_validateAndExtractMessage` function call ensures that the `emitter of the child tunnel ERC20