From 1195f7ab11b2ca89cfdbd3ace50e7572522c779a Mon Sep 17 00:00:00 2001 From: liuhaoyang Date: Mon, 8 Apr 2024 18:58:28 +0800 Subject: [PATCH 01/12] import upgrade to metatx to ensure sponsor doesn't equal to tx sender --- core/genesis.go | 3 +- core/mantle_upgrade.go | 19 ++++--- core/state_transition.go | 7 ++- core/txpool/txpool.go | 9 ++-- core/types/meta_transaction.go | 25 ++++++--- core/types/meta_transaction_test.go | 82 ++++++++++++++++++++++++----- core/types/transaction_signing.go | 69 ++++++++++++++++++++++++ light/txpool.go | 2 +- params/config.go | 13 +++-- 9 files changed, 193 insertions(+), 36 deletions(-) diff --git a/core/genesis.go b/core/genesis.go index 265cbb130a..742a5d93f7 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -311,7 +311,8 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen if mantleUpgradeChainConfig != nil { config.BaseFeeTime = mantleUpgradeChainConfig.BaseFeeTime config.BVMETHMintUpgradeTime = mantleUpgradeChainConfig.BVMETHMintUpgradeTime - config.MetaTxUpgradeTime = mantleUpgradeChainConfig.MetaTxUpgradeTime + config.MetaTxV1UpgradeTime = mantleUpgradeChainConfig.MetaTxV1UpgradeTime + config.MetaTxV2UpgradeTime = mantleUpgradeChainConfig.MetaTxV2UpgradeTime } if overrides != nil && overrides.OverrideShanghai != nil { diff --git a/core/mantle_upgrade.go b/core/mantle_upgrade.go index ce033805d0..e692944949 100644 --- a/core/mantle_upgrade.go +++ b/core/mantle_upgrade.go @@ -11,34 +11,39 @@ var ( ChainID: params.MantleMainnetChainId, BaseFeeTime: u64Ptr(0), BVMETHMintUpgradeTime: u64Ptr(0), - MetaTxUpgradeTime: u64Ptr(0), + MetaTxV1UpgradeTime: u64Ptr(0), + MetaTxV2UpgradeTime: u64Ptr(0), //TODO set upgrade timestamp } MantleSepoliaUpgradeConfig = MantleUpgradeChainConfig{ ChainID: params.MantleSepoliaChainId, BaseFeeTime: u64Ptr(1_704_891_600), BVMETHMintUpgradeTime: nil, //TODO set upgrade timestamp - MetaTxUpgradeTime: nil, //TODO set upgrade timestamp + MetaTxV1UpgradeTime: nil, //TODO set upgrade timestamp + MetaTxV2UpgradeTime: nil, //TODO set upgrade timestamp } MantleLocalUpgradeConfig = MantleUpgradeChainConfig{ ChainID: params.MantleLocalChainId, BaseFeeTime: u64Ptr(0), BVMETHMintUpgradeTime: u64Ptr(0), - MetaTxUpgradeTime: u64Ptr(0), + MetaTxV1UpgradeTime: u64Ptr(0), + MetaTxV2UpgradeTime: u64Ptr(0), } MantleDefaultUpgradeConfig = MantleUpgradeChainConfig{ BaseFeeTime: u64Ptr(0), BVMETHMintUpgradeTime: u64Ptr(0), - MetaTxUpgradeTime: u64Ptr(0), + MetaTxV1UpgradeTime: u64Ptr(0), + MetaTxV2UpgradeTime: u64Ptr(0), } ) type MantleUpgradeChainConfig struct { ChainID *big.Int `json:"chainId"` // chainId identifies the current chain and is used for replay protection - BaseFeeTime *uint64 `json:"BaseFeeTime"` // Mantle BaseFee switch time (nil = no fork, 0 = already on mantle baseFee) - BVMETHMintUpgradeTime *uint64 `json:"BVMETHMintUpgradeTime"` // BVM_ETH mint upgrade switch time (nil = no fork, 0 = already on) - MetaTxUpgradeTime *uint64 `json:"metaTxUpgradeTime"` // MetaTxUpgradeBlock identifies the current block height is using metaTx with MetaTxSignDataV2 + BaseFeeTime *uint64 `json:"baseFeeTime"` // Mantle BaseFee switch time (nil = no fork, 0 = already on mantle baseFee) + BVMETHMintUpgradeTime *uint64 `json:"bvmETHMintUpgradeTime"` // BVM_ETH mint upgrade switch time (nil = no fork, 0 = already on) + MetaTxV1UpgradeTime *uint64 `json:"metaTxV1UpgradeTime"` // MetaTxV1UpgradeBlock identifies the current block height is using metaTx with MetaTxSignDataV2 + MetaTxV2UpgradeTime *uint64 `json:"metaTxV2UpgradeTime"` // MetaTxV2UpgradeBlock identifies the current block height is using metaTx with MetaTxSignDataV3 } func GetUpgradeConfigForMantle(chainID *big.Int) *MantleUpgradeChainConfig { diff --git a/core/state_transition.go b/core/state_transition.go index 8f61dab191..fe204b8342 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -175,7 +175,7 @@ func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.In if rules == nil { return nil, errors.New("param rules is nil pointer") } - metaTxParams, err := types.DecodeAndVerifyMetaTxParams(tx, rules.IsMetaTxV2) + metaTxParams, err := types.DecodeAndVerifyMetaTxParams(tx, rules.IsMetaTxV2, rules.IsMetaTxV3) if err != nil { return nil, err } @@ -321,6 +321,11 @@ func (st *StateTransition) buyGas() (*big.Int, error) { if have, want := st.state.GetBalance(st.msg.From), selfPayAmount; have.Cmp(want) < 0 { return nil, fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From.Hex(), have, want) } + if st.msg.MetaTxParams.GasFeeSponsor == st.msg.From { + if have, want := st.state.GetBalance(st.msg.From), pureGasFeeValue; have.Cmp(want) < 0 { + return nil, fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From.Hex(), have, want) + } + } } else { if have, want := st.state.GetBalance(st.msg.From), balanceCheck; have.Cmp(want) < 0 { return nil, fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From.Hex(), have, want) diff --git a/core/txpool/txpool.go b/core/txpool/txpool.go index 3d47c6bde0..0929f7038f 100644 --- a/core/txpool/txpool.go +++ b/core/txpool/txpool.go @@ -694,7 +694,8 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { cost = cost.Add(cost, l1Cost) } - metaTxParams, err := types.DecodeAndVerifyMetaTxParams(tx, pool.chainconfig.IsMetaTxV2(pool.chain.CurrentBlock().Time)) + metaTxParams, err := types.DecodeAndVerifyMetaTxParams(tx, + pool.chainconfig.IsMetaTxV2(pool.chain.CurrentBlock().Time), pool.chainconfig.IsMetaTxV3(pool.chain.CurrentBlock().Time)) if err != nil { return err } @@ -737,7 +738,8 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { if replL1Cost := pool.l1CostFn(repl.RollupDataGas(), repl.IsDepositTx(), repl.To()); replL1Cost != nil { // add rollup cost replCost = replCost.Add(cost, replL1Cost) } - replMetaTxParams, err := types.DecodeAndVerifyMetaTxParams(repl, pool.chainconfig.IsMetaTxV2(pool.chain.CurrentBlock().Time)) + replMetaTxParams, err := types.DecodeAndVerifyMetaTxParams(repl, + pool.chainconfig.IsMetaTxV2(pool.chain.CurrentBlock().Time), pool.chainconfig.IsMetaTxV3(pool.chain.CurrentBlock().Time)) if err != nil { return err } @@ -1525,7 +1527,8 @@ func (pool *TxPool) validateMetaTxList(list *list) ([]*types.Transaction, *big.I sponsorCostSum := big.NewInt(0) sponsorCostSumPerSponsor := make(map[common.Address]*big.Int) for _, tx := range list.txs.Flatten() { - metaTxParams, err := types.DecodeAndVerifyMetaTxParams(tx, pool.chainconfig.IsMetaTxV2(pool.chain.CurrentBlock().Time)) + metaTxParams, err := types.DecodeAndVerifyMetaTxParams(tx, + pool.chainconfig.IsMetaTxV2(pool.chain.CurrentBlock().Time), pool.chainconfig.IsMetaTxV3(pool.chain.CurrentBlock().Time)) if err != nil { invalidMetaTxs = append(invalidMetaTxs, tx) continue diff --git a/core/types/meta_transaction.go b/core/types/meta_transaction.go index afd0b4c45a..6d32661670 100644 --- a/core/types/meta_transaction.go +++ b/core/types/meta_transaction.go @@ -19,11 +19,12 @@ var ( // ASCII code of "MantleMetaTxPrefix" MetaTxPrefix, _ = hexutil.Decode("0x00000000000000000000000000004D616E746C654D6574615478507265666978") - ErrExpiredMetaTx = errors.New("expired meta transaction") - ErrInvalidGasFeeSponsorSig = errors.New("invalid gas fee sponsor signature") - ErrGasFeeSponsorMismatch = errors.New("gas fee sponsor address is mismatch with signature") - ErrInvalidSponsorPercent = errors.New("invalid sponsor percent, expected range (0, 100]") - ErrSponsorBalanceNotEnough = errors.New("sponsor doesn't have enough balance") + ErrExpiredMetaTx = errors.New("expired meta transaction") + ErrInvalidGasFeeSponsorSig = errors.New("invalid gas fee sponsor signature") + ErrGasFeeSponsorMismatch = errors.New("gas fee sponsor address is mismatch with signature") + ErrInvalidSponsorPercent = errors.New("invalid sponsor percent, expected range (0, 100]") + ErrSponsorBalanceNotEnough = errors.New("sponsor doesn't have enough balance") + ErrSponsorMustNotEqualToSender = errors.New("sponsor must not equal to tx sender") ) type MetaTxParams struct { @@ -104,7 +105,7 @@ func DecodeMetaTxParams(txData []byte) (*MetaTxParams, error) { return &metaTxParams, nil } -func DecodeAndVerifyMetaTxParams(tx *Transaction, isMetaTxUpgraded bool) (*MetaTxParams, error) { +func DecodeAndVerifyMetaTxParams(tx *Transaction, isMetaTxV1Upgraded, isMetaTxV2Upgraded bool) (*MetaTxParams, error) { if tx.Type() != DynamicFeeTxType { return nil, nil } @@ -128,10 +129,20 @@ func DecodeAndVerifyMetaTxParams(tx *Transaction, isMetaTxUpgraded bool) (*MetaT return nil, nil } - if err = checkSponsorSignature(tx, metaTxParams, isMetaTxUpgraded); err != nil { + if err = checkSponsorSignature(tx, metaTxParams, isMetaTxV1Upgraded); err != nil { return nil, err } + if isMetaTxV2Upgraded { + txSender, err := Sender(LatestSignerForChainID(tx.ChainId()), tx) + if err != nil { + return nil, err + } + if txSender == metaTxParams.GasFeeSponsor { + return nil, ErrSponsorMustNotEqualToSender + } + } + tx.metaTxParams.Store(&MetaTxParamsCache{ metaTxParams: metaTxParams, }) diff --git a/core/types/meta_transaction_test.go b/core/types/meta_transaction_test.go index e6fc819334..1519db5b34 100644 --- a/core/types/meta_transaction_test.go +++ b/core/types/meta_transaction_test.go @@ -101,11 +101,10 @@ func generateMetaTxDataWithMockSig(dynamicTx *DynamicFeeTx, expireHeight uint64, return append(MetaTxPrefix, metaTxDataBz...), nil } -func generateMetaTxDataV2(dynamicTx *DynamicFeeTx, expireHeight uint64, sponsorPercent uint64, +func generateMetaTxDataV2(dynamicTx *DynamicFeeTx, msgSender common.Address, expireHeight uint64, sponsorPercent uint64, gasFeeSponsorAddr common.Address, privateKey *ecdsa.PrivateKey) ([]byte, error) { - from := crypto.PubkeyToAddress(userKey.PublicKey) metaTxSignData := &MetaTxSignDataV2{ - From: from, + From: msgSender, ChainID: dynamicTx.ChainID, Nonce: dynamicTx.Nonce, GasTipCap: dynamicTx.GasTipCap, @@ -232,7 +231,7 @@ func TestDecodeAndVerifyMetaTxParams(t *testing.T) { require.NoError(t, err) // test normal metaTx - metaTxParams, err := DecodeAndVerifyMetaTxParams(signedTx, false) + metaTxParams, err := DecodeAndVerifyMetaTxParams(signedTx, false, false) require.NoError(t, err) require.Equal(t, gasFeeSponsorAddr.String(), metaTxParams.GasFeeSponsor.String()) @@ -250,7 +249,7 @@ func TestDecodeAndVerifyMetaTxParams(t *testing.T) { signedTx, err = tx.WithSignature(signer, txSignature) require.NoError(t, err) - _, err = DecodeAndVerifyMetaTxParams(signedTx, false) + _, err = DecodeAndVerifyMetaTxParams(signedTx, false, false) require.Equal(t, err, ErrInvalidGasFeeSponsorSig) // Test ErrGasFeeSponsorMismatch @@ -265,7 +264,7 @@ func TestDecodeAndVerifyMetaTxParams(t *testing.T) { signedTx, err = tx.WithSignature(signer, txSignature) require.NoError(t, err) - _, err = DecodeAndVerifyMetaTxParams(signedTx, true) + _, err = DecodeAndVerifyMetaTxParams(signedTx, true, false) require.Equal(t, err, ErrGasFeeSponsorMismatch) // Test ErrGasFeeSponsorMismatch @@ -280,7 +279,7 @@ func TestDecodeAndVerifyMetaTxParams(t *testing.T) { signedTx, err = tx.WithSignature(signer, txSignature) require.NoError(t, err) - _, err = DecodeAndVerifyMetaTxParams(signedTx, false) + _, err = DecodeAndVerifyMetaTxParams(signedTx, false, false) require.Equal(t, err, ErrInvalidSponsorPercent) } @@ -305,7 +304,7 @@ func TestDecodeAndVerifyMetaTxParamsV2(t *testing.T) { AccessList: nil, } - payload, err := generateMetaTxDataV2(dynamicTx, expireHeight, 50, gasFeeSponsorAddr, gasFeeSponsorKey1) + payload, err := generateMetaTxDataV2(dynamicTx, crypto.PubkeyToAddress(userKey.PublicKey), expireHeight, 50, gasFeeSponsorAddr, gasFeeSponsorKey1) require.NoError(t, err) dynamicTx.Data = payload @@ -317,7 +316,7 @@ func TestDecodeAndVerifyMetaTxParamsV2(t *testing.T) { require.NoError(t, err) // test normal metaTx - metaTxParams, err := DecodeAndVerifyMetaTxParams(signedTx, true) + metaTxParams, err := DecodeAndVerifyMetaTxParams(signedTx, true, false) require.NoError(t, err) require.Equal(t, gasFeeSponsorAddr.String(), metaTxParams.GasFeeSponsor.String()) @@ -335,12 +334,12 @@ func TestDecodeAndVerifyMetaTxParamsV2(t *testing.T) { signedTx, err = tx.WithSignature(signer, txSignature) require.NoError(t, err) - _, err = DecodeAndVerifyMetaTxParams(signedTx, true) + _, err = DecodeAndVerifyMetaTxParams(signedTx, true, false) require.Equal(t, err, ErrInvalidGasFeeSponsorSig) // Test ErrGasFeeSponsorMismatch dynamicTx.Data = depositABICalldata - payload, err = generateMetaTxDataV2(dynamicTx, expireHeight, 80, gasFeeSponsorAddr, gasFeeSponsorKey2) + payload, err = generateMetaTxDataV2(dynamicTx, crypto.PubkeyToAddress(userKey.PublicKey), expireHeight, 80, gasFeeSponsorAddr, gasFeeSponsorKey2) require.NoError(t, err) dynamicTx.Data = payload @@ -350,7 +349,7 @@ func TestDecodeAndVerifyMetaTxParamsV2(t *testing.T) { signedTx, err = tx.WithSignature(signer, txSignature) require.NoError(t, err) - _, err = DecodeAndVerifyMetaTxParams(signedTx, true) + _, err = DecodeAndVerifyMetaTxParams(signedTx, true, false) require.Equal(t, err, ErrGasFeeSponsorMismatch) // Test ErrGasFeeSponsorMismatch @@ -365,6 +364,63 @@ func TestDecodeAndVerifyMetaTxParamsV2(t *testing.T) { signedTx, err = tx.WithSignature(signer, txSignature) require.NoError(t, err) - _, err = DecodeAndVerifyMetaTxParams(signedTx, false) + _, err = DecodeAndVerifyMetaTxParams(signedTx, false, false) require.Equal(t, err, ErrInvalidSponsorPercent) } + +func TestDecodeAndVerifyMetaTxParamsV3(t *testing.T) { + gasFeeSponsorPublicKey := gasFeeSponsorKey1.Public() + pubKeyECDSA, _ := gasFeeSponsorPublicKey.(*ecdsa.PublicKey) + gasFeeSponsorAddr := crypto.PubkeyToAddress(*pubKeyECDSA) + + chainId := big.NewInt(1) + depositABICalldata, _ := hexutil.Decode("0xd0e30db0") + to := common.HexToAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") + expireHeight := uint64(20_000_010) + dynamicTx := &DynamicFeeTx{ + ChainID: chainId, + Nonce: 100, + GasTipCap: big.NewInt(1e9), + GasFeeCap: big.NewInt(1e15), + Gas: 4700000, + To: &to, + Value: big.NewInt(1e18), + Data: depositABICalldata, + AccessList: nil, + } + + userPrivateKey := gasFeeSponsorKey1 + msgSender := crypto.PubkeyToAddress(userPrivateKey.PublicKey) + payload, err := generateMetaTxDataV2(dynamicTx, msgSender, expireHeight, 50, gasFeeSponsorAddr, gasFeeSponsorKey1) + require.NoError(t, err) + + dynamicTx.Data = payload + tx := NewTx(dynamicTx) + signer := LatestSignerForChainID(chainId) + txSignature, err := crypto.Sign(signer.Hash(tx).Bytes(), userPrivateKey) + require.NoError(t, err) + signedTx, err := tx.WithSignature(signer, txSignature) + require.NoError(t, err) + + // test normal metaTx + metaTxParams, err := DecodeAndVerifyMetaTxParams(signedTx, true, false) + require.NoError(t, err) + + require.Equal(t, gasFeeSponsorAddr.String(), metaTxParams.GasFeeSponsor.String()) + require.Equal(t, hexutil.Encode(depositABICalldata), hexutil.Encode(metaTxParams.Payload)) + + dynamicTx.Nonce = dynamicTx.Nonce + 1 + payload, err = generateMetaTxDataV2(dynamicTx, msgSender, expireHeight, 50, gasFeeSponsorAddr, gasFeeSponsorKey1) + require.NoError(t, err) + + dynamicTx.Data = payload + tx = NewTx(dynamicTx) + txSignature, err = crypto.Sign(signer.Hash(tx).Bytes(), userPrivateKey) + require.NoError(t, err) + signedTx, err = tx.WithSignature(signer, txSignature) + require.NoError(t, err) + + // test normal metaTx + metaTxParams, err = DecodeAndVerifyMetaTxParams(signedTx, true, true) + require.Error(t, err, ErrSponsorMustNotEqualToSender) +} diff --git a/core/types/transaction_signing.go b/core/types/transaction_signing.go index 70a10eb1c1..dbf46b4e36 100644 --- a/core/types/transaction_signing.go +++ b/core/types/transaction_signing.go @@ -170,6 +170,75 @@ type Signer interface { Equal(Signer) bool } +type cancunSigner struct{ londonSigner } + +// NewCancunSigner returns a signer that accepts +// - EIP-4844 blob transactions +// - EIP-1559 dynamic fee transactions +// - EIP-2930 access list transactions, +// - EIP-155 replay protected transactions, and +// - legacy Homestead transactions. +func NewCancunSigner(chainId *big.Int) Signer { + return cancunSigner{londonSigner{eip2930Signer{NewEIP155Signer(chainId)}}} +} + +func (s cancunSigner) Sender(tx *Transaction) (common.Address, error) { + if tx.Type() != BlobTxType { + return s.londonSigner.Sender(tx) + } + V, R, S := tx.RawSignatureValues() + // Blob txs are defined to use 0 and 1 as their recovery + // id, add 27 to become equivalent to unprotected Homestead signatures. + V = new(big.Int).Add(V, big.NewInt(27)) + if tx.ChainId().Cmp(s.chainId) != 0 { + return common.Address{}, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, tx.ChainId(), s.chainId) + } + return recoverPlain(s.Hash(tx), R, S, V, true) +} + +func (s cancunSigner) Equal(s2 Signer) bool { + x, ok := s2.(cancunSigner) + return ok && x.chainId.Cmp(s.chainId) == 0 +} + +func (s cancunSigner) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big.Int, err error) { + txdata, ok := tx.inner.(*BlobTx) + if !ok { + return s.londonSigner.SignatureValues(tx, sig) + } + // Check that chain ID of tx matches the signer. We also accept ID zero here, + // because it indicates that the chain ID was not specified in the tx. + if txdata.ChainID.Sign() != 0 && txdata.ChainID.ToBig().Cmp(s.chainId) != 0 { + return nil, nil, nil, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, txdata.ChainID, s.chainId) + } + R, S, _ = decodeSignature(sig) + V = big.NewInt(int64(sig[64])) + return R, S, V, nil +} + +// Hash returns the hash to be signed by the sender. +// It does not uniquely identify the transaction. +func (s cancunSigner) Hash(tx *Transaction) common.Hash { + if tx.Type() != BlobTxType { + return s.londonSigner.Hash(tx) + } + return prefixedRlpHash( + tx.Type(), + []interface{}{ + s.chainId, + tx.Nonce(), + tx.GasTipCap(), + tx.GasFeeCap(), + tx.Gas(), + tx.To(), + tx.Value(), + tx.Data(), + tx.AccessList(), + tx.BlobGasFeeCap(), + tx.BlobHashes(), + }) +} + type londonSigner struct{ eip2930Signer } // NewLondonSigner returns a signer that accepts diff --git a/light/txpool.go b/light/txpool.go index 5ab9ffdf5b..71958c0971 100644 --- a/light/txpool.go +++ b/light/txpool.go @@ -379,7 +379,7 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error return txpool.ErrNegativeValue } - metaTxParams, err := types.DecodeAndVerifyMetaTxParams(tx, pool.config.IsMetaTxV2(header.Time)) + metaTxParams, err := types.DecodeAndVerifyMetaTxParams(tx, pool.config.IsMetaTxV2(header.Time), pool.config.IsMetaTxV3(header.Time)) if err != nil { return err } diff --git a/params/config.go b/params/config.go index 924ffced7d..f980752e6c 100644 --- a/params/config.go +++ b/params/config.go @@ -462,7 +462,8 @@ type ChainConfig struct { BVMETHMintUpgradeTime *uint64 `json:"bvmETHMintUpgradeTime,omitempty"` // BVM_ETH mint upgrade switch time (nil = no fork, 0 = already on) // MetaTx upgrade config - MetaTxUpgradeTime *uint64 `json:"metaTxUpgradeTime,omitempty"` // MetaTxUpgradeTime switch time ( nil = no fork, 0 = already forked) + MetaTxV1UpgradeTime *uint64 `json:"metaTxV1UpgradeTime,omitempty"` // MetaTxUpgradeTime switch time ( nil = no fork, 0 = already forked) + MetaTxV2UpgradeTime *uint64 `json:"metaTxV2UpgradeTime,omitempty"` // MetaTxUpgradeTime switch time ( nil = no fork, 0 = already forked) // Fork scheduling was switched from blocks to timestamps here @@ -688,7 +689,12 @@ func (c *ChainConfig) IsMantleBVMETHMintUpgrade(time uint64) bool { // IsMetaTxV2 returns whether time is either equal to the MetaTx fork time or greater. func (c *ChainConfig) IsMetaTxV2(time uint64) bool { - return isTimestampForked(c.MetaTxUpgradeTime, time) + return isTimestampForked(c.MetaTxV1UpgradeTime, time) +} + +// IsMetaTxV3 returns whether time is either equal to the MetaTx fork time or greater. +func (c *ChainConfig) IsMetaTxV3(time uint64) bool { + return isTimestampForked(c.MetaTxV2UpgradeTime, time) } // IsArrowGlacier returns whether num is either equal to the Arrow Glacier (EIP-4345) fork block or greater. @@ -1062,7 +1068,7 @@ type Rules struct { IsMerge, IsShanghai, isCancun, isPrague bool IsMantleBaseFee, IsMantleBVMETHMintUpgrade bool IsOptimismBedrock, IsOptimismRegolith bool - IsMetaTxV2 bool + IsMetaTxV2, IsMetaTxV3 bool } // Rules ensures c's ChainID is not nil. @@ -1090,6 +1096,7 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules isCancun: c.IsCancun(timestamp), isPrague: c.IsPrague(timestamp), IsMetaTxV2: c.IsMetaTxV2(timestamp), + IsMetaTxV3: c.IsMetaTxV3(timestamp), // Optimism IsOptimismBedrock: c.IsOptimismBedrock(num), IsOptimismRegolith: c.IsOptimismRegolith(timestamp), From a16aca147d7b31cc6a90893a303332a6b6aa74cf Mon Sep 17 00:00:00 2001 From: liuhaoyang Date: Tue, 9 Apr 2024 14:48:13 +0800 Subject: [PATCH 02/12] rename upgrade name --- core/genesis.go | 2 +- core/mantle_upgrade.go | 14 +++++++------- core/txpool/txpool.go | 9 ++++++--- light/txpool.go | 3 ++- params/config.go | 8 ++++---- 5 files changed, 20 insertions(+), 16 deletions(-) diff --git a/core/genesis.go b/core/genesis.go index 742a5d93f7..e99eea751c 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -311,8 +311,8 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen if mantleUpgradeChainConfig != nil { config.BaseFeeTime = mantleUpgradeChainConfig.BaseFeeTime config.BVMETHMintUpgradeTime = mantleUpgradeChainConfig.BVMETHMintUpgradeTime - config.MetaTxV1UpgradeTime = mantleUpgradeChainConfig.MetaTxV1UpgradeTime config.MetaTxV2UpgradeTime = mantleUpgradeChainConfig.MetaTxV2UpgradeTime + config.MetaTxV3UpgradeTime = mantleUpgradeChainConfig.MetaTxV3UpgradeTime } if overrides != nil && overrides.OverrideShanghai != nil { diff --git a/core/mantle_upgrade.go b/core/mantle_upgrade.go index e692944949..62fa6a2e74 100644 --- a/core/mantle_upgrade.go +++ b/core/mantle_upgrade.go @@ -11,29 +11,29 @@ var ( ChainID: params.MantleMainnetChainId, BaseFeeTime: u64Ptr(0), BVMETHMintUpgradeTime: u64Ptr(0), - MetaTxV1UpgradeTime: u64Ptr(0), - MetaTxV2UpgradeTime: u64Ptr(0), //TODO set upgrade timestamp + MetaTxV2UpgradeTime: u64Ptr(0), + MetaTxV3UpgradeTime: u64Ptr(0), //TODO set upgrade timestamp } MantleSepoliaUpgradeConfig = MantleUpgradeChainConfig{ ChainID: params.MantleSepoliaChainId, BaseFeeTime: u64Ptr(1_704_891_600), BVMETHMintUpgradeTime: nil, //TODO set upgrade timestamp - MetaTxV1UpgradeTime: nil, //TODO set upgrade timestamp MetaTxV2UpgradeTime: nil, //TODO set upgrade timestamp + MetaTxV3UpgradeTime: nil, //TODO set upgrade timestamp } MantleLocalUpgradeConfig = MantleUpgradeChainConfig{ ChainID: params.MantleLocalChainId, BaseFeeTime: u64Ptr(0), BVMETHMintUpgradeTime: u64Ptr(0), - MetaTxV1UpgradeTime: u64Ptr(0), MetaTxV2UpgradeTime: u64Ptr(0), + MetaTxV3UpgradeTime: u64Ptr(0), } MantleDefaultUpgradeConfig = MantleUpgradeChainConfig{ BaseFeeTime: u64Ptr(0), BVMETHMintUpgradeTime: u64Ptr(0), - MetaTxV1UpgradeTime: u64Ptr(0), MetaTxV2UpgradeTime: u64Ptr(0), + MetaTxV3UpgradeTime: u64Ptr(0), } ) @@ -42,8 +42,8 @@ type MantleUpgradeChainConfig struct { BaseFeeTime *uint64 `json:"baseFeeTime"` // Mantle BaseFee switch time (nil = no fork, 0 = already on mantle baseFee) BVMETHMintUpgradeTime *uint64 `json:"bvmETHMintUpgradeTime"` // BVM_ETH mint upgrade switch time (nil = no fork, 0 = already on) - MetaTxV1UpgradeTime *uint64 `json:"metaTxV1UpgradeTime"` // MetaTxV1UpgradeBlock identifies the current block height is using metaTx with MetaTxSignDataV2 - MetaTxV2UpgradeTime *uint64 `json:"metaTxV2UpgradeTime"` // MetaTxV2UpgradeBlock identifies the current block height is using metaTx with MetaTxSignDataV3 + MetaTxV2UpgradeTime *uint64 `json:"metaTxV2UpgradeTime"` // MetaTxV1UpgradeBlock identifies the current block height is using metaTx with MetaTxSignDataV2 + MetaTxV3UpgradeTime *uint64 `json:"metaTxV3UpgradeTime"` // MetaTxV3UpgradeBlock identifies the current block height is ensuring sponsor and sender are not the same } func GetUpgradeConfigForMantle(chainID *big.Int) *MantleUpgradeChainConfig { diff --git a/core/txpool/txpool.go b/core/txpool/txpool.go index 0929f7038f..07519706bd 100644 --- a/core/txpool/txpool.go +++ b/core/txpool/txpool.go @@ -695,7 +695,8 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { } metaTxParams, err := types.DecodeAndVerifyMetaTxParams(tx, - pool.chainconfig.IsMetaTxV2(pool.chain.CurrentBlock().Time), pool.chainconfig.IsMetaTxV3(pool.chain.CurrentBlock().Time)) + pool.chainconfig.IsMetaTxV2(pool.chain.CurrentBlock().Time), + pool.chainconfig.IsMetaTxV3(pool.chain.CurrentBlock().Time)) if err != nil { return err } @@ -739,7 +740,8 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { replCost = replCost.Add(cost, replL1Cost) } replMetaTxParams, err := types.DecodeAndVerifyMetaTxParams(repl, - pool.chainconfig.IsMetaTxV2(pool.chain.CurrentBlock().Time), pool.chainconfig.IsMetaTxV3(pool.chain.CurrentBlock().Time)) + pool.chainconfig.IsMetaTxV2(pool.chain.CurrentBlock().Time), + pool.chainconfig.IsMetaTxV3(pool.chain.CurrentBlock().Time)) if err != nil { return err } @@ -1528,7 +1530,8 @@ func (pool *TxPool) validateMetaTxList(list *list) ([]*types.Transaction, *big.I sponsorCostSumPerSponsor := make(map[common.Address]*big.Int) for _, tx := range list.txs.Flatten() { metaTxParams, err := types.DecodeAndVerifyMetaTxParams(tx, - pool.chainconfig.IsMetaTxV2(pool.chain.CurrentBlock().Time), pool.chainconfig.IsMetaTxV3(pool.chain.CurrentBlock().Time)) + pool.chainconfig.IsMetaTxV2(pool.chain.CurrentBlock().Time), + pool.chainconfig.IsMetaTxV3(pool.chain.CurrentBlock().Time)) if err != nil { invalidMetaTxs = append(invalidMetaTxs, tx) continue diff --git a/light/txpool.go b/light/txpool.go index 71958c0971..745bfbf6bb 100644 --- a/light/txpool.go +++ b/light/txpool.go @@ -379,7 +379,8 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error return txpool.ErrNegativeValue } - metaTxParams, err := types.DecodeAndVerifyMetaTxParams(tx, pool.config.IsMetaTxV2(header.Time), pool.config.IsMetaTxV3(header.Time)) + metaTxParams, err := types.DecodeAndVerifyMetaTxParams(tx, + pool.config.IsMetaTxV2(header.Time), pool.config.IsMetaTxV3(header.Time)) if err != nil { return err } diff --git a/params/config.go b/params/config.go index f980752e6c..882f3d4a47 100644 --- a/params/config.go +++ b/params/config.go @@ -462,8 +462,8 @@ type ChainConfig struct { BVMETHMintUpgradeTime *uint64 `json:"bvmETHMintUpgradeTime,omitempty"` // BVM_ETH mint upgrade switch time (nil = no fork, 0 = already on) // MetaTx upgrade config - MetaTxV1UpgradeTime *uint64 `json:"metaTxV1UpgradeTime,omitempty"` // MetaTxUpgradeTime switch time ( nil = no fork, 0 = already forked) - MetaTxV2UpgradeTime *uint64 `json:"metaTxV2UpgradeTime,omitempty"` // MetaTxUpgradeTime switch time ( nil = no fork, 0 = already forked) + MetaTxV2UpgradeTime *uint64 `json:"metaTxV2UpgradeTime,omitempty"` // MetaTxV2UpgradeTime switch time ( nil = no fork, 0 = already forked) + MetaTxV3UpgradeTime *uint64 `json:"metaTxV3UpgradeTime,omitempty"` // MetaTxV3UpgradeTime switch time ( nil = no fork, 0 = already forked) // Fork scheduling was switched from blocks to timestamps here @@ -689,12 +689,12 @@ func (c *ChainConfig) IsMantleBVMETHMintUpgrade(time uint64) bool { // IsMetaTxV2 returns whether time is either equal to the MetaTx fork time or greater. func (c *ChainConfig) IsMetaTxV2(time uint64) bool { - return isTimestampForked(c.MetaTxV1UpgradeTime, time) + return isTimestampForked(c.MetaTxV2UpgradeTime, time) } // IsMetaTxV3 returns whether time is either equal to the MetaTx fork time or greater. func (c *ChainConfig) IsMetaTxV3(time uint64) bool { - return isTimestampForked(c.MetaTxV2UpgradeTime, time) + return isTimestampForked(c.MetaTxV3UpgradeTime, time) } // IsArrowGlacier returns whether num is either equal to the Arrow Glacier (EIP-4345) fork block or greater. From 3c17af41c13d1d8a0a2fe580c8f4913f070ec93d Mon Sep 17 00:00:00 2001 From: liuhaoyang Date: Tue, 9 Apr 2024 14:50:48 +0800 Subject: [PATCH 03/12] fix relaced tx cost --- core/txpool/txpool.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/txpool/txpool.go b/core/txpool/txpool.go index 07519706bd..6cb05e8ca6 100644 --- a/core/txpool/txpool.go +++ b/core/txpool/txpool.go @@ -737,7 +737,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { // Deduct the cost of a transaction replaced by this replCost := repl.Cost() if replL1Cost := pool.l1CostFn(repl.RollupDataGas(), repl.IsDepositTx(), repl.To()); replL1Cost != nil { // add rollup cost - replCost = replCost.Add(cost, replL1Cost) + replCost = replCost.Add(replCost, replL1Cost) } replMetaTxParams, err := types.DecodeAndVerifyMetaTxParams(repl, pool.chainconfig.IsMetaTxV2(pool.chain.CurrentBlock().Time), From 12250d0ab2bd41e7aa161d8d00e413d4e6783486 Mon Sep 17 00:00:00 2001 From: liuhaoyang Date: Thu, 11 Apr 2024 16:00:42 +0800 Subject: [PATCH 04/12] generate sponsor event --- core/state_transition.go | 44 ++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/core/state_transition.go b/core/state_transition.go index fe204b8342..61b88e70d9 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -33,7 +33,8 @@ import ( ) var ( - BVM_ETH_ADDR = common.HexToAddress("0xdEAddEaDdeadDEadDEADDEAddEADDEAddead1111") + BVM_ETH_ADDR = common.HexToAddress("0xdEAddEaDdeadDEadDEADDEAddEADDEAddead1111") + LEGACY_ERC20_MNT = common.HexToAddress("0xdEAddEaDdeadDEadDEADDEAddEADDEAddead0000") ) // ExecutionResult includes all output after executing given evm @@ -265,15 +266,18 @@ type StateTransition struct { initialGas uint64 state vm.StateDB evm *vm.EVM + + initialSponsorValue *big.Int } // NewStateTransition initialises and returns a new state transition object. func NewStateTransition(evm *vm.EVM, msg *Message, gp *GasPool) *StateTransition { return &StateTransition{ - gp: gp, - evm: evm, - msg: msg, - state: evm.StateDB, + gp: gp, + evm: evm, + msg: msg, + state: evm.StateDB, + initialSponsorValue: big.NewInt(0), } } @@ -342,6 +346,7 @@ func (st *StateTransition) buyGas() (*big.Int, error) { if st.msg.RunMode != GasEstimationWithSkipCheckBalanceMode && st.msg.RunMode != EthcallMode { if st.msg.MetaTxParams != nil { sponsorAmount, selfPayAmount := types.CalculateSponsorPercentAmount(st.msg.MetaTxParams, mgval) + st.initialSponsorValue = sponsorAmount st.state.SubBalance(st.msg.MetaTxParams.GasFeeSponsor, sponsorAmount) st.state.SubBalance(st.msg.From, selfPayAmount) log.Debug("BuyGas for metaTx", @@ -599,10 +604,10 @@ func (st *StateTransition) innerTransitionDb() (*ExecutionResult, error) { if !st.msg.IsDepositTx && !st.msg.IsSystemTx { if !rules.IsLondon { // Before EIP-3529: refunds were capped to gasUsed / 2 - st.refundGas(params.RefundQuotient, tokenRatio) + st.refundGas(params.RefundQuotient, tokenRatio, rules) } else { // After EIP-3529: refunds are capped to gasUsed / 5 - st.refundGas(params.RefundQuotientEIP3529, tokenRatio) + st.refundGas(params.RefundQuotientEIP3529, tokenRatio, rules) } } @@ -646,7 +651,7 @@ func (st *StateTransition) innerTransitionDb() (*ExecutionResult, error) { }, nil } -func (st *StateTransition) refundGas(refundQuotient, tokenRatio uint64) { +func (st *StateTransition) refundGas(refundQuotient, tokenRatio uint64, rules params.Rules) { if st.msg.RunMode == GasEstimationWithSkipCheckBalanceMode || st.msg.RunMode == EthcallMode { st.gasRemaining = st.gasRemaining * tokenRatio st.gp.AddGas(st.gasRemaining) @@ -666,6 +671,10 @@ func (st *StateTransition) refundGas(refundQuotient, tokenRatio uint64) { sponsorRefundAmount, selfRefundAmount := types.CalculateSponsorPercentAmount(st.msg.MetaTxParams, remaining) st.state.AddBalance(st.msg.MetaTxParams.GasFeeSponsor, sponsorRefundAmount) st.state.AddBalance(st.msg.From, selfRefundAmount) + if rules.IsMetaTxV3 { + actualSponsorValue := new(big.Int).Sub(st.initialSponsorValue, sponsorRefundAmount) + st.generateMetaTxSponsorEvent(st.msg.MetaTxParams.GasFeeSponsor, st.msg.From, actualSponsorValue) + } log.Debug("RefundGas for metaTx", "sponsor", st.msg.MetaTxParams.GasFeeSponsor.String(), "refundAmount", sponsorRefundAmount.String(), "user", st.msg.From.String(), "refundAmount", selfRefundAmount.String()) @@ -806,3 +815,22 @@ func (st *StateTransition) generateBVMETHTransferEvent(from, to common.Address, BlockNumber: st.evm.Context.BlockNumber.Uint64(), }) } + +func (st *StateTransition) generateMetaTxSponsorEvent(sponsor, txSender common.Address, actualSponsorAmount *big.Int) { + // keccak("MetaTxSponsor(address,address,uint256)") = "0xe57e5af44e0b977ac446043abcb6b8958c04a1004c91d7342e2870761b21af95" + methodHash := common.HexToHash("0xe57e5af44e0b977ac446043abcb6b8958c04a1004c91d7342e2870761b21af95") + topics := make([]common.Hash, 2) + topics[0] = methodHash + topics[1] = sponsor.Hash() + topics[1] = txSender.Hash() + //data means the sponsor amount in MetaTxSponsor EVENT. + d := common.HexToHash(common.Bytes2Hex(actualSponsorAmount.Bytes())).Bytes() + st.evm.StateDB.AddLog(&types.Log{ + Address: LEGACY_ERC20_MNT, + Topics: topics, + Data: d, + // This is a non-consensus field, but assigned here because + // core/state doesn't know the current block number. + BlockNumber: st.evm.Context.BlockNumber.Uint64(), + }) +} From 757949a46563a70311b41fc12a52c4dbcb31a487 Mon Sep 17 00:00:00 2001 From: pandainzoo Date: Tue, 21 May 2024 17:50:24 +0800 Subject: [PATCH 05/12] bugfix: metatx gas undercharge && estimate insufficient Signed-off-by: pandainzoo --- core/state_transition.go | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/core/state_transition.go b/core/state_transition.go index 61b88e70d9..6b04c4ec65 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -224,6 +224,11 @@ func (st *StateTransition) CalculateRollupGasDataFromMessage() { // 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 // just used for estimateGas and the actual L1 cost depends on users' tx when executing st.msg.RollupDataGas.Ones += 80 + + // add a constant to cover meta tx sigs(V,R,S) + if st.msg.MetaTxParams != nil { + st.msg.RollupDataGas.Ones += 80 + } } // ApplyMessage computes the new state by applying the given message @@ -289,10 +294,13 @@ func (st *StateTransition) to() common.Address { return *st.msg.To } -func (st *StateTransition) buyGas() (*big.Int, error) { - if err := st.applyMetaTransaction(); err != nil { - return nil, err +func (st *StateTransition) buyGas(metaTxV3 bool) (*big.Int, error) { + if !metaTxV3 { + if err := st.applyMetaTransaction(); err != nil { + return nil, err + } } + mgval := new(big.Int).SetUint64(st.msg.GasLimit) mgval = mgval.Mul(mgval, st.msg.GasPrice) var l1Cost *big.Int @@ -371,7 +379,7 @@ func (st *StateTransition) applyMetaTransaction() error { return nil } -func (st *StateTransition) preCheck() (*big.Int, error) { +func (st *StateTransition) preCheck(metaTxV3 bool) (*big.Int, error) { if st.msg.IsDepositTx { // No fee fields to check, no nonce to check, and no need to check if EOA (L1 already verified it for us) // Gas is free, but no refunds! @@ -437,7 +445,7 @@ func (st *StateTransition) preCheck() (*big.Int, error) { } } } - return st.buyGas() + return st.buyGas(metaTxV3) } // TransitionDb will transition the state by applying the current message and @@ -510,7 +518,7 @@ func (st *StateTransition) innerTransitionDb() (*ExecutionResult, error) { // Check clauses 1-3, buy gas if everything is correct tokenRatio := st.state.GetState(types.GasOracleAddr, types.TokenRatioSlot).Big().Uint64() - l1Cost, err := st.preCheck() + l1Cost, err := st.preCheck(rules.IsMetaTxV3) if err != nil { return nil, err } @@ -534,6 +542,13 @@ func (st *StateTransition) innerTransitionDb() (*ExecutionResult, error) { return nil, err } + // after calculate intrinsic gas, apply meta tx data + if rules.IsMetaTxV3 { + if err := st.applyMetaTransaction(); err != nil { + return nil, err + } + } + if !st.msg.IsDepositTx && !st.msg.IsSystemTx { gas = gas * tokenRatio } From a72614df0c0871fa6855e30ffe6f40de66e196e1 Mon Sep 17 00:00:00 2001 From: pandainzoo Date: Mon, 27 May 2024 16:11:57 +0800 Subject: [PATCH 06/12] add testnet network upgrade config Signed-off-by: pandainzoo --- core/mantle_upgrade.go | 11 ++++++++++- core/state_transition.go | 2 +- params/config.go | 7 ++++--- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/core/mantle_upgrade.go b/core/mantle_upgrade.go index 62fa6a2e74..4b20bc60a4 100644 --- a/core/mantle_upgrade.go +++ b/core/mantle_upgrade.go @@ -22,6 +22,13 @@ var ( MetaTxV2UpgradeTime: nil, //TODO set upgrade timestamp MetaTxV3UpgradeTime: nil, //TODO set upgrade timestamp } + MantleSepoliaQA9UpgradeConfig = MantleUpgradeChainConfig{ + ChainID: params.MantleSepoliaQA9ChainId, + BaseFeeTime: u64Ptr(0), + BVMETHMintUpgradeTime: u64Ptr(0), + MetaTxV2UpgradeTime: u64Ptr(0), + MetaTxV3UpgradeTime: u64Ptr(1716998400), + } MantleLocalUpgradeConfig = MantleUpgradeChainConfig{ ChainID: params.MantleLocalChainId, BaseFeeTime: u64Ptr(0), @@ -33,7 +40,7 @@ var ( BaseFeeTime: u64Ptr(0), BVMETHMintUpgradeTime: u64Ptr(0), MetaTxV2UpgradeTime: u64Ptr(0), - MetaTxV3UpgradeTime: u64Ptr(0), + MetaTxV3UpgradeTime: nil, } ) @@ -55,6 +62,8 @@ func GetUpgradeConfigForMantle(chainID *big.Int) *MantleUpgradeChainConfig { return &MantleMainnetUpgradeConfig case params.MantleSepoliaChainId.Int64(): return &MantleSepoliaUpgradeConfig + case params.MantleSepoliaQA9ChainId.Int64(): + return &MantleSepoliaQA9UpgradeConfig case params.MantleLocalChainId.Int64(): return &MantleLocalUpgradeConfig default: diff --git a/core/state_transition.go b/core/state_transition.go index 6b04c4ec65..217263ad9d 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -357,7 +357,7 @@ func (st *StateTransition) buyGas(metaTxV3 bool) (*big.Int, error) { st.initialSponsorValue = sponsorAmount st.state.SubBalance(st.msg.MetaTxParams.GasFeeSponsor, sponsorAmount) st.state.SubBalance(st.msg.From, selfPayAmount) - log.Debug("BuyGas for metaTx", + log.Debug("BuyGas for metaTx", "v3", metaTxV3, "sponsor", st.msg.MetaTxParams.GasFeeSponsor.String(), "amount", sponsorAmount.String(), "user", st.msg.From.String(), "amount", selfPayAmount.String()) } else { diff --git a/params/config.go b/params/config.go index 882f3d4a47..53382d593c 100644 --- a/params/config.go +++ b/params/config.go @@ -44,9 +44,10 @@ var ( BaseGoerliRegolithTime = uint64(1682614800) // Mantle chain_id - MantleMainnetChainId = big.NewInt(5000) - MantleSepoliaChainId = big.NewInt(5003) - MantleLocalChainId = big.NewInt(17) + MantleMainnetChainId = big.NewInt(5000) + MantleSepoliaChainId = big.NewInt(5003) + MantleSepoliaQA9ChainId = big.NewInt(5003009) + MantleLocalChainId = big.NewInt(17) ) // TrustedCheckpoints associates each known checkpoint with the genesis hash of From efd624e08c26948824ca3e23e936983a600b7dee Mon Sep 17 00:00:00 2001 From: pandainzoo Date: Tue, 28 May 2024 17:05:17 +0800 Subject: [PATCH 07/12] modify testnet upgrade time Signed-off-by: pandainzoo --- core/mantle_upgrade.go | 2 +- core/types/meta_transaction.go | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/mantle_upgrade.go b/core/mantle_upgrade.go index 4b20bc60a4..8c3ba86eb4 100644 --- a/core/mantle_upgrade.go +++ b/core/mantle_upgrade.go @@ -27,7 +27,7 @@ var ( BaseFeeTime: u64Ptr(0), BVMETHMintUpgradeTime: u64Ptr(0), MetaTxV2UpgradeTime: u64Ptr(0), - MetaTxV3UpgradeTime: u64Ptr(1716998400), + MetaTxV3UpgradeTime: u64Ptr(1716962400), } MantleLocalUpgradeConfig = MantleUpgradeChainConfig{ ChainID: params.MantleLocalChainId, diff --git a/core/types/meta_transaction.go b/core/types/meta_transaction.go index 6d32661670..811a02f2df 100644 --- a/core/types/meta_transaction.go +++ b/core/types/meta_transaction.go @@ -105,7 +105,7 @@ func DecodeMetaTxParams(txData []byte) (*MetaTxParams, error) { return &metaTxParams, nil } -func DecodeAndVerifyMetaTxParams(tx *Transaction, isMetaTxV1Upgraded, isMetaTxV2Upgraded bool) (*MetaTxParams, error) { +func DecodeAndVerifyMetaTxParams(tx *Transaction, isMetaTxV2, isMetaTxV3 bool) (*MetaTxParams, error) { if tx.Type() != DynamicFeeTxType { return nil, nil } @@ -129,11 +129,11 @@ func DecodeAndVerifyMetaTxParams(tx *Transaction, isMetaTxV1Upgraded, isMetaTxV2 return nil, nil } - if err = checkSponsorSignature(tx, metaTxParams, isMetaTxV1Upgraded); err != nil { + if err = checkSponsorSignature(tx, metaTxParams, isMetaTxV2); err != nil { return nil, err } - if isMetaTxV2Upgraded { + if isMetaTxV3 { txSender, err := Sender(LatestSignerForChainID(tx.ChainId()), tx) if err != nil { return nil, err @@ -150,7 +150,7 @@ func DecodeAndVerifyMetaTxParams(tx *Transaction, isMetaTxV1Upgraded, isMetaTxV2 return metaTxParams, nil } -func checkSponsorSignature(tx *Transaction, metaTxParams *MetaTxParams, isMetaTxUpgraded bool) error { +func checkSponsorSignature(tx *Transaction, metaTxParams *MetaTxParams, isMetaTxV2 bool) error { var ( txSender, gasFeeSponsorSigner common.Address err error @@ -161,7 +161,7 @@ func checkSponsorSignature(tx *Transaction, metaTxParams *MetaTxParams, isMetaTx return err } - if isMetaTxUpgraded { + if isMetaTxV2 { metaTxSignData := &MetaTxSignDataV2{ From: txSender, ChainID: tx.ChainId(), From 8c7b120322575e4b06a5cf9119fad9b4c0061071 Mon Sep 17 00:00:00 2001 From: pandainzoo Date: Tue, 28 May 2024 18:24:17 +0800 Subject: [PATCH 08/12] fix metatx event Signed-off-by: pandainzoo --- core/state_transition.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/state_transition.go b/core/state_transition.go index 217263ad9d..47576fa3ec 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -834,10 +834,10 @@ func (st *StateTransition) generateBVMETHTransferEvent(from, to common.Address, func (st *StateTransition) generateMetaTxSponsorEvent(sponsor, txSender common.Address, actualSponsorAmount *big.Int) { // keccak("MetaTxSponsor(address,address,uint256)") = "0xe57e5af44e0b977ac446043abcb6b8958c04a1004c91d7342e2870761b21af95" methodHash := common.HexToHash("0xe57e5af44e0b977ac446043abcb6b8958c04a1004c91d7342e2870761b21af95") - topics := make([]common.Hash, 2) + topics := make([]common.Hash, 3) topics[0] = methodHash topics[1] = sponsor.Hash() - topics[1] = txSender.Hash() + topics[2] = txSender.Hash() //data means the sponsor amount in MetaTxSponsor EVENT. d := common.HexToHash(common.Bytes2Hex(actualSponsorAmount.Bytes())).Bytes() st.evm.StateDB.AddLog(&types.Log{ From be781ff5e69b7184b9ad8455badd9ca0549f4754 Mon Sep 17 00:00:00 2001 From: pandainzoo Date: Wed, 29 May 2024 17:37:02 +0800 Subject: [PATCH 09/12] fix metatx estimate Signed-off-by: pandainzoo --- internal/ethapi/api.go | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 529f07314e..9282996f23 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1279,18 +1279,25 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr available.Sub(available, args.Value.ToInt()) } + allowance := new(big.Int).Div(available, feeCap) + if metaTxParams != nil { - sponsorAmount, _ := types.CalculateSponsorPercentAmount(metaTxParams, new(big.Int).Mul(feeCap, new(big.Int).SetUint64(hi))) sponsorBalance := state.GetBalance(metaTxParams.GasFeeSponsor) - if sponsorAmount.Cmp(sponsorBalance) < 0 { - available.Add(available, sponsorAmount) + sponsorAllowance := new(big.Int).Div(sponsorBalance, feeCap) + if metaTxParams.SponsorPercent == types.OneHundredPercent { + allowance = sponsorAllowance } else { - available.Add(available, sponsorBalance) + // calculate sponsor & from allowance with sponsorPercent, use min value as allowance + fromAllowanceWithSponsorPercent := calculateGasAllowanceWithSponsorPercent(allowance, types.OneHundredPercent-metaTxParams.SponsorPercent) + sponsorAllowanceWithSponsorPercent := calculateGasAllowanceWithSponsorPercent(sponsorAllowance, metaTxParams.SponsorPercent) + if sponsorAllowanceWithSponsorPercent.Cmp(fromAllowanceWithSponsorPercent) < 0 { + allowance = sponsorAllowanceWithSponsorPercent + } else { + allowance = fromAllowanceWithSponsorPercent + } } } - allowance := new(big.Int).Div(available, feeCap) - // If the allowance is larger than maximum uint64, skip checking // If the runMode is core.GasEstimationWithSkipCheckBalanceMode, skip checking if runMode != core.GasEstimationWithSkipCheckBalanceMode && allowance.IsUint64() && hi > allowance.Uint64() { @@ -1388,6 +1395,12 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr return hexutil.Uint64(hi * gasBuffer / 100), nil } +func calculateGasAllowanceWithSponsorPercent(allowance *big.Int, sponsorPercent uint64) *big.Int { + allowance.Div(allowance, big.NewInt(0).SetUint64(sponsorPercent)) + allowance.Mul(allowance, big.NewInt(0).SetUint64(types.OneHundredPercent)) + return allowance +} + func calculateGasWithAllowance(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, gasPriceForEstimate *big.Int, gasCap uint64) (uint64, error) { state, _, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) if err != nil { From d7cdd5ee48da0921567c7d05022d2f83c6159fa9 Mon Sep 17 00:00:00 2001 From: pandainzoo Date: Thu, 30 May 2024 12:13:18 +0800 Subject: [PATCH 10/12] fix estimate gas Signed-off-by: pandainzoo --- internal/ethapi/api.go | 6 +----- internal/ethapi/transaction_args.go | 23 ++--------------------- 2 files changed, 3 insertions(+), 26 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 9282996f23..6ba14947e8 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1290,11 +1290,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr // calculate sponsor & from allowance with sponsorPercent, use min value as allowance fromAllowanceWithSponsorPercent := calculateGasAllowanceWithSponsorPercent(allowance, types.OneHundredPercent-metaTxParams.SponsorPercent) sponsorAllowanceWithSponsorPercent := calculateGasAllowanceWithSponsorPercent(sponsorAllowance, metaTxParams.SponsorPercent) - if sponsorAllowanceWithSponsorPercent.Cmp(fromAllowanceWithSponsorPercent) < 0 { - allowance = sponsorAllowanceWithSponsorPercent - } else { - allowance = fromAllowanceWithSponsorPercent - } + allowance = math.BigMin(sponsorAllowanceWithSponsorPercent, fromAllowanceWithSponsorPercent) } } diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go index 976839f48b..dec61b6352 100644 --- a/internal/ethapi/transaction_args.go +++ b/internal/ethapi/transaction_args.go @@ -258,27 +258,8 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int, ru // use suggested gasPrice for estimateGas to calculate gasUsed if runMode == core.GasEstimationMode || runMode == core.GasEstimationWithSkipCheckBalanceMode { - // use default gasPrice if user does not set gasPrice or gasPrice is 0 - if args.GasPrice == nil || gasPrice.Cmp(common.Big0) == 0 { - gasPrice = gasPriceForEstimate.ToInt() - } - // use gasTipCap to set gasFeeCap - if args.MaxFeePerGas == nil && args.MaxPriorityFeePerGas != nil { - gasFeeCap = args.MaxPriorityFeePerGas.ToInt() - } - // use gasFeeCap to set gasTipCap - if args.MaxPriorityFeePerGas == nil && args.MaxFeePerGas != nil { - gasTipCap = args.MaxFeePerGas.ToInt() - } - // use default gasPrice to set gasFeeCap & gasTipCap if user set gasPrice - if args.GasPrice != nil { - gasFeeCap = gasPrice - gasTipCap = gasPrice - } - // use default gasPrice to set gasFeeCap & gasTipCap if user does not set any value - if args.MaxFeePerGas == nil && args.MaxPriorityFeePerGas == nil && args.GasPrice == nil { - gasFeeCap = gasPriceForEstimate.ToInt() - gasTipCap = gasPriceForEstimate.ToInt() + if gasPrice.BitLen() == 0 && gasFeeCap.BitLen() == 0 && gasTipCap.BitLen() == 0 { + gasPrice, gasFeeCap, gasTipCap = gasPriceForEstimate.ToInt(), gasPriceForEstimate.ToInt(), gasPriceForEstimate.ToInt() } } From 294678fe7c698dde3e63aff2cb1cfa73a727d104 Mon Sep 17 00:00:00 2001 From: pandainzoo Date: Fri, 31 May 2024 18:17:52 +0800 Subject: [PATCH 11/12] fix estimate gas Signed-off-by: pandainzoo --- core/state_transition.go | 7 +------ internal/ethapi/transaction_args.go | 4 ++++ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/core/state_transition.go b/core/state_transition.go index 47576fa3ec..66ebfa39b8 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -310,17 +310,12 @@ func (st *StateTransition) buyGas(metaTxV3 bool) (*big.Int, error) { if st.evm.Context.L1CostFunc != nil && st.msg.RunMode != EthcallMode { l1Cost = st.evm.Context.L1CostFunc(st.evm.Context.BlockNumber.Uint64(), st.evm.Context.Time, st.msg.RollupDataGas, st.msg.IsDepositTx, st.msg.To) } - if l1Cost != nil && (st.msg.RunMode == GasEstimationMode || st.msg.RunMode == GasEstimationWithSkipCheckBalanceMode) { - mgval = mgval.Add(mgval, l1Cost) - } + balanceCheck := new(big.Int).Set(mgval) if st.msg.GasFeeCap != nil { balanceCheck.SetUint64(st.msg.GasLimit) balanceCheck = balanceCheck.Mul(balanceCheck, st.msg.GasFeeCap) balanceCheck.Add(balanceCheck, st.msg.Value) - if l1Cost != nil && st.msg.RunMode == GasEstimationMode { - balanceCheck.Add(balanceCheck, l1Cost) - } } if st.msg.RunMode != GasEstimationWithSkipCheckBalanceMode && st.msg.RunMode != EthcallMode { if st.msg.MetaTxParams != nil { diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go index dec61b6352..181fa464e4 100644 --- a/internal/ethapi/transaction_args.go +++ b/internal/ethapi/transaction_args.go @@ -258,8 +258,12 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int, ru // use suggested gasPrice for estimateGas to calculate gasUsed if runMode == core.GasEstimationMode || runMode == core.GasEstimationWithSkipCheckBalanceMode { + // user don't set price, set all price to min value if gasPrice.BitLen() == 0 && gasFeeCap.BitLen() == 0 && gasTipCap.BitLen() == 0 { gasPrice, gasFeeCap, gasTipCap = gasPriceForEstimate.ToInt(), gasPriceForEstimate.ToInt(), gasPriceForEstimate.ToInt() + } else if args.GasPrice == nil { + // eip1559 tx, use min value as gas price + gasPrice = gasPriceForEstimate.ToInt() } } From 8d737a8ea76e442e5d2e087794726aa6566e437a Mon Sep 17 00:00:00 2001 From: pandainzoo Date: Thu, 6 Jun 2024 16:16:48 +0800 Subject: [PATCH 12/12] add qa3 upgrade info Signed-off-by: pandainzoo --- core/mantle_upgrade.go | 9 +++++++++ params/config.go | 1 + 2 files changed, 10 insertions(+) diff --git a/core/mantle_upgrade.go b/core/mantle_upgrade.go index 8c3ba86eb4..5b85483604 100644 --- a/core/mantle_upgrade.go +++ b/core/mantle_upgrade.go @@ -22,6 +22,13 @@ var ( MetaTxV2UpgradeTime: nil, //TODO set upgrade timestamp MetaTxV3UpgradeTime: nil, //TODO set upgrade timestamp } + MantleSepoliaQA3UpgradeConfig = MantleUpgradeChainConfig{ + ChainID: params.MantleSepoliaQA3ChainId, + BaseFeeTime: u64Ptr(0), + BVMETHMintUpgradeTime: u64Ptr(0), + MetaTxV2UpgradeTime: u64Ptr(0), + MetaTxV3UpgradeTime: u64Ptr(1717689600), + } MantleSepoliaQA9UpgradeConfig = MantleUpgradeChainConfig{ ChainID: params.MantleSepoliaQA9ChainId, BaseFeeTime: u64Ptr(0), @@ -62,6 +69,8 @@ func GetUpgradeConfigForMantle(chainID *big.Int) *MantleUpgradeChainConfig { return &MantleMainnetUpgradeConfig case params.MantleSepoliaChainId.Int64(): return &MantleSepoliaUpgradeConfig + case params.MantleSepoliaQA3ChainId.Int64(): + return &MantleSepoliaQA3UpgradeConfig case params.MantleSepoliaQA9ChainId.Int64(): return &MantleSepoliaQA9UpgradeConfig case params.MantleLocalChainId.Int64(): diff --git a/params/config.go b/params/config.go index 53382d593c..0de4c101d8 100644 --- a/params/config.go +++ b/params/config.go @@ -46,6 +46,7 @@ var ( // Mantle chain_id MantleMainnetChainId = big.NewInt(5000) MantleSepoliaChainId = big.NewInt(5003) + MantleSepoliaQA3ChainId = big.NewInt(5003003) MantleSepoliaQA9ChainId = big.NewInt(5003009) MantleLocalChainId = big.NewInt(17) )