Function `l2TransactionBaseCost`  in `Mailbox.sol` Lacks Range Checks for Parameters and Validation in Process Logic, Leading to Unreasonable Cost Calculation Results
Audit: 2024-03-zksync-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-03-zksync/blob/0ac7f015e6d091eba444fe6e490a85e3ee4faf79/code/contracts/ethereum/contracts/state-transition/chain-deps/facets/Mailbox.sol#L143-L175


# Vulnerability details

The function `l2TransactionBaseCost` in `Mailbox.sol` is responsible for calculating the L2 Transaction Base Cost. The parameters `_gasPrice`, `_l2GasLimit`, and `_l2GasPerPubdataByteLimit` lack any value range checks, leading to occasionally large calculation results.

Moreover, there are issues with the test code for this function, and the correctness of its internal logic needs verification.

## Impact
- Incorrect calculation of L2 Transaction Base Cost, affecting all related L2 fees.
- The possibility of extreme values for the L2 Transaction Base Cost, impacting the entire zkSync era.

## Proof of Concept

1. The function `l2TransactionBaseCost` and the function `_deriveL2GasPrice` it calls do not perform any validation on external input parameters.
https://github.com/code-423n4/2024-03-zksync/blob/0ac7f015e6d091eba444fe6e490a85e3ee4faf79/code/contracts/ethereum/contracts/state-transition/chain-deps/facets/Mailbox.sol#L143-L175

```solidity
    function l2TransactionBaseCost(
        uint256 _gasPrice,
        uint256 _l2GasLimit,
        uint256 _l2GasPerPubdataByteLimit
    ) public view returns (uint256) {
        uint256 l2GasPrice = _deriveL2GasPrice(_gasPrice, _l2GasPerPubdataByteLimit);
        return l2GasPrice * _l2GasLimit;
    }

    /// @notice Derives the price for L2 gas in ETH to be paid.
    /// @param _l1GasPrice The gas price on L1
    /// @param _gasPerPubdata The price for each pubdata byte in L2 gas
    /// @return The price of L2 gas in ETH
    function _deriveL2GasPrice(uint256 _l1GasPrice, uint256 _gasPerPubdata) internal view returns (uint256) {
        FeeParams memory feeParams = s.feeParams;
        require(s.baseTokenGasPriceMultiplierDenominator > 0, "Mailbox: baseTokenGasPriceDenominator not set");
        uint256 l1GasPriceConverted = (_l1GasPrice * s.baseTokenGasPriceMultiplierNominator) /
            s.baseTokenGasPriceMultiplierDenominator;
        uint256 pubdataPriceBaseToken;
        if (feeParams.pubdataPricingMode == PubdataPricingMode.Rollup) {
            pubdataPriceBaseToken = L1_GAS_PER_PUBDATA_BYTE * l1GasPriceConverted;
        }

        uint256 batchOverheadBaseToken = uint256(feeParams.batchOverheadL1Gas) * l1GasPriceConverted;
        uint256 fullPubdataPriceBaseToken = pubdataPriceBaseToken +
            batchOverheadBaseToken /
            uint256(feeParams.maxPubdataPerBatch);

        uint256 l2GasPrice = feeParams.minimalL2GasPrice + batchOverheadBaseToken / uint256(feeParams.maxL2GasPerBatch);
        uint256 minL2GasPriceBaseToken = (fullPubdataPriceBaseToken + _gasPerPubdata - 1) / _gasPerPubdata;

        return Math.max(l2GasPrice, minL2GasPriceBaseToken);
    }
```
2. The function `test_l2TransactionBaseCost` in the test code `experimental_bridge.t.sol` is use