diff --git a/substrate/frame/contracts/rpc/src/lib.rs b/substrate/frame/contracts/rpc/src/lib.rs index e330e9efcc0e305606fef12e0bc69291c42342c2..6f357f53b855843224956ca84d435456f9509de3 100644 --- a/substrate/frame/contracts/rpc/src/lib.rs +++ b/substrate/frame/contracts/rpc/src/lib.rs @@ -39,7 +39,16 @@ const RUNTIME_ERROR: i64 = 1; const CONTRACT_DOESNT_EXIST: i64 = 2; const CONTRACT_IS_A_TOMBSTONE: i64 = 3; -// A private newtype for converting `GetStorageError` into an RPC error. +/// A rough estimate of how much gas a decent hardware consumes per second, +/// using native execution. +/// This value is used to set the upper bound for maximal contract calls to +/// prevent blocking the RPC for too long. +/// +/// Based on W3F research spreadsheet: +/// https://docs.google.com/spreadsheets/d/1h0RqncdqiWI4KgxO0z9JIpZEJESXjX_ZCK6LFX6veDo/view +const GAS_PER_SECOND: u64 = 1_000_000_000; + +/// A private newtype for converting `GetStorageError` into an RPC error. struct GetStorageError(runtime_api::GetStorageError); impl From<GetStorageError> for Error { fn from(e: GetStorageError) -> Error { @@ -148,6 +157,19 @@ where data: None, })?; + let max_gas_limit = 5 * GAS_PER_SECOND; + if gas_limit > max_gas_limit { + return Err(Error { + code: ErrorCode::InvalidParams, + message: format!( + "Requested gas limit is greater than maximum allowed: {} > {}", + gas_limit, + max_gas_limit + ), + data: None, + }); + } + let exec_result = api .call(&at, origin, dest, value, gas_limit, input_data.to_vec()) .map_err(|e| Error {