@@ -136,8 +136,6 @@ where
136136 let is_eip3607_disabled = ctx. cfg ( ) . is_eip3607_disabled ( ) ;
137137 let is_nonce_check_disabled = ctx. cfg ( ) . is_nonce_check_disabled ( ) ;
138138
139- let mint = ctx. tx ( ) . mint ( ) . unwrap_or_default ( ) ;
140-
141139 let ( tx, journal) = ctx. tx_journal_mut ( ) ;
142140
143141 let mut caller_account = journal. load_account_with_code_mut ( tx. caller ( ) ) ?. data ;
@@ -152,11 +150,19 @@ where
152150 ) ?;
153151 }
154152
155- let mut new_balance = caller_account. info . balance . saturating_add ( U256 :: from ( mint) ) ;
153+ // For L1->L2 transactions, we only credit the tx value so the initial value transfer succeeds.
154+ // On ZKsync OS, the mint value isn’t added to msg.sender.balance until the transaction finishes.
155+ if is_l1_to_l2_tx {
156+ let new_balance = caller_account. info . balance . saturating_add ( tx. value ( ) ) ;
157+ caller_account. touch ( ) ;
158+ caller_account. set_balance ( new_balance) ;
159+ return Ok ( ( ) ) ;
160+ }
156161
162+ let mut new_balance = caller_account. info . balance ;
157163 let max_balance_spending = tx. max_balance_spending ( ) ?;
158164
159- if !is_l1_to_l2_tx && max_balance_spending > new_balance {
165+ if max_balance_spending > new_balance {
160166 // skip max balance check for deposit transactions.
161167 // this check for deposit was skipped previously in `validate_tx_against_state` function
162168 return Err ( InvalidTransaction :: LackOfFundForMaxFee {
@@ -192,38 +198,41 @@ where
192198 evm : & mut Self :: Evm ,
193199 frame_result : & mut <<Self :: Evm as EvmTr >:: Frame as FrameTr >:: FrameResult ,
194200 ) -> Result < ( ) , Self :: Error > {
195- reimburse_caller ( evm. ctx ( ) , frame_result. gas ( ) , U256 :: ZERO ) ?;
201+ if !evm. ctx ( ) . tx ( ) . is_l1_to_l2_tx ( ) {
202+ reimburse_caller ( evm. ctx ( ) , frame_result. gas ( ) , U256 :: ZERO ) ?;
203+ return Ok ( ( ) ) ;
204+ }
196205
197- let is_l1_to_l2_tx = evm. ctx ( ) . tx ( ) . is_l1_to_l2_tx ( ) ;
198- if is_l1_to_l2_tx {
199- let caller = evm. ctx ( ) . tx ( ) . caller ( ) ;
200- let refund_recipient = evm
201- . ctx ( )
202- . tx ( )
203- . refund_recipient ( )
204- . expect ( "Refund recipient is missing for L1 -> L2 tx" ) ;
205-
206- let basefee = evm. ctx ( ) . block ( ) . basefee ( ) as u128 ;
207- let effective_gas_price = evm. ctx ( ) . tx ( ) . effective_gas_price ( basefee) ;
208- let spent_fee =
209- U256 :: from ( frame_result. gas ( ) . spent ( ) ) * U256 :: from ( effective_gas_price) ;
210- let mint = evm. ctx ( ) . tx ( ) . mint ( ) . unwrap_or_default ( ) ;
211- let value = evm. ctx ( ) . tx ( ) . value ( ) ;
212-
213- // Did the call succeed?
214- let is_success = frame_result. interpreter_result ( ) . result . is_ok ( ) ;
215-
216- let additional_refund = if is_success {
217- mint - value - spent_fee
218- } else {
219- mint - spent_fee
220- } ;
221-
222- // // Return balance of not spend gas.
206+ // For L1->L2 transactions, mint and gas fees were not applied to the
207+ // sender before execution. Handle all balance accounting here.
208+ let caller = evm. ctx ( ) . tx ( ) . caller ( ) ;
209+ let refund_recipient = evm
210+ . ctx ( )
211+ . tx ( )
212+ . refund_recipient ( )
213+ . expect ( "Refund recipient is missing for L1 -> L2 tx" ) ;
214+
215+ let basefee = evm. ctx ( ) . block ( ) . basefee ( ) as u128 ;
216+ let effective_gas_price = evm. ctx ( ) . tx ( ) . effective_gas_price ( basefee) ;
217+ let spent_fee = U256 :: from ( frame_result. gas ( ) . spent ( ) ) * U256 :: from ( effective_gas_price) ;
218+ let mint = evm. ctx ( ) . tx ( ) . mint ( ) . unwrap_or_default ( ) ;
219+ let value = evm. ctx ( ) . tx ( ) . value ( ) ;
220+
221+ let is_success = frame_result. interpreter_result ( ) . result . is_ok ( ) ;
222+
223+ if !is_success {
224+ // On failure, value transfer was rolled back so sender still holds
225+ // the extra `value` credited before execution. Move it to refund_recipient.
223226 evm. ctx ( )
224227 . journal_mut ( )
225- . transfer ( caller, refund_recipient, additional_refund ) ?;
228+ . transfer ( caller, refund_recipient, value ) ?;
226229 }
230+
231+ // Mint the remaining refund directly to refund_recipient.
232+ evm. ctx ( )
233+ . journal_mut ( )
234+ . balance_incr ( refund_recipient, mint - value - spent_fee) ?;
235+
227236 Ok ( ( ) )
228237 }
229238
0 commit comments