Skip to content

Commit 44a0515

Browse files
committed
check gas before access db
1 parent a1873c6 commit 44a0515

File tree

7 files changed

+75
-0
lines changed

7 files changed

+75
-0
lines changed

crates/interpreter/src/host.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@ pub trait Host {
4848
/// Get code hash of `address` and if the account is cold.
4949
fn code_hash(&mut self, address: Address) -> Option<StateLoad<B256>>;
5050

51+
/// Check a storage slot is code or not without change the access status.
52+
///
53+
/// # Panics
54+
///
55+
/// Panics if the account is not present in the state.
56+
fn is_storage_cold(&self, address: Address, key: U256) -> bool;
57+
5158
#[cfg(feature = "scroll")]
5259
/// Get code size of `address` and if the account is cold.
5360
fn code_size(&mut self, address: Address) -> Option<StateLoad<usize>>;

crates/interpreter/src/host/dummy.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ impl Host for DummyHost {
7575
Some(StateLoad::new(0, false))
7676
}
7777

78+
#[inline]
79+
fn is_storage_cold(&self, _address: Address, key: U256) -> bool {
80+
self.storage.contains_key(&key)
81+
}
82+
7883
#[inline]
7984
fn sload(&mut self, _address: Address, index: U256) -> Option<StateLoad<U256>> {
8085
match self.storage.entry(index) {

crates/interpreter/src/instructions/host.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,13 @@ pub fn blockhash<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, ho
176176

177177
pub fn sload<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, host: &mut H) {
178178
pop_top!(interpreter, index);
179+
min_gas!(
180+
interpreter,
181+
gas::sload_cost(
182+
SPEC::SPEC_ID,
183+
host.is_storage_cold(interpreter.contract.target_address, *index)
184+
)
185+
);
179186
let Some(value) = host.sload(interpreter.contract.target_address, *index) else {
180187
interpreter.instruction_result = InstructionResult::FatalExternalError;
181188
return;
@@ -194,6 +201,13 @@ pub fn sstore<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, host:
194201
require_non_staticcall!(interpreter);
195202

196203
pop!(interpreter, index, value);
204+
min_gas!(
205+
interpreter,
206+
gas::sload_cost(
207+
SPEC::SPEC_ID,
208+
host.is_storage_cold(interpreter.contract.target_address, *index)
209+
)
210+
);
197211
let Some(state_load) = host.sstore(interpreter.contract.target_address, index, value) else {
198212
interpreter.instruction_result = InstructionResult::FatalExternalError;
199213
return;

crates/interpreter/src/instructions/macros.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,20 @@ macro_rules! gas {
6161
};
6262
}
6363

64+
/// Check if a `gas` cost would exceed the available gas.
65+
#[macro_export]
66+
macro_rules! min_gas {
67+
($interp:expr, $gas:expr) => {
68+
$crate::min_gas!($interp, $gas, ())
69+
};
70+
($interp:expr, $gas:expr, $ret:expr) => {
71+
if $interp.gas.remaining() < $gas {
72+
$interp.instruction_result = $crate::InstructionResult::OutOfGas;
73+
return $ret;
74+
}
75+
};
76+
}
77+
6478
/// Records a `gas` refund.
6579
#[macro_export]
6680
macro_rules! refund {

crates/revm/src/context.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,15 @@ impl<EXT, DB: Database> Host for Context<EXT, DB> {
167167
.ok()
168168
}
169169

170+
/// Check a storage slot is code or not without change the access status.
171+
///
172+
/// # Panics
173+
///
174+
/// Panics if the account is not present in the state.
175+
fn is_storage_cold(&self, address: Address, key: U256) -> bool {
176+
self.evm.is_storage_cold(address, key)
177+
}
178+
170179
fn sload(&mut self, address: Address, index: U256) -> Option<StateLoad<U256>> {
171180
self.evm
172181
.sload(address, index)

crates/revm/src/context/inner_evm_context.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,16 @@ impl<DB: Database> InnerEvmContext<DB> {
253253
Ok(StateLoad::new(hash, acc.is_cold))
254254
}
255255

256+
/// Check a storage slot is code or not without change the access status.
257+
///
258+
/// # Panics
259+
///
260+
/// Panics if the account is not present in the state.
261+
#[inline]
262+
pub fn is_storage_cold(&self, address: Address, key: U256) -> bool {
263+
self.journaled_state.is_storage_cold(address, key)
264+
}
265+
256266
/// Load storage slot, if storage is not present inside the account then it will be loaded from database.
257267
#[inline]
258268
pub fn sload(

crates/revm/src/journaled_state.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,22 @@ impl JournaledState {
692692
Ok(account_load)
693693
}
694694

695+
/// Check a storage slot is code or not without change the access status.
696+
///
697+
/// # Panics
698+
///
699+
/// Panics if the account is not present in the state.
700+
#[inline]
701+
pub fn is_storage_cold(&self, address: Address, key: U256) -> bool {
702+
// assume acc is warm
703+
let account = self.state.get(&address).unwrap();
704+
account
705+
.storage
706+
.get(&key)
707+
.map(|slot| slot.is_cold)
708+
.unwrap_or(true)
709+
}
710+
695711
/// Load storage slot
696712
///
697713
/// # Panics

0 commit comments

Comments
 (0)