@@ -33,7 +33,8 @@ import (
3333)
3434
3535var (
36- BVM_ETH_ADDR = common .HexToAddress ("0xdEAddEaDdeadDEadDEADDEAddEADDEAddead1111" )
36+ BVM_ETH_ADDR = common .HexToAddress ("0xdEAddEaDdeadDEadDEADDEAddEADDEAddead1111" )
37+ LEGACY_ERC20_MNT = common .HexToAddress ("0xdEAddEaDdeadDEadDEADDEAddEADDEAddead0000" )
3738)
3839
3940// ExecutionResult includes all output after executing given evm
@@ -175,7 +176,7 @@ func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.In
175176 if rules == nil {
176177 return nil , errors .New ("param rules is nil pointer" )
177178 }
178- metaTxParams , err := types .DecodeAndVerifyMetaTxParams (tx , rules .IsMetaTxV2 )
179+ metaTxParams , err := types .DecodeAndVerifyMetaTxParams (tx , rules .IsMetaTxV2 , rules . IsMetaTxV3 )
179180 if err != nil {
180181 return nil , err
181182 }
@@ -223,6 +224,11 @@ func (st *StateTransition) CalculateRollupGasDataFromMessage() {
223224 // add a constant to cover sigs(V,R,S) and other data to make sure that the gasLimit from eth_estimateGas can cover L1 cost
224225 // just used for estimateGas and the actual L1 cost depends on users' tx when executing
225226 st .msg .RollupDataGas .Ones += 80
227+
228+ // add a constant to cover meta tx sigs(V,R,S)
229+ if st .msg .MetaTxParams != nil {
230+ st .msg .RollupDataGas .Ones += 80
231+ }
226232}
227233
228234// ApplyMessage computes the new state by applying the given message
@@ -265,15 +271,18 @@ type StateTransition struct {
265271 initialGas uint64
266272 state vm.StateDB
267273 evm * vm.EVM
274+
275+ initialSponsorValue * big.Int
268276}
269277
270278// NewStateTransition initialises and returns a new state transition object.
271279func NewStateTransition (evm * vm.EVM , msg * Message , gp * GasPool ) * StateTransition {
272280 return & StateTransition {
273- gp : gp ,
274- evm : evm ,
275- msg : msg ,
276- state : evm .StateDB ,
281+ gp : gp ,
282+ evm : evm ,
283+ msg : msg ,
284+ state : evm .StateDB ,
285+ initialSponsorValue : big .NewInt (0 ),
277286 }
278287}
279288
@@ -285,10 +294,13 @@ func (st *StateTransition) to() common.Address {
285294 return * st .msg .To
286295}
287296
288- func (st * StateTransition ) buyGas () (* big.Int , error ) {
289- if err := st .applyMetaTransaction (); err != nil {
290- return nil , err
297+ func (st * StateTransition ) buyGas (metaTxV3 bool ) (* big.Int , error ) {
298+ if ! metaTxV3 {
299+ if err := st .applyMetaTransaction (); err != nil {
300+ return nil , err
301+ }
291302 }
303+
292304 mgval := new (big.Int ).SetUint64 (st .msg .GasLimit )
293305 mgval = mgval .Mul (mgval , st .msg .GasPrice )
294306 var l1Cost * big.Int
@@ -298,17 +310,12 @@ func (st *StateTransition) buyGas() (*big.Int, error) {
298310 if st .evm .Context .L1CostFunc != nil && st .msg .RunMode != EthcallMode {
299311 l1Cost = st .evm .Context .L1CostFunc (st .evm .Context .BlockNumber .Uint64 (), st .evm .Context .Time , st .msg .RollupDataGas , st .msg .IsDepositTx , st .msg .To )
300312 }
301- if l1Cost != nil && (st .msg .RunMode == GasEstimationMode || st .msg .RunMode == GasEstimationWithSkipCheckBalanceMode ) {
302- mgval = mgval .Add (mgval , l1Cost )
303- }
313+
304314 balanceCheck := new (big.Int ).Set (mgval )
305315 if st .msg .GasFeeCap != nil {
306316 balanceCheck .SetUint64 (st .msg .GasLimit )
307317 balanceCheck = balanceCheck .Mul (balanceCheck , st .msg .GasFeeCap )
308318 balanceCheck .Add (balanceCheck , st .msg .Value )
309- if l1Cost != nil && st .msg .RunMode == GasEstimationMode {
310- balanceCheck .Add (balanceCheck , l1Cost )
311- }
312319 }
313320 if st .msg .RunMode != GasEstimationWithSkipCheckBalanceMode && st .msg .RunMode != EthcallMode {
314321 if st .msg .MetaTxParams != nil {
@@ -321,6 +328,11 @@ func (st *StateTransition) buyGas() (*big.Int, error) {
321328 if have , want := st .state .GetBalance (st .msg .From ), selfPayAmount ; have .Cmp (want ) < 0 {
322329 return nil , fmt .Errorf ("%w: address %v have %v want %v" , ErrInsufficientFunds , st .msg .From .Hex (), have , want )
323330 }
331+ if st .msg .MetaTxParams .GasFeeSponsor == st .msg .From {
332+ if have , want := st .state .GetBalance (st .msg .From ), pureGasFeeValue ; have .Cmp (want ) < 0 {
333+ return nil , fmt .Errorf ("%w: address %v have %v want %v" , ErrInsufficientFunds , st .msg .From .Hex (), have , want )
334+ }
335+ }
324336 } else {
325337 if have , want := st .state .GetBalance (st .msg .From ), balanceCheck ; have .Cmp (want ) < 0 {
326338 return nil , fmt .Errorf ("%w: address %v have %v want %v" , ErrInsufficientFunds , st .msg .From .Hex (), have , want )
@@ -337,9 +349,10 @@ func (st *StateTransition) buyGas() (*big.Int, error) {
337349 if st .msg .RunMode != GasEstimationWithSkipCheckBalanceMode && st .msg .RunMode != EthcallMode {
338350 if st .msg .MetaTxParams != nil {
339351 sponsorAmount , selfPayAmount := types .CalculateSponsorPercentAmount (st .msg .MetaTxParams , mgval )
352+ st .initialSponsorValue = sponsorAmount
340353 st .state .SubBalance (st .msg .MetaTxParams .GasFeeSponsor , sponsorAmount )
341354 st .state .SubBalance (st .msg .From , selfPayAmount )
342- log .Debug ("BuyGas for metaTx" ,
355+ log .Debug ("BuyGas for metaTx" , "v3" , metaTxV3 ,
343356 "sponsor" , st .msg .MetaTxParams .GasFeeSponsor .String (), "amount" , sponsorAmount .String (),
344357 "user" , st .msg .From .String (), "amount" , selfPayAmount .String ())
345358 } else {
@@ -361,7 +374,7 @@ func (st *StateTransition) applyMetaTransaction() error {
361374 return nil
362375}
363376
364- func (st * StateTransition ) preCheck () (* big.Int , error ) {
377+ func (st * StateTransition ) preCheck (metaTxV3 bool ) (* big.Int , error ) {
365378 if st .msg .IsDepositTx {
366379 // No fee fields to check, no nonce to check, and no need to check if EOA (L1 already verified it for us)
367380 // Gas is free, but no refunds!
@@ -427,7 +440,7 @@ func (st *StateTransition) preCheck() (*big.Int, error) {
427440 }
428441 }
429442 }
430- return st .buyGas ()
443+ return st .buyGas (metaTxV3 )
431444}
432445
433446// TransitionDb will transition the state by applying the current message and
@@ -500,7 +513,7 @@ func (st *StateTransition) innerTransitionDb() (*ExecutionResult, error) {
500513
501514 // Check clauses 1-3, buy gas if everything is correct
502515 tokenRatio := st .state .GetState (types .GasOracleAddr , types .TokenRatioSlot ).Big ().Uint64 ()
503- l1Cost , err := st .preCheck ()
516+ l1Cost , err := st .preCheck (rules . IsMetaTxV3 )
504517 if err != nil {
505518 return nil , err
506519 }
@@ -524,6 +537,13 @@ func (st *StateTransition) innerTransitionDb() (*ExecutionResult, error) {
524537 return nil , err
525538 }
526539
540+ // after calculate intrinsic gas, apply meta tx data
541+ if rules .IsMetaTxV3 {
542+ if err := st .applyMetaTransaction (); err != nil {
543+ return nil , err
544+ }
545+ }
546+
527547 if ! st .msg .IsDepositTx && ! st .msg .IsSystemTx {
528548 gas = gas * tokenRatio
529549 }
@@ -594,10 +614,10 @@ func (st *StateTransition) innerTransitionDb() (*ExecutionResult, error) {
594614 if ! st .msg .IsDepositTx && ! st .msg .IsSystemTx {
595615 if ! rules .IsLondon {
596616 // Before EIP-3529: refunds were capped to gasUsed / 2
597- st .refundGas (params .RefundQuotient , tokenRatio )
617+ st .refundGas (params .RefundQuotient , tokenRatio , rules )
598618 } else {
599619 // After EIP-3529: refunds are capped to gasUsed / 5
600- st .refundGas (params .RefundQuotientEIP3529 , tokenRatio )
620+ st .refundGas (params .RefundQuotientEIP3529 , tokenRatio , rules )
601621 }
602622 }
603623
@@ -641,7 +661,7 @@ func (st *StateTransition) innerTransitionDb() (*ExecutionResult, error) {
641661 }, nil
642662}
643663
644- func (st * StateTransition ) refundGas (refundQuotient , tokenRatio uint64 ) {
664+ func (st * StateTransition ) refundGas (refundQuotient , tokenRatio uint64 , rules params. Rules ) {
645665 if st .msg .RunMode == GasEstimationWithSkipCheckBalanceMode || st .msg .RunMode == EthcallMode {
646666 st .gasRemaining = st .gasRemaining * tokenRatio
647667 st .gp .AddGas (st .gasRemaining )
@@ -661,6 +681,10 @@ func (st *StateTransition) refundGas(refundQuotient, tokenRatio uint64) {
661681 sponsorRefundAmount , selfRefundAmount := types .CalculateSponsorPercentAmount (st .msg .MetaTxParams , remaining )
662682 st .state .AddBalance (st .msg .MetaTxParams .GasFeeSponsor , sponsorRefundAmount )
663683 st .state .AddBalance (st .msg .From , selfRefundAmount )
684+ if rules .IsMetaTxV3 {
685+ actualSponsorValue := new (big.Int ).Sub (st .initialSponsorValue , sponsorRefundAmount )
686+ st .generateMetaTxSponsorEvent (st .msg .MetaTxParams .GasFeeSponsor , st .msg .From , actualSponsorValue )
687+ }
664688 log .Debug ("RefundGas for metaTx" ,
665689 "sponsor" , st .msg .MetaTxParams .GasFeeSponsor .String (), "refundAmount" , sponsorRefundAmount .String (),
666690 "user" , st .msg .From .String (), "refundAmount" , selfRefundAmount .String ())
@@ -801,3 +825,22 @@ func (st *StateTransition) generateBVMETHTransferEvent(from, to common.Address,
801825 BlockNumber : st .evm .Context .BlockNumber .Uint64 (),
802826 })
803827}
828+
829+ func (st * StateTransition ) generateMetaTxSponsorEvent (sponsor , txSender common.Address , actualSponsorAmount * big.Int ) {
830+ // keccak("MetaTxSponsor(address,address,uint256)") = "0xe57e5af44e0b977ac446043abcb6b8958c04a1004c91d7342e2870761b21af95"
831+ methodHash := common .HexToHash ("0xe57e5af44e0b977ac446043abcb6b8958c04a1004c91d7342e2870761b21af95" )
832+ topics := make ([]common.Hash , 3 )
833+ topics [0 ] = methodHash
834+ topics [1 ] = sponsor .Hash ()
835+ topics [2 ] = txSender .Hash ()
836+ //data means the sponsor amount in MetaTxSponsor EVENT.
837+ d := common .HexToHash (common .Bytes2Hex (actualSponsorAmount .Bytes ())).Bytes ()
838+ st .evm .StateDB .AddLog (& types.Log {
839+ Address : LEGACY_ERC20_MNT ,
840+ Topics : topics ,
841+ Data : d ,
842+ // This is a non-consensus field, but assigned here because
843+ // core/state doesn't know the current block number.
844+ BlockNumber : st .evm .Context .BlockNumber .Uint64 (),
845+ })
846+ }
0 commit comments