diff --git a/radix-engine/src/vm/wasm_runtime/scrypto_runtime.rs b/radix-engine/src/vm/wasm_runtime/scrypto_runtime.rs index af4d953a47..d1d268038e 100644 --- a/radix-engine/src/vm/wasm_runtime/scrypto_runtime.rs +++ b/radix-engine/src/vm/wasm_runtime/scrypto_runtime.rs @@ -1,3 +1,5 @@ +use core::u32; + use crate::errors::InvokeError; use crate::errors::RuntimeError; use crate::internal_prelude::*; @@ -21,6 +23,7 @@ pub struct ScryptoRuntime<'y, Y: SystemApi> { export_name: String, wasm_execution_units_buffer: u32, scrypto_vm_version: ScryptoVmVersion, + wasm_execution_units_base: u32, } impl<'y, Y: SystemApi> ScryptoRuntime<'y, Y> { @@ -30,6 +33,18 @@ impl<'y, Y: SystemApi> ScryptoRuntime<'y, Y> { export_name: String, scrypto_vm_version: ScryptoVmVersion, ) -> Self { + let wasm_execution_units_base = if scrypto_vm_version < ScryptoVmVersion::cuttlefish() { + 0 + } else { + // Add 6,000 base units to make sure the we do not undercharge for WASM execution, + // which might lead to system exploitation. + // This is especially important in corner-cases such as `costing::spin_loop_v2` benchmark. + // Use larger cost unit buffer to call `consume_wasm_execution_exceeding_buffer` + // less frequently. + // 6000 + 6000 + }; + ScryptoRuntime { api, buffers: index_map_new(), @@ -38,6 +53,7 @@ impl<'y, Y: SystemApi> ScryptoRuntime<'y, Y> { export_name, wasm_execution_units_buffer: 0, scrypto_vm_version, + wasm_execution_units_base, } } @@ -401,6 +417,10 @@ impl<'y, Y: SystemApi> WasmRuntime for ScryptoRuntime<'y, Y> { &mut self, n: u32, ) -> Result<(), InvokeError> { + let n = n + .checked_add(self.wasm_execution_units_base) + .unwrap_or(u32::MAX); + if n <= self.wasm_execution_units_buffer { self.wasm_execution_units_buffer -= n; Ok(())