@@ -98,6 +98,8 @@ pub struct Batcher {
9898 aggregator_fee_percentage_multiplier : u128 ,
9999 aggregator_gas_cost : u128 ,
100100 latest_block_gas_price : RwLock < U256 > ,
101+ proofs_to_cover_in_min_max_fee : usize ,
102+ min_bump_percentage : U256 ,
101103 pub metrics : metrics:: BatcherMetrics ,
102104 pub telemetry : TelemetrySender ,
103105}
@@ -267,6 +269,8 @@ impl Batcher {
267269 max_proof_size : config. batcher . max_proof_size ,
268270 max_batch_byte_size : config. batcher . max_batch_byte_size ,
269271 max_batch_proof_qty : config. batcher . max_batch_proof_qty ,
272+ proofs_to_cover_in_min_max_fee : config. batcher . proofs_to_cover_in_min_max_fee ,
273+ min_bump_percentage : U256 :: from ( config. batcher . min_bump_percentage ) ,
270274 last_uploaded_batch_block : Mutex :: new ( last_uploaded_batch_block) ,
271275 pre_verification_is_enabled : config. batcher . pre_verification_is_enabled ,
272276 non_paying_config,
@@ -664,6 +668,19 @@ impl Batcher {
664668 nonced_verification_data = aux_verification_data
665669 }
666670
671+ // Before moving on to process the message, verify that the max fee covers the
672+ // minimum max fee allowed. This prevents users from spamming with very low max fees
673+ // the min max fee is enforced by checking if it can cover a batch of [`proofs_to_cover_in_min_max_fee`]
674+ let msg_max_fee = nonced_verification_data. max_fee ;
675+ if !self . msg_covers_minimum_max_fee ( msg_max_fee) . await {
676+ send_message (
677+ ws_conn_sink. clone ( ) ,
678+ SubmitProofResponseMessage :: UnderpricedProof ,
679+ )
680+ . await ;
681+ return Ok ( ( ) ) ;
682+ } ;
683+
667684 // When pre-verification is enabled, batcher will verify proofs for faster feedback with clients
668685 if self . pre_verification_is_enabled {
669686 let verification_data = & nonced_verification_data. verification_data ;
@@ -768,23 +785,6 @@ impl Batcher {
768785
769786 let mut batch_state_lock = self . batch_state . lock ( ) . await ;
770787
771- let msg_max_fee = nonced_verification_data. max_fee ;
772-
773- // Verify that the max fee is enough to cover a batch of 32 proofs at least
774- // TODO move number to config file
775- let gas_price = * self . latest_block_gas_price . read ( ) . await ;
776- let min_max_fee_per_proof =
777- aligned_sdk:: verification_layer:: compute_fee_per_proof_formula ( 32 , gas_price) ;
778- if msg_max_fee < min_max_fee_per_proof {
779- std:: mem:: drop ( batch_state_lock) ;
780- send_message (
781- ws_conn_sink. clone ( ) ,
782- SubmitProofResponseMessage :: UnderpricedProof ,
783- )
784- . await ;
785- return Ok ( ( ) ) ;
786- }
787-
788788 let Some ( user_last_max_fee_limit) =
789789 batch_state_lock. get_user_last_max_fee_limit ( & addr) . await
790790 else {
@@ -1007,12 +1007,11 @@ impl Batcher {
10071007 return ;
10081008 } ;
10091009
1010- // the replacement max fee bump must be at least 10 percent higher
1011- // TODO: move this to a config file
1010+ // Validate that the max fee is at least higher or equal to the original fee + a [`min_bump_percentage`]
10121011 let original_max_fee = entry. nonced_verification_data . max_fee ;
1013- let bump_factor_percentage = 10 ;
10141012 let min_bump = original_max_fee
1015- + ( original_max_fee * U256 :: from ( bump_factor_percentage) ) / U256 :: from ( 100 ) ;
1013+ + ( original_max_fee * U256 :: from ( self . min_bump_percentage ) ) / U256 :: from ( 100 ) ;
1014+
10161015 if replacement_max_fee < min_bump {
10171016 std:: mem:: drop ( batch_state_lock) ;
10181017 warn ! ( "Invalid replacement message for address {addr}, had max fee: {original_max_fee:?}, received fee: {replacement_max_fee:?}" ) ;
@@ -2046,6 +2045,15 @@ impl Batcher {
20462045 true
20472046 }
20482047
2048+ async fn msg_covers_minimum_max_fee ( & self , msg_max_fee : U256 ) -> bool {
2049+ let gas_price = * self . latest_block_gas_price . read ( ) . await ;
2050+ let min_max_fee_per_proof = aligned_sdk:: verification_layer:: compute_fee_per_proof_formula (
2051+ self . proofs_to_cover_in_min_max_fee ,
2052+ gas_price,
2053+ ) ;
2054+ msg_max_fee >= min_max_fee_per_proof
2055+ }
2056+
20492057 /// Checks if the user's balance is unlocked
20502058 /// Returns false if balance is unlocked, logs the error,
20512059 /// and sends it to the metrics server
0 commit comments