diff --git a/crates/blockifier/src/execution/native/syscall_handler.rs b/crates/blockifier/src/execution/native/syscall_handler.rs
index d0cabe9c10..21943382ee 100644
--- a/crates/blockifier/src/execution/native/syscall_handler.rs
+++ b/crates/blockifier/src/execution/native/syscall_handler.rs
@@ -452,47 +452,13 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> {
     fn keccak(&mut self, input: &[u64], remaining_gas: &mut u64) -> SyscallResult<U256> {
         self.pre_execute_syscall(remaining_gas, self.gas_costs().keccak_gas_cost)?;
 
-        const KECCAK_FULL_RATE_IN_WORDS: usize = 17;
-
-        let input_length = input.len();
-        let (n_rounds, remainder) = num_integer::div_rem(input_length, KECCAK_FULL_RATE_IN_WORDS);
-
-        if remainder != 0 {
-            return Err(self.handle_error(
-                remaining_gas,
-                SyscallExecutionError::SyscallError {
-                    error_data: vec![Felt::from_hex(INVALID_INPUT_LENGTH_ERROR).unwrap()],
-                },
-            ));
-        }
-
-        // TODO(Ori, 1/2/2024): Write an indicative expect message explaining why the conversion
-        // works.
-        let n_rounds = u64::try_from(n_rounds).expect("Failed to convert usize to u64.");
-        let gas_cost = n_rounds * self.gas_costs().keccak_round_cost_gas_cost;
-
-        if gas_cost > *remaining_gas {
-            return Err(self.handle_error(
-                remaining_gas,
-                SyscallExecutionError::SyscallError {
-                    error_data: vec![Felt::from_hex(OUT_OF_GAS_ERROR).unwrap()],
-                },
-            ));
-        }
-        *remaining_gas -= gas_cost;
-
-        let mut state = [0u64; 25];
-        for chunk in input.chunks(KECCAK_FULL_RATE_IN_WORDS) {
-            for (i, val) in chunk.iter().enumerate() {
-                state[i] ^= val;
-            }
-            keccak::f1600(&mut state)
+        match self.base.keccak(input, remaining_gas) {
+            Ok((state, _n_rounds)) => Ok(U256 {
+                hi: u128::from(state[2]) | (u128::from(state[3]) << 64),
+                lo: u128::from(state[0]) | (u128::from(state[1]) << 64),
+            }),
+            Err(err) => Err(self.handle_error(remaining_gas, err)),
         }
-
-        Ok(U256 {
-            hi: u128::from(state[2]) | (u128::from(state[3]) << 64),
-            lo: u128::from(state[0]) | (u128::from(state[1]) << 64),
-        })
     }
 
     fn secp256k1_new(
diff --git a/crates/blockifier/src/execution/syscalls/mod.rs b/crates/blockifier/src/execution/syscalls/mod.rs
index d902bcbfd6..b1d6b0be39 100644
--- a/crates/blockifier/src/execution/syscalls/mod.rs
+++ b/crates/blockifier/src/execution/syscalls/mod.rs
@@ -30,7 +30,6 @@ use crate::execution::execution_utils::{
     write_maybe_relocatable,
     ReadOnlySegment,
 };
-use crate::execution::syscalls::hint_processor::{INVALID_INPUT_LENGTH_ERROR, OUT_OF_GAS_ERROR};
 use crate::execution::syscalls::syscall_base::SyscallResult;
 use crate::versioned_constants::{EventLimits, VersionedConstants};
 
@@ -613,45 +612,23 @@ pub fn keccak(
 ) -> SyscallResult<KeccakResponse> {
     let input_length = (request.input_end - request.input_start)?;
 
-    const KECCAK_FULL_RATE_IN_WORDS: usize = 17;
-    let (n_rounds, remainder) = num_integer::div_rem(input_length, KECCAK_FULL_RATE_IN_WORDS);
-
-    if remainder != 0 {
-        return Err(SyscallExecutionError::SyscallError {
-            error_data: vec![
-                Felt::from_hex(INVALID_INPUT_LENGTH_ERROR).map_err(SyscallExecutionError::from)?,
-            ],
-        });
-    }
-
-    // TODO(Ori, 1/2/2024): Write an indicative expect message explaining why the conversion works.
-    let n_rounds_as_u64 = u64::try_from(n_rounds).expect("Failed to convert usize to u64.");
-    let gas_cost = n_rounds_as_u64 * syscall_handler.gas_costs().keccak_round_cost_gas_cost;
-    if gas_cost > *remaining_gas {
-        let out_of_gas_error =
-            Felt::from_hex(OUT_OF_GAS_ERROR).map_err(SyscallExecutionError::from)?;
+    let data = vm.get_integer_range(request.input_start, input_length)?;
+    let data_u64: &[u64] = &data
+        .iter()
+        .map(|felt| {
+            felt.to_u64().ok_or_else(|| SyscallExecutionError::InvalidSyscallInput {
+                input: **felt,
+                info: "Invalid input for the keccak syscall.".to_string(),
+            })
+        })
+        .collect::<Result<Vec<u64>, _>>()?;
 
-        return Err(SyscallExecutionError::SyscallError { error_data: vec![out_of_gas_error] });
-    }
-    *remaining_gas -= gas_cost;
+    let (state, n_rounds) = syscall_handler.base.keccak(data_u64, remaining_gas)?;
 
     // For the keccak system call we want to count the number of rounds rather than the number of
     // syscall invocations.
     syscall_handler.increment_syscall_count_by(&SyscallSelector::Keccak, n_rounds);
 
-    let data = vm.get_integer_range(request.input_start, input_length)?;
-
-    let mut state = [0u64; 25];
-    for chunk in data.chunks(KECCAK_FULL_RATE_IN_WORDS) {
-        for (i, val) in chunk.iter().enumerate() {
-            state[i] ^= val.to_u64().ok_or_else(|| SyscallExecutionError::InvalidSyscallInput {
-                input: **val,
-                info: String::from("Invalid input for the keccak syscall."),
-            })?;
-        }
-        keccak::f1600(&mut state)
-    }
-
     Ok(KeccakResponse {
         result_low: (Felt::from(state[1]) * Felt::TWO.pow(64_u128)) + Felt::from(state[0]),
         result_high: (Felt::from(state[3]) * Felt::TWO.pow(64_u128)) + Felt::from(state[2]),
diff --git a/crates/blockifier/src/execution/syscalls/syscall_base.rs b/crates/blockifier/src/execution/syscalls/syscall_base.rs
index 5ca3fa8675..99da673ea9 100644
--- a/crates/blockifier/src/execution/syscalls/syscall_base.rs
+++ b/crates/blockifier/src/execution/syscalls/syscall_base.rs
@@ -21,11 +21,14 @@ use crate::execution::syscalls::hint_processor::{
     SyscallExecutionError,
     BLOCK_NUMBER_OUT_OF_RANGE_ERROR,
     ENTRYPOINT_FAILED_ERROR,
+    INVALID_INPUT_LENGTH_ERROR,
+    OUT_OF_GAS_ERROR,
 };
 use crate::state::state_api::State;
 use crate::transaction::account_transaction::is_cairo1;
 
 pub type SyscallResult<T> = Result<T, SyscallExecutionError>;
+pub const KECCAK_FULL_RATE_IN_WORDS: usize = 17;
 
 /// This file is for sharing common logic between Native and VM syscall implementations.
 
@@ -241,6 +244,47 @@ impl<'state> SyscallHandlerBase<'state> {
         Ok(raw_retdata)
     }
 
+    pub fn keccak(
+        &mut self,
+        input: &[u64],
+        remaining_gas: &mut u64,
+    ) -> SyscallResult<([u64; 4], usize)> {
+        let input_length = input.len();
+
+        let (n_rounds, remainder) = num_integer::div_rem(input_length, KECCAK_FULL_RATE_IN_WORDS);
+
+        if remainder != 0 {
+            return Err(SyscallExecutionError::SyscallError {
+                error_data: vec![
+                    Felt::from_hex(INVALID_INPUT_LENGTH_ERROR)
+                        .expect("Failed to parse INVALID_INPUT_LENGTH_ERROR hex string"),
+                ],
+            });
+        }
+        // TODO(Ori, 1/2/2024): Write an indicative expect message explaining why the conversion
+        // works.
+        let n_rounds_as_u64 = u64::try_from(n_rounds).expect("Failed to convert usize to u64.");
+        let gas_cost = n_rounds_as_u64 * self.context.gas_costs().keccak_round_cost_gas_cost;
+
+        if gas_cost > *remaining_gas {
+            let out_of_gas_error = Felt::from_hex(OUT_OF_GAS_ERROR)
+                .expect("Failed to parse OUT_OF_GAS_ERROR hex string");
+
+            return Err(SyscallExecutionError::SyscallError { error_data: vec![out_of_gas_error] });
+        }
+        *remaining_gas -= gas_cost;
+
+        let mut state = [0u64; 25];
+        for chunk in input.chunks(KECCAK_FULL_RATE_IN_WORDS) {
+            for (i, val) in chunk.iter().enumerate() {
+                state[i] ^= val;
+            }
+            keccak::f1600(&mut state)
+        }
+
+        Ok((state[..4].try_into().expect("Slice with incorrect length"), n_rounds))
+    }
+
     pub fn finalize(&mut self) {
         self.context
             .revert_infos