Skip to content

Commit f5f7fcc

Browse files
authored
feat: impl tx for transactionrequest (#75)
* feat: impl tx for transactionrequest * feat: block overrides * feat: apply block and state overrides * chore: bump version
1 parent 7b63461 commit f5f7fcc

File tree

3 files changed

+146
-2
lines changed

3 files changed

+146
-2
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "trevm"
3-
version = "0.19.0"
3+
version = "0.19.1"
44
rust-version = "1.83.0"
55
edition = "2021"
66
authors = ["init4"]

src/evm.rs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ use crate::{
44
EvmNeedsCfg, EvmNeedsTx, EvmReady, EvmTransacted, HasBlock, HasCfg, HasTx, NeedsCfg, NeedsTx,
55
TransactedState, Tx,
66
};
7-
use alloy::primitives::{Address, Bytes, U256};
7+
use alloy::{
8+
primitives::{Address, Bytes, U256},
9+
rpc::types::{state::StateOverride, BlockOverrides},
10+
};
811
use core::convert::Infallible;
912
use revm::{
1013
db::{states::bundle_state::BundleRetention, BundleState, State},
@@ -137,6 +140,42 @@ impl<'a, Ext, Db: Database + DatabaseCommit, TrevmState> Trevm<'a, Ext, Db, Trev
137140
None => Ok(None),
138141
}
139142
}
143+
144+
/// Apply [`StateOverride`]s to the current state.
145+
pub fn apply_state_overrides(
146+
mut self,
147+
overrides: &StateOverride,
148+
) -> Result<Self, EVMError<Db::Error>> {
149+
for (address, account_override) in overrides {
150+
if let Some(balance) = account_override.balance {
151+
self.inner.set_balance(*address, balance).map_err(EVMError::Database)?;
152+
}
153+
if let Some(nonce) = account_override.nonce {
154+
self.inner.set_nonce(*address, nonce).map_err(EVMError::Database)?;
155+
}
156+
if let Some(code) = account_override.code.as_ref() {
157+
self.inner
158+
.set_bytecode(
159+
*address,
160+
Bytecode::new_raw_checked(code.clone())
161+
.map_err(|_| EVMError::Custom("Invalid bytecode".to_string()))?,
162+
)
163+
.map_err(EVMError::Database)?;
164+
}
165+
if let Some(state) = account_override.state.as_ref() {
166+
for (slot, value) in state {
167+
self.inner
168+
.set_storage(
169+
*address,
170+
U256::from_be_bytes((*slot).into()),
171+
U256::from_be_bytes((*value).into()),
172+
)
173+
.map_err(EVMError::Database)?;
174+
}
175+
}
176+
}
177+
Ok(self)
178+
}
140179
}
141180

142181
impl<Ext, Db: Database + DatabaseCommit + DatabaseRef, TrevmState> Trevm<'_, Ext, Db, TrevmState> {
@@ -981,6 +1020,21 @@ impl<'a, Ext, Db: Database + DatabaseCommit, TrevmState: HasTx> Trevm<'a, Ext, D
9811020
}
9821021
}
9831022

1023+
// -- HAS TX with State<Db>
1024+
1025+
impl<Ext, Db: Database> EvmNeedsTx<'_, Ext, State<Db>> {
1026+
/// Apply block overrides to the current block.
1027+
pub fn apply_block_overrides(mut self, overrides: BlockOverrides) -> Self {
1028+
overrides.fill_block(&mut self.inner);
1029+
1030+
if let Some(hashes) = overrides.block_hash {
1031+
self.inner.db_mut().block_hashes.extend(hashes)
1032+
}
1033+
1034+
self
1035+
}
1036+
}
1037+
9841038
// --- READY
9851039

9861040
impl<'a, Ext, Db: Database + DatabaseCommit> EvmReady<'a, Ext, Db> {

src/fill/alloy.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,96 @@ impl<T: Send + Sync> Block for alloy::rpc::types::eth::Block<T> {
284284
}
285285
}
286286

287+
impl Tx for alloy::rpc::types::TransactionRequest {
288+
fn fill_tx_env(&self, tx_env: &mut TxEnv) {
289+
let TxEnv {
290+
caller,
291+
gas_limit,
292+
gas_price,
293+
transact_to,
294+
value,
295+
data,
296+
nonce,
297+
chain_id,
298+
access_list,
299+
gas_priority_fee,
300+
blob_hashes,
301+
max_fee_per_blob_gas,
302+
authorization_list,
303+
} = tx_env;
304+
305+
*caller = self.from.unwrap_or_default();
306+
*gas_limit = self.gas.unwrap_or_default();
307+
*gas_price = U256::from(self.gas_price.unwrap_or_default());
308+
*transact_to = self.to.unwrap_or_default();
309+
*value = self.value.unwrap_or_default();
310+
*data = self.input.input().cloned().unwrap_or_default();
311+
*nonce = self.nonce;
312+
*chain_id = self.chain_id;
313+
if let Some(al) = &self.access_list {
314+
access_list.clone_from(al);
315+
} else {
316+
access_list.clear();
317+
}
318+
if let Some(gpf) = &self.max_priority_fee_per_gas {
319+
*gas_priority_fee = Some(U256::from(*gpf));
320+
} else {
321+
gas_priority_fee.take();
322+
}
323+
if let Some(bh) = &self.blob_versioned_hashes {
324+
blob_hashes.clone_from(bh);
325+
} else {
326+
blob_hashes.clear();
327+
}
328+
if let Some(mfbg) = &self.max_fee_per_blob_gas {
329+
*max_fee_per_blob_gas = Some(U256::from(*mfbg));
330+
} else {
331+
max_fee_per_blob_gas.take();
332+
}
333+
if let Some(al) = &self.authorization_list {
334+
*authorization_list = Some(al.clone().into());
335+
} else {
336+
authorization_list.take();
337+
}
338+
}
339+
}
340+
341+
impl Block for alloy::rpc::types::BlockOverrides {
342+
fn fill_block_env(&self, block_env: &mut BlockEnv) {
343+
let BlockEnv {
344+
number,
345+
coinbase,
346+
timestamp,
347+
gas_limit,
348+
basefee,
349+
difficulty,
350+
prevrandao,
351+
blob_excess_gas_and_price: _,
352+
} = block_env;
353+
if let Some(n) = &self.number {
354+
*number = U256::from(*n);
355+
}
356+
if let Some(d) = &self.difficulty {
357+
*difficulty = U256::from(*d);
358+
}
359+
if let Some(t) = &self.time {
360+
*timestamp = U256::from(*t);
361+
}
362+
if let Some(g) = &self.gas_limit {
363+
*gas_limit = U256::from(*g);
364+
}
365+
if let Some(c) = &self.coinbase {
366+
*coinbase = *c;
367+
}
368+
if let Some(r) = self.random {
369+
*prevrandao = Some(r);
370+
}
371+
if let Some(b) = &self.base_fee {
372+
*basefee = U256::from(*b);
373+
}
374+
}
375+
}
376+
287377
#[cfg(test)]
288378
mod tests {
289379
use crate::{NoopBlock, NoopCfg, TrevmBuilder};

0 commit comments

Comments
 (0)