fn extract_commit_data(
        commit_tx_input_data: &[u8],
        commit_function: &ethabi::Function,
        batch_number: L1BatchNumber,
        pre_gateway: bool,
    ) -> anyhow::Result<ethabi::Token> {
        let expected_solidity_selector = commit_function.short_signature();
        let actual_solidity_selector = &commit_tx_input_data[..4];
        anyhow::ensure!(
            expected_solidity_selector == actual_solidity_selector,
            "unexpected Solidity function selector: expected {expected_solidity_selector:?}, got {actual_solidity_selector:?}"
        );

        let mut commit_input_tokens = commit_function
            .decode_input(&commit_tx_input_data[4..])
            .context("Failed decoding calldata for L1 commit function")?;
        let mut commitments: Vec<Token>;
        if pre_gateway {
            commitments = commit_input_tokens
                .pop()
                .context("Unexpected signature for L1 commit function")?
                .into_array()
                .context("Unexpected signature for L1 commit function")?;
        } else {
            let commitments_popped = commit_input_tokens
                .pop()
                .context("Unexpected signature for L1 commit function: no tokens")?;
            let commitment_bytes = match commitments_popped {
                Token::Bytes(arr) => arr,
                _ => anyhow::bail!(
                    "Unexpected signature for L1 commit function: last token is not bytes"
                ),
            };
            let (version, encoded_data) = commitment_bytes.split_at(1);
            anyhow::ensure!(
                version[0] == SUPPORTED_ENCODING_VERSION,
                "Unexpected encoding version: {}",
                version[0]
            );
            let decoded_data = ethabi::decode(
                &[
                    StoredBatchInfo::schema(),
                    ParamType::Array(Box::new(CommitBatchInfo::post_gateway_schema())),
                ],
                encoded_data,
            )
            .context("Failed to decode commitData")?;
            if let Some(Token::Array(batch_commitments)) = &decoded_data.get(1) {
                // Now you have access to `stored_batch_info` and `l1_batches_to_commit`
                // Process them as needed
                commitments = batch_commitments.clone();
            } else {
                anyhow::bail!("Unexpected data format");
            }
        }

        // Commit transactions usually publish multiple commitments at once, so we need to find
        // the one that corresponds to the batch we're checking.
        let first_batch_commitment = commitments
            .first()
            .context("L1 batch commitment is empty")?;
        let ethabi::Token::Tuple(first_batch_commitment) = first_batch_commitment else {
            anyhow::bail!("Unexpected signature for L1 commit function 3");
        };
        let first_batch_number = first_batch_commitment
            .first()
            .context("Unexpected signature for L1 commit function 4")?;
        let first_batch_number = first_batch_number
            .clone()
            .into_uint()
            .context("Unexpected signature for L1 commit function  5")?;
        let first_batch_number = usize::try_from(first_batch_number)
            .map_err(|_| anyhow::anyhow!("Integer overflow for L1 batch number"))?;
        // ^ `TryFrom` has `&str` error here, so we can't use `.context()`.

        let commitment = (batch_number.0 as usize)
            .checked_sub(first_batch_number)
            .and_then(|offset| {
                (offset < commitments.len()).then(|| commitments.swap_remove(offset))
            });
        commitment.with_context(|| {
            let actual_range = first_batch_number..(first_batch_number + commitments.len());
            format!(
                "Malformed commitment data; it should commit to L1 batch #{batch_number}, \
                 but it actually commits to batches #{actual_range:?}"
            )
        })
    }
All returned errors are validation errors.
core/node/consistency_checker/src/lib.rs