<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def binary_gas_search(state: BaseState, transaction: BaseTransaction, tolerance: int=1) -> int: """ Run the transaction with various gas limits, progressively approaching the minimum needed to succeed without an OutOfGas exception. The starting range of possible estimates is: [transaction.intrinsic_gas, state.gas_limit]. After the first OutOfGas exception, the range is: (largest_limit_out_of_gas, state.gas_limit]. After the first run not out of gas, the range is: (largest_limit_out_of_gas, smallest_success]. :param int tolerance: When the range of estimates is less than tolerance, return the top of the range. :returns int: The smallest confirmed gas to not throw an OutOfGas exception, subject to tolerance. If OutOfGas is thrown at block limit, return block limit. :raises VMError: if the computation fails even when given the block gas_limit to complete """

    if not hasattr(transaction, 'sender'):
        raise TypeError(
            "Transaction is missing attribute sender.",
            "If sending an unsigned transaction, use SpoofTransaction and provide the",
            "sender using the 'from' parameter")

    minimum_transaction = SpoofTransaction(
        transaction,
        gas=transaction.intrinsic_gas,
        gas_price=0,
    )

    if _get_computation_error(state, minimum_transaction) is None:
        return transaction.intrinsic_gas

    maximum_transaction = SpoofTransaction(
        transaction,
        gas=state.gas_limit,
        gas_price=0,
    )
    error = _get_computation_error(state, maximum_transaction)
    if error is not None:
        raise error

    minimum_viable = state.gas_limit
    maximum_out_of_gas = transaction.intrinsic_gas
    while minimum_viable - maximum_out_of_gas > tolerance:
        midpoint = (minimum_viable + maximum_out_of_gas) // 2
        test_transaction = SpoofTransaction(transaction, gas=midpoint)
        if _get_computation_error(state, test_transaction) is None:
            minimum_viable = midpoint
        else:
            maximum_out_of_gas = midpoint

    return minimum_viable