From e5ebc1ec089c6f32773d61f0705bde063c842c47 Mon Sep 17 00:00:00 2001
From: Yonatan-Starkware <yonatan.k@starkware.co>
Date: Tue, 19 Nov 2024 18:46:58 +0200
Subject: [PATCH] feat(blockifier): add get_syscall_gas_cost to versioned
 constants impl

---
 crates/blockifier/src/versioned_constants.rs  | 30 +++++++++++++++++++
 .../src/versioned_constants_test.rs           | 22 ++++++++++++++
 2 files changed, 52 insertions(+)

diff --git a/crates/blockifier/src/versioned_constants.rs b/crates/blockifier/src/versioned_constants.rs
index 6d18bca5e8..0ce942652a 100644
--- a/crates/blockifier/src/versioned_constants.rs
+++ b/crates/blockifier/src/versioned_constants.rs
@@ -26,6 +26,7 @@ use crate::execution::execution_utils::poseidon_hash_many_cost;
 use crate::execution::syscalls::SyscallSelector;
 use crate::fee::resources::StarknetResources;
 use crate::transaction::transaction_types::TransactionType;
+use crate::utils::u64_from_usize;
 
 #[cfg(test)]
 #[path = "versioned_constants_test.rs"]
@@ -347,6 +348,35 @@ impl VersionedConstants {
             GasVectorComputationMode::NoL2Gas => &self.deprecated_l2_resource_gas_costs,
         }
     }
+
+    /// Calculates the syscall gas cost from the OS resources.
+    pub fn get_syscall_gas_cost(&self, syscall_selector: &SyscallSelector) -> u64 {
+        let gas_costs = &self.os_constants.gas_costs;
+        let execution_resources = &self
+            .os_resources
+            .execute_syscalls
+            .get(syscall_selector)
+            .expect("Fetching the execution resources of a syscall should not fail.");
+        let n_steps = u64_from_usize(execution_resources.n_steps);
+        let n_memory_holes = u64_from_usize(execution_resources.n_memory_holes);
+        let total_builtin_gas_cost: u64 = execution_resources
+            .builtin_instance_counter
+            .iter()
+            .map(|(builtin, amount)| {
+                let builtin_cost = gas_costs
+                    .get_builtin_gas_cost(builtin)
+                    .unwrap_or_else(|err| panic!("Failed to get gas cost: {}", err));
+                builtin_cost * u64_from_usize(*amount)
+            })
+            .sum();
+        // The minimum total cost is `syscall_base_gas_cost`, which is pre-charged by the compiler.
+        std::cmp::max(
+            n_steps * gas_costs.step_gas_cost
+                + n_memory_holes * gas_costs.memory_hole_gas_cost
+                + total_builtin_gas_cost,
+            gas_costs.syscall_base_gas_cost,
+        )
+    }
 }
 
 #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq)]
diff --git a/crates/blockifier/src/versioned_constants_test.rs b/crates/blockifier/src/versioned_constants_test.rs
index 7947afc52a..4f281f71af 100644
--- a/crates/blockifier/src/versioned_constants_test.rs
+++ b/crates/blockifier/src/versioned_constants_test.rs
@@ -167,3 +167,25 @@ fn test_all_jsons_in_enum() {
 fn test_latest_no_panic() {
     VersionedConstants::latest_constants();
 }
+
+#[test]
+fn test_syscall_gas_cost_calculation() {
+    const EXPECTED_CALL_CONTRACT_GAS_COST: u64 = 87650;
+    const EXPECTED_SECP256K1MUL_GAS_COST: u64 = 8143650;
+    const EXPECTED_SHA256PROCESSBLOCK_GAS_COST: u64 = 841095;
+
+    let versioned_constants = VersionedConstants::latest_constants().clone();
+
+    assert_eq!(
+        versioned_constants.get_syscall_gas_cost(&SyscallSelector::CallContract),
+        EXPECTED_CALL_CONTRACT_GAS_COST
+    );
+    assert_eq!(
+        versioned_constants.get_syscall_gas_cost(&SyscallSelector::Secp256k1Mul),
+        EXPECTED_SECP256K1MUL_GAS_COST
+    );
+    assert_eq!(
+        versioned_constants.get_syscall_gas_cost(&SyscallSelector::Sha256ProcessBlock),
+        EXPECTED_SHA256PROCESSBLOCK_GAS_COST
+    );
+}