11use alloy_consensus:: Typed2718 ;
22use alloy_consensus:: constants:: KECCAK_EMPTY ;
33use alloy_consensus:: { Transaction , transaction:: SignerRecoverable } ;
4- use alloy_primitives:: { Address , B256 , Bytes , address} ;
4+ use alloy_primitives:: { Address , B256 , Bytes , U256 , address} ;
55use alloy_provider:: network:: eip2718:: Decodable2718 ;
66use alloy_provider:: { Provider , RootProvider } ;
77use alloy_rpc_types_mev:: { EthBundleHash , EthCancelBundle , EthSendBundle } ;
@@ -22,6 +22,27 @@ use crate::queue::QueuePublisher;
2222// reference: https://github.com/paradigmxyz/reth/blob/bdc59799d0651133d8b191bbad62746cb5036595/crates/optimism/txpool/src/supervisor/access_list.rs#L39
2323const CROSS_L2_INBOX_ADDRESS : Address = address ! ( "0x4200000000000000000000000000000000000022" ) ;
2424
25+ pub struct AccountInfo {
26+ pub balance : U256 ,
27+ pub nonce : u64 ,
28+ pub code_hash : B256 ,
29+ }
30+
31+ pub trait AccountInfoLookup {
32+ async fn fetch_account_info ( & self , address : Address ) -> Result < AccountInfo > ;
33+ }
34+
35+ impl AccountInfoLookup for RootProvider < Optimism > {
36+ async fn fetch_account_info ( & self , address : Address ) -> Result < AccountInfo > {
37+ let account = self . get_account ( address) . await ?;
38+ Ok ( AccountInfo {
39+ balance : account. balance ,
40+ nonce : account. nonce ,
41+ code_hash : account. code_hash ,
42+ } )
43+ }
44+ }
45+
2546#[ rpc( server, namespace = "eth" ) ]
2647pub trait IngressApi {
2748 /// `eth_sendBundle` can be used to send your bundles to the builder.
@@ -54,7 +75,7 @@ impl<Queue> IngressService<Queue> {
5475
5576 async fn validate_tx ( & self , envelope : & OpTxEnvelope ) -> Result < ( ) > {
5677 let sender = envelope. recover_signer ( ) . unwrap_or_default ( ) ;
57- let account = self . provider . get_account ( sender) . await . unwrap_or_default ( ) ;
78+ let account = self . provider . fetch_account_info ( sender) . await ? ;
5879
5980 // skip eip4844 transactions
6081 if envelope. is_eip4844 ( ) {
@@ -73,22 +94,24 @@ impl<Queue> IngressService<Queue> {
7394 }
7495 }
7596
76- // check account bytecode to see if the account is 7702 then is the tx 7702
77- if account. code_hash != KECCAK_EMPTY && envelope. is_eip7702 ( ) {
97+ // error if account is 7702 but tx is not 7702
98+ if account. code_hash != KECCAK_EMPTY && ! envelope. is_eip7702 ( ) {
7899 return Err ( anyhow:: anyhow!(
79100 "Account is a 7702 account but transaction is not EIP-7702"
80101 ) ) ;
81102 }
82103
83- // check if nonce is the latest
84- if account . nonce < envelope . nonce ( ) {
104+ // error if tx nonce is not the latest
105+ if envelope . nonce ( ) != account . nonce - 1 {
85106 return Err ( anyhow:: anyhow!( "Nonce is not the latest" ) ) ;
86107 }
87108
88- // check if execution cost <= balance
89- if account . balance < envelope. value ( ) {
109+ // error if execution cost costs more than balance
110+ if envelope. value ( ) > account . balance {
90111 return Err ( anyhow:: anyhow!( "Insufficient funds" ) ) ;
91112 }
113+
114+ // TODO: op-checks (l1 block info, l1 balance > execution + DA fee)
92115 Ok ( ( ) )
93116 }
94117}
0 commit comments