diff --git a/accounts/external/backend.go b/accounts/external/backend.go
index 49b5f2e934..28c6dccabb 100644
--- a/accounts/external/backend.go
+++ b/accounts/external/backend.go
@@ -215,7 +215,7 @@ func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transactio
switch tx.Type() {
case types.LegacyTxType, types.AccessListTxType:
args.GasPrice = (*hexutil.Big)(tx.GasPrice())
- case types.DynamicFeeTxType, types.CeloDynamicFeeTxType, types.CeloDenominatedTxType:
+ case types.DynamicFeeTxType, types.CeloDynamicFeeTxV2Type, types.CeloDenominatedTxType:
args.MaxFeePerGas = (*hexutil.Big)(tx.GasFeeCap())
args.MaxPriorityFeePerGas = (*hexutil.Big)(tx.GasTipCap())
default:
diff --git a/core/blockchain_celo_test.go b/core/blockchain_celo_test.go
index 6b2724bfef..ec5c8eadac 100644
--- a/core/blockchain_celo_test.go
+++ b/core/blockchain_celo_test.go
@@ -77,7 +77,7 @@ func testNativeTransferWithFeeCurrency(t *testing.T, scheme string, feeCurrencyA
_, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) {
b.SetCoinbase(common.Address{1})
- txdata := &types.CeloDynamicFeeTx{
+ txdata := &types.CeloDynamicFeeTxV2{
ChainID: gspec.Config.ChainID,
Nonce: 0,
To: &aa,
diff --git a/core/state_processor.go b/core/state_processor.go
index 18c1687ba5..f0f443720a 100644
--- a/core/state_processor.go
+++ b/core/state_processor.go
@@ -153,7 +153,7 @@ func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, sta
*receipt.DepositReceiptVersion = types.CanyonDepositReceiptVersion
}
}
- if tx.Type() == types.CeloDynamicFeeTxType {
+ if tx.Type() == types.CeloDynamicFeeTxV2Type {
alternativeBaseFee := evm.Context.BaseFee
if msg.FeeCurrency != nil {
alternativeBaseFee, err = exchange.ConvertCeloToCurrency(evm.Context.ExchangeRates, msg.FeeCurrency, evm.Context.BaseFee)
diff --git a/core/state_transition.go b/core/state_transition.go
index ba8ac4074d..289692ff34 100644
--- a/core/state_transition.go
+++ b/core/state_transition.go
@@ -212,7 +212,7 @@ func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.In
}
// If baseFee provided, set gasPrice to effectiveGasPrice.
if baseFee != nil {
- if tx.Type() == types.CeloDynamicFeeTxType {
+ if tx.Type() == types.CeloDynamicFeeTxV2Type {
var err error
baseFee, err = exchange.ConvertCeloToCurrency(exchangeRates, msg.FeeCurrency, baseFee)
if err != nil {
diff --git a/core/txpool/legacypool/celo_list_test.go b/core/txpool/legacypool/celo_list_test.go
index 5cba5966b0..31b6741c34 100644
--- a/core/txpool/legacypool/celo_list_test.go
+++ b/core/txpool/legacypool/celo_list_test.go
@@ -11,7 +11,7 @@ import (
)
func txC(nonce int, feeCap int, tipCap int, gas int, currency *common.Address) *types.Transaction {
- return types.NewTx(&types.CeloDynamicFeeTx{
+ return types.NewTx(&types.CeloDynamicFeeTxV2{
GasFeeCap: big.NewInt(int64(feeCap)),
GasTipCap: big.NewInt(int64(tipCap)),
FeeCurrency: currency,
diff --git a/core/txpool/legacypool/legacypool.go b/core/txpool/legacypool/legacypool.go
index 7abd75203a..0facd29673 100644
--- a/core/txpool/legacypool/legacypool.go
+++ b/core/txpool/legacypool/legacypool.go
@@ -290,7 +290,7 @@ func New(config Config, chain BlockChain) *LegacyPool {
// pool, specifically, whether it is a Legacy, AccessList or Dynamic transaction.
func (pool *LegacyPool) Filter(tx *types.Transaction) bool {
switch tx.Type() {
- case types.LegacyTxType, types.AccessListTxType, types.DynamicFeeTxType, types.CeloDynamicFeeTxType:
+ case types.LegacyTxType, types.AccessListTxType, types.DynamicFeeTxType, types.CeloDynamicFeeTxV2Type:
return true
default:
return false
@@ -642,7 +642,7 @@ func (pool *LegacyPool) validateTxBasics(tx *types.Transaction, local bool) erro
types.LegacyTxType,
types.AccessListTxType,
types.DynamicFeeTxType,
- types.CeloDynamicFeeTxType),
+ types.CeloDynamicFeeTxV2Type),
MaxSize: txMaxSize,
MinTip: pool.gasTip.Load().ToBig(),
EffectiveGasCeil: pool.config.EffectiveGasCeil,
diff --git a/core/types/celo_denominated_tx.go b/core/types/celo_denominated_tx.go
index 977397d650..21ed9da556 100644
--- a/core/types/celo_denominated_tx.go
+++ b/core/types/celo_denominated_tx.go
@@ -8,6 +8,8 @@ import (
"github.com/ethereum/go-ethereum/rlp"
)
+const CeloDenominatedTxType = 0x7a
+
type CeloDenominatedTx struct {
ChainID *big.Int
Nonce uint64
@@ -115,7 +117,3 @@ func (tx *CeloDenominatedTx) encode(b *bytes.Buffer) error {
func (tx *CeloDenominatedTx) decode(input []byte) error {
return rlp.DecodeBytes(input, tx)
}
-
-func (tx *CeloDenominatedTx) feeCurrency() *common.Address { return tx.FeeCurrency }
-
-func (tx *CeloDenominatedTx) maxFeeInFeeCurrency() *big.Int { return tx.MaxFeeInFeeCurrency }
diff --git a/core/types/celo_dynamic_fee_tx.go b/core/types/celo_dynamic_fee_tx.go
index 800addd11e..f1fab1f4d8 100644
--- a/core/types/celo_dynamic_fee_tx.go
+++ b/core/types/celo_dynamic_fee_tx.go
@@ -1,4 +1,18 @@
-// TODO: needs copyright header?
+// Copyright 2024 The Celo Authors
+// This file is part of the celo library.
+//
+// The celo library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The celo library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the celo library. If not, see .
package types
@@ -10,19 +24,21 @@ import (
"github.com/ethereum/go-ethereum/rlp"
)
-// CeloDynamicFeeTx represents a CIP-64 transaction.
-type CeloDynamicFeeTx struct {
- ChainID *big.Int
- Nonce uint64
- GasTipCap *big.Int
- GasFeeCap *big.Int
- Gas uint64
- To *common.Address `rlp:"nil"` // nil means contract creation
- Value *big.Int
- Data []byte
- AccessList AccessList
+const CeloDynamicFeeTxType = 0x7c
- FeeCurrency *common.Address `rlp:"nil"` // nil means native currency
+type CeloDynamicFeeTx struct {
+ ChainID *big.Int
+ Nonce uint64
+ GasTipCap *big.Int
+ GasFeeCap *big.Int
+ Gas uint64
+ FeeCurrency *common.Address `rlp:"nil"` // nil means native currency
+ GatewayFeeRecipient *common.Address `rlp:"nil"` // nil means no gateway fee is paid
+ GatewayFee *big.Int `rlp:"nil"`
+ To *common.Address `rlp:"nil"` // nil means contract creation
+ Value *big.Int
+ Data []byte
+ AccessList AccessList
// Signature values
V *big.Int `json:"v" gencodec:"required"`
@@ -33,13 +49,15 @@ type CeloDynamicFeeTx struct {
// copy creates a deep copy of the transaction data and initializes all fields.
func (tx *CeloDynamicFeeTx) copy() TxData {
cpy := &CeloDynamicFeeTx{
- Nonce: tx.Nonce,
- To: copyAddressPtr(tx.To),
- Data: common.CopyBytes(tx.Data),
- Gas: tx.Gas,
- FeeCurrency: copyAddressPtr(tx.FeeCurrency),
+ Nonce: tx.Nonce,
+ To: copyAddressPtr(tx.To),
+ Data: common.CopyBytes(tx.Data),
+ Gas: tx.Gas,
+ FeeCurrency: copyAddressPtr(tx.FeeCurrency),
+ GatewayFeeRecipient: copyAddressPtr(tx.GatewayFeeRecipient),
// These are copied below.
AccessList: make(AccessList, len(tx.AccessList)),
+ GatewayFee: new(big.Int),
Value: new(big.Int),
ChainID: new(big.Int),
GasTipCap: new(big.Int),
@@ -61,6 +79,9 @@ func (tx *CeloDynamicFeeTx) copy() TxData {
if tx.GasFeeCap != nil {
cpy.GasFeeCap.Set(tx.GasFeeCap)
}
+ if tx.GatewayFee != nil {
+ cpy.GatewayFee.Set(tx.GatewayFee)
+ }
if tx.V != nil {
cpy.V.Set(tx.V)
}
@@ -113,6 +134,3 @@ func (tx *CeloDynamicFeeTx) encode(b *bytes.Buffer) error {
func (tx *CeloDynamicFeeTx) decode(input []byte) error {
return rlp.DecodeBytes(input, tx)
}
-
-func (tx *CeloDynamicFeeTx) feeCurrency() *common.Address { return tx.FeeCurrency }
-func (tx *CeloDynamicFeeTx) maxFeeInFeeCurrency() *big.Int { return nil }
diff --git a/core/types/celo_dynamic_fee_tx_v2.go b/core/types/celo_dynamic_fee_tx_v2.go
new file mode 100644
index 0000000000..45f83a5b70
--- /dev/null
+++ b/core/types/celo_dynamic_fee_tx_v2.go
@@ -0,0 +1,131 @@
+// Copyright 2024 The Celo Authors
+// This file is part of the celo library.
+//
+// The celo library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The celo library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the celo library. If not, see .
+
+package types
+
+import (
+ "bytes"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/rlp"
+)
+
+const CeloDynamicFeeTxV2Type = 0x7b
+
+// CeloDynamicFeeTxV2 represents a CIP-64 transaction.
+type CeloDynamicFeeTxV2 struct {
+ ChainID *big.Int
+ Nonce uint64
+ GasTipCap *big.Int
+ GasFeeCap *big.Int
+ Gas uint64
+ To *common.Address `rlp:"nil"` // nil means contract creation
+ Value *big.Int
+ Data []byte
+ AccessList AccessList
+
+ FeeCurrency *common.Address `rlp:"nil"` // nil means native currency
+
+ // Signature values
+ V *big.Int `json:"v" gencodec:"required"`
+ R *big.Int `json:"r" gencodec:"required"`
+ S *big.Int `json:"s" gencodec:"required"`
+}
+
+// copy creates a deep copy of the transaction data and initializes all fields.
+func (tx *CeloDynamicFeeTxV2) copy() TxData {
+ cpy := &CeloDynamicFeeTxV2{
+ Nonce: tx.Nonce,
+ To: copyAddressPtr(tx.To),
+ Data: common.CopyBytes(tx.Data),
+ Gas: tx.Gas,
+ FeeCurrency: copyAddressPtr(tx.FeeCurrency),
+ // These are copied below.
+ AccessList: make(AccessList, len(tx.AccessList)),
+ Value: new(big.Int),
+ ChainID: new(big.Int),
+ GasTipCap: new(big.Int),
+ GasFeeCap: new(big.Int),
+ V: new(big.Int),
+ R: new(big.Int),
+ S: new(big.Int),
+ }
+ copy(cpy.AccessList, tx.AccessList)
+ if tx.Value != nil {
+ cpy.Value.Set(tx.Value)
+ }
+ if tx.ChainID != nil {
+ cpy.ChainID.Set(tx.ChainID)
+ }
+ if tx.GasTipCap != nil {
+ cpy.GasTipCap.Set(tx.GasTipCap)
+ }
+ if tx.GasFeeCap != nil {
+ cpy.GasFeeCap.Set(tx.GasFeeCap)
+ }
+ if tx.V != nil {
+ cpy.V.Set(tx.V)
+ }
+ if tx.R != nil {
+ cpy.R.Set(tx.R)
+ }
+ if tx.S != nil {
+ cpy.S.Set(tx.S)
+ }
+ return cpy
+}
+
+// accessors for innerTx.
+func (tx *CeloDynamicFeeTxV2) txType() byte { return CeloDynamicFeeTxV2Type }
+func (tx *CeloDynamicFeeTxV2) chainID() *big.Int { return tx.ChainID }
+func (tx *CeloDynamicFeeTxV2) accessList() AccessList { return tx.AccessList }
+func (tx *CeloDynamicFeeTxV2) data() []byte { return tx.Data }
+func (tx *CeloDynamicFeeTxV2) gas() uint64 { return tx.Gas }
+func (tx *CeloDynamicFeeTxV2) gasFeeCap() *big.Int { return tx.GasFeeCap }
+func (tx *CeloDynamicFeeTxV2) gasTipCap() *big.Int { return tx.GasTipCap }
+func (tx *CeloDynamicFeeTxV2) gasPrice() *big.Int { return tx.GasFeeCap }
+func (tx *CeloDynamicFeeTxV2) value() *big.Int { return tx.Value }
+func (tx *CeloDynamicFeeTxV2) nonce() uint64 { return tx.Nonce }
+func (tx *CeloDynamicFeeTxV2) to() *common.Address { return tx.To }
+func (tx *CeloDynamicFeeTxV2) isSystemTx() bool { return false }
+
+func (tx *CeloDynamicFeeTxV2) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int {
+ if baseFee == nil {
+ return dst.Set(tx.GasFeeCap)
+ }
+ tip := dst.Sub(tx.GasFeeCap, baseFee)
+ if tip.Cmp(tx.GasTipCap) > 0 {
+ tip.Set(tx.GasTipCap)
+ }
+ return tip.Add(tip, baseFee)
+}
+
+func (tx *CeloDynamicFeeTxV2) rawSignatureValues() (v, r, s *big.Int) {
+ return tx.V, tx.R, tx.S
+}
+
+func (tx *CeloDynamicFeeTxV2) setSignatureValues(chainID, v, r, s *big.Int) {
+ tx.ChainID, tx.V, tx.R, tx.S = chainID, v, r, s
+}
+
+func (tx *CeloDynamicFeeTxV2) encode(b *bytes.Buffer) error {
+ return rlp.Encode(b, tx)
+}
+
+func (tx *CeloDynamicFeeTxV2) decode(input []byte) error {
+ return rlp.DecodeBytes(input, tx)
+}
diff --git a/core/types/celo_transaction.go b/core/types/celo_transaction.go
index 9cc79a7c0e..06dbd52ed4 100644
--- a/core/types/celo_transaction.go
+++ b/core/types/celo_transaction.go
@@ -1,9 +1,48 @@
+// Copyright 2024 The Celo Authors
+// This file is part of the celo library.
+//
+// The celo library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The celo library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the celo library. If not, see .
+
package types
import (
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/exchange"
)
+// FeeCurrency returns the fee currency of the transaction if there is one.
+func (tx *Transaction) FeeCurrency() *common.Address {
+ var feeCurrency *common.Address
+ switch t := tx.inner.(type) {
+ case *CeloDynamicFeeTxV2:
+ feeCurrency = t.FeeCurrency
+ }
+ return feeCurrency
+}
+
+// MaxFeeInFeeCurrency returns the maximum fee in the fee currency of the transaction if there is one.
+func (tx *Transaction) MaxFeeInFeeCurrency() *big.Int {
+ var maxFeeInFeeCurrency *big.Int
+ switch t := tx.inner.(type) {
+ case *CeloDenominatedTx:
+ maxFeeInFeeCurrency = t.MaxFeeInFeeCurrency
+ }
+ return maxFeeInFeeCurrency
+}
+
// CompareWithRates compares the effective gas price of two transactions according to the exchange rates and
// the base fees in the transactions currencies.
func CompareWithRates(a, b *Transaction, ratesAndFees *exchange.RatesAndFees) int {
@@ -17,16 +56,16 @@ func CompareWithRates(a, b *Transaction, ratesAndFees *exchange.RatesAndFees) in
}
rates := ratesAndFees.Rates
if ratesAndFees.HasBaseFee() {
- tipA := a.EffectiveGasTipValue(ratesAndFees.GetBaseFeeIn(a.inner.feeCurrency()))
- tipB := b.EffectiveGasTipValue(ratesAndFees.GetBaseFeeIn(b.inner.feeCurrency()))
- c, _ := exchange.CompareValue(rates, tipA, a.inner.feeCurrency(), tipB, b.inner.feeCurrency())
+ tipA := a.EffectiveGasTipValue(ratesAndFees.GetBaseFeeIn(a.FeeCurrency()))
+ tipB := b.EffectiveGasTipValue(ratesAndFees.GetBaseFeeIn(b.FeeCurrency()))
+ c, _ := exchange.CompareValue(rates, tipA, a.FeeCurrency(), tipB, b.FeeCurrency())
return c
}
// Compare fee caps if baseFee is not specified or effective tips are equal
feeA := a.inner.gasFeeCap()
feeB := b.inner.gasFeeCap()
- c, _ := exchange.CompareValue(rates, feeA, a.inner.feeCurrency(), feeB, b.inner.feeCurrency())
+ c, _ := exchange.CompareValue(rates, feeA, a.FeeCurrency(), feeB, b.FeeCurrency())
if c != 0 {
return c
}
@@ -34,6 +73,6 @@ func CompareWithRates(a, b *Transaction, ratesAndFees *exchange.RatesAndFees) in
// Compare tips if effective tips and fee caps are equal
tipCapA := a.inner.gasTipCap()
tipCapB := b.inner.gasTipCap()
- c, _ = exchange.CompareValue(rates, tipCapA, a.inner.feeCurrency(), tipCapB, b.inner.feeCurrency())
+ c, _ = exchange.CompareValue(rates, tipCapA, a.FeeCurrency(), tipCapB, b.FeeCurrency())
return c
}
diff --git a/core/types/celo_transaction_marshalling.go b/core/types/celo_transaction_marshalling.go
new file mode 100644
index 0000000000..109342a366
--- /dev/null
+++ b/core/types/celo_transaction_marshalling.go
@@ -0,0 +1,133 @@
+// Copyright 2024 The Celo Authors
+// This file is part of the celo library.
+//
+// The celo library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The celo library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the celo library. If not, see .
+
+package types
+
+import (
+ "encoding/json"
+ "errors"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common/hexutil"
+)
+
+func celoTransactionMarshal(tx *Transaction) ([]byte, bool, error) {
+ var enc txJSON
+ // These are set for all tx types.
+ enc.Hash = tx.Hash()
+ enc.Type = hexutil.Uint64(tx.Type())
+ switch itx := tx.inner.(type) {
+ case *CeloDynamicFeeTxV2:
+ enc.ChainID = (*hexutil.Big)(itx.ChainID)
+ enc.Nonce = (*hexutil.Uint64)(&itx.Nonce)
+ enc.To = tx.To()
+ enc.Gas = (*hexutil.Uint64)(&itx.Gas)
+ enc.MaxFeePerGas = (*hexutil.Big)(itx.GasFeeCap)
+ enc.MaxPriorityFeePerGas = (*hexutil.Big)(itx.GasTipCap)
+ enc.FeeCurrency = itx.FeeCurrency
+ enc.Value = (*hexutil.Big)(itx.Value)
+ enc.Input = (*hexutil.Bytes)(&itx.Data)
+ enc.AccessList = &itx.AccessList
+ enc.V = (*hexutil.Big)(itx.V)
+ enc.R = (*hexutil.Big)(itx.R)
+ enc.S = (*hexutil.Big)(itx.S)
+ default:
+ return nil, false, nil
+ }
+ bytes, err := json.Marshal(&enc)
+ return bytes, true, err
+}
+
+func celoTransactionUnmarshal(dec txJSON, inner *TxData) (bool, error) {
+ switch dec.Type {
+ case CeloDynamicFeeTxV2Type:
+ var itx CeloDynamicFeeTxV2
+ *inner = &itx
+ if dec.ChainID == nil {
+ return true, errors.New("missing required field 'chainId' in transaction")
+ }
+ itx.ChainID = (*big.Int)(dec.ChainID)
+ if dec.Nonce == nil {
+ return true, errors.New("missing required field 'nonce' in transaction")
+ }
+ itx.Nonce = uint64(*dec.Nonce)
+ if dec.To != nil {
+ itx.To = dec.To
+ }
+ if dec.Gas == nil {
+ return true, errors.New("missing required field 'gas' for txdata")
+ }
+ itx.Gas = uint64(*dec.Gas)
+ if dec.MaxPriorityFeePerGas == nil {
+ return true, errors.New("missing required field 'maxPriorityFeePerGas' for txdata")
+ }
+ itx.GasTipCap = (*big.Int)(dec.MaxPriorityFeePerGas)
+ if dec.MaxFeePerGas == nil {
+ return true, errors.New("missing required field 'maxFeePerGas' for txdata")
+ }
+ itx.GasFeeCap = (*big.Int)(dec.MaxFeePerGas)
+ if dec.Value == nil {
+ return true, errors.New("missing required field 'value' in transaction")
+ }
+ itx.FeeCurrency = dec.FeeCurrency
+ itx.Value = (*big.Int)(dec.Value)
+ if dec.Input == nil {
+ return true, errors.New("missing required field 'input' in transaction")
+ }
+ itx.Data = *dec.Input
+ if dec.V == nil {
+ return true, errors.New("missing required field 'v' in transaction")
+ }
+ if dec.AccessList != nil {
+ itx.AccessList = *dec.AccessList
+ }
+ itx.V = (*big.Int)(dec.V)
+ if dec.R == nil {
+ return true, errors.New("missing required field 'r' in transaction")
+ }
+ itx.R = (*big.Int)(dec.R)
+ if dec.S == nil {
+ return true, errors.New("missing required field 's' in transaction")
+ }
+ itx.S = (*big.Int)(dec.S)
+ withSignature := itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0
+ if withSignature {
+ if err := sanityCheckSignature(itx.V, itx.R, itx.S, false); err != nil {
+ return true, err
+ }
+ }
+ default:
+ return false, nil
+ }
+
+ return true, nil
+}
+
+func celoDecodeTyped(b []byte) (TxData, bool, error) {
+ var inner TxData
+ switch b[0] {
+ case CeloDenominatedTxType:
+ inner = new(CeloDenominatedTx)
+ case CeloDynamicFeeTxV2Type:
+ inner = new(CeloDynamicFeeTxV2)
+ case CeloDynamicFeeTxType:
+ inner = new(CeloDynamicFeeTx)
+ default:
+ return nil, false, nil
+ }
+ err := inner.decode(b[1:])
+ return inner, true, err
+}
diff --git a/core/types/celo_transaction_signing.go b/core/types/celo_transaction_signing.go
index 1dffdbe408..0fe6ed3eb4 100644
--- a/core/types/celo_transaction_signing.go
+++ b/core/types/celo_transaction_signing.go
@@ -1,18 +1,18 @@
-// Copyright 2016 The go-ethereum Authors
-// This file is part of the go-ethereum library.
+// Copyright 2024 The Celo Authors
+// This file is part of the celo library.
//
-// The go-ethereum library is free software: you can redistribute it and/or modify
+// The celo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
-// The go-ethereum library is distributed in the hope that it will be useful,
+// The celo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
+// along with the celo library. If not, see .
package types
@@ -36,7 +36,7 @@ func NewCel2Signer(chainId *big.Int) Signer {
}
func (s cel2Signer) Sender(tx *Transaction) (common.Address, error) {
- if tx.Type() != CeloDynamicFeeTxType && tx.Type() != CeloDenominatedTxType {
+ if tx.Type() != CeloDynamicFeeTxV2Type && tx.Type() != CeloDenominatedTxType {
return s.londonSigner.Sender(tx)
}
V, R, S := tx.RawSignatureValues()
@@ -55,7 +55,7 @@ func (s cel2Signer) Equal(s2 Signer) bool {
}
func (s cel2Signer) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big.Int, err error) {
- if tx.Type() != CeloDynamicFeeTxType && tx.Type() != CeloDenominatedTxType {
+ if tx.Type() != CeloDynamicFeeTxV2Type && tx.Type() != CeloDenominatedTxType {
return s.londonSigner.SignatureValues(tx, sig)
}
@@ -73,7 +73,7 @@ func (s cel2Signer) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big.I
// Hash returns the hash to be signed by the sender.
// It does not uniquely identify the transaction.
func (s cel2Signer) Hash(tx *Transaction) common.Hash {
- if tx.Type() == CeloDynamicFeeTxType {
+ if tx.Type() == CeloDynamicFeeTxV2Type {
return prefixedRlpHash(
tx.Type(),
[]interface{}{
diff --git a/core/types/celo_tx_legacy.go b/core/types/celo_tx_legacy.go
new file mode 100644
index 0000000000..b1ea042095
--- /dev/null
+++ b/core/types/celo_tx_legacy.go
@@ -0,0 +1,162 @@
+// Copyright 2024 The Celo Authors
+// This file is part of the celo library.
+//
+// The celo library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The celo library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the celo library. If not, see .
+
+package types
+
+import (
+ "io"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/rlp"
+)
+
+var ethCompatibleTxNumFields = 9
+
+// ethCompatibleTxRlpList is used for RLP encoding/decoding of eth-compatible transactions.
+// As such, it:
+// (a) excludes the Celo-only fields,
+// (b) doesn't need the Hash or EthCompatible fields, and
+// (c) doesn't need the `json` or `gencodec` tags
+type ethCompatibleTxRlpList struct {
+ Nonce uint64 // nonce of sender account
+ GasPrice *big.Int // wei per gas
+ Gas uint64 // gas limit
+ To *common.Address `rlp:"nil"` // nil means contract creation
+ Value *big.Int // wei amount
+ Data []byte // contract invocation input data
+ V, R, S *big.Int // signature values
+}
+
+// celoTxRlpList is used for RLP encoding/decoding of celo transactions.
+type celoTxRlpList struct {
+ Nonce uint64 // nonce of sender account
+ GasPrice *big.Int // wei per gas
+ Gas uint64 // gas limit
+ FeeCurrency *common.Address `rlp:"nil"` // nil means native currency
+ GatewayFeeRecipient *common.Address `rlp:"nil"` // nil means no gateway fee is paid
+ GatewayFee *big.Int `rlp:"nil"`
+ To *common.Address `rlp:"nil"` // nil means contract creation
+ Value *big.Int // wei amount
+ Data []byte // contract invocation input data
+ V, R, S *big.Int // signature values
+}
+
+func toEthCompatibleRlpList(tx LegacyTx) ethCompatibleTxRlpList {
+ return ethCompatibleTxRlpList{
+ Nonce: tx.Nonce,
+ GasPrice: tx.GasPrice,
+ Gas: tx.Gas,
+ To: tx.To,
+ Value: tx.Value,
+ Data: tx.Data,
+ V: tx.V,
+ R: tx.R,
+ S: tx.S,
+ }
+}
+
+func toCeloRlpList(tx LegacyTx) celoTxRlpList {
+ return celoTxRlpList{
+ Nonce: tx.Nonce,
+ GasPrice: tx.GasPrice,
+ Gas: tx.Gas,
+ To: tx.To,
+ Value: tx.Value,
+ Data: tx.Data,
+ V: tx.V,
+ R: tx.R,
+ S: tx.S,
+
+ // Celo specific fields
+ FeeCurrency: tx.FeeCurrency,
+ GatewayFeeRecipient: tx.GatewayFeeRecipient,
+ GatewayFee: tx.GatewayFee,
+ }
+}
+
+func setTxFromEthCompatibleRlpList(tx *LegacyTx, rlplist ethCompatibleTxRlpList) {
+ tx.Nonce = rlplist.Nonce
+ tx.GasPrice = rlplist.GasPrice
+ tx.Gas = rlplist.Gas
+ tx.To = rlplist.To
+ tx.Value = rlplist.Value
+ tx.Data = rlplist.Data
+ tx.V = rlplist.V
+ tx.R = rlplist.R
+ tx.S = rlplist.S
+ tx.Hash = nil // txdata.Hash is calculated and saved inside tx.Hash()
+
+ // Celo specific fields
+ tx.FeeCurrency = nil
+ tx.GatewayFeeRecipient = nil
+ tx.GatewayFee = big.NewInt(0)
+ tx.CeloLegacy = false
+}
+
+func setTxFromCeloRlpList(tx *LegacyTx, rlplist celoTxRlpList) {
+ tx.Nonce = rlplist.Nonce
+ tx.GasPrice = rlplist.GasPrice
+ tx.Gas = rlplist.Gas
+ tx.To = rlplist.To
+ tx.Value = rlplist.Value
+ tx.Data = rlplist.Data
+ tx.V = rlplist.V
+ tx.R = rlplist.R
+ tx.S = rlplist.S
+ tx.Hash = nil // txdata.Hash is calculated and saved inside tx.Hash()
+
+ // Celo specific fields
+ tx.FeeCurrency = rlplist.FeeCurrency
+ tx.GatewayFeeRecipient = rlplist.GatewayFeeRecipient
+ tx.GatewayFee = rlplist.GatewayFee
+ tx.CeloLegacy = true
+}
+
+// EncodeRLP implements rlp.Encoder
+func (tx *LegacyTx) EncodeRLP(w io.Writer) error {
+ if tx.CeloLegacy {
+ return rlp.Encode(w, toCeloRlpList(*tx))
+ } else {
+ return rlp.Encode(w, toEthCompatibleRlpList(*tx))
+ }
+}
+
+// DecodeRLP implements rlp.Decoder
+func (tx *LegacyTx) DecodeRLP(s *rlp.Stream) (err error) {
+ _, size, _ := s.Kind()
+ var raw rlp.RawValue
+ err = s.Decode(&raw)
+ if err != nil {
+ return err
+ }
+ headerSize := len(raw) - int(size)
+ numElems, err := rlp.CountValues(raw[headerSize:])
+ if err != nil {
+ return err
+ }
+ if numElems == ethCompatibleTxNumFields {
+ rlpList := ethCompatibleTxRlpList{}
+ err = rlp.DecodeBytes(raw, &rlpList)
+ setTxFromEthCompatibleRlpList(tx, rlpList)
+ } else {
+ var rlpList celoTxRlpList
+ err = rlp.DecodeBytes(raw, &rlpList)
+ setTxFromCeloRlpList(tx, rlpList)
+ }
+
+ return err
+}
diff --git a/core/types/deposit_tx.go b/core/types/deposit_tx.go
index bbfec79323..4131ee7af0 100644
--- a/core/types/deposit_tx.go
+++ b/core/types/deposit_tx.go
@@ -101,6 +101,3 @@ func (tx *DepositTx) encode(b *bytes.Buffer) error {
func (tx *DepositTx) decode(input []byte) error {
return rlp.DecodeBytes(input, tx)
}
-
-func (tx *DepositTx) feeCurrency() *common.Address { return nil }
-func (tx *DepositTx) maxFeeInFeeCurrency() *big.Int { return nil }
diff --git a/core/types/receipt.go b/core/types/receipt.go
index 69e143ff8b..5ce8302dd3 100644
--- a/core/types/receipt.go
+++ b/core/types/receipt.go
@@ -278,7 +278,7 @@ func (r *Receipt) EncodeRLP(w io.Writer) error {
func (r *Receipt) encodeTyped(data *receiptRLP, w *bytes.Buffer) error {
w.WriteByte(r.Type)
switch r.Type {
- case CeloDynamicFeeTxType:
+ case CeloDynamicFeeTxV2Type:
withBaseFee := &celoDynamicReceiptRLP{data.PostStateOrStatus, data.CumulativeGasUsed, data.Bloom, data.Logs, r.BaseFee}
return rlp.Encode(w, withBaseFee)
case DepositTxType:
@@ -362,7 +362,7 @@ func (r *Receipt) decodeTyped(b []byte) error {
}
r.Type = b[0]
return r.setFromRLP(data)
- case CeloDynamicFeeTxType:
+ case CeloDynamicFeeTxV2Type:
var data celoDynamicReceiptRLP
err := rlp.DecodeBytes(b[1:], &data)
if err != nil {
@@ -435,7 +435,7 @@ type ReceiptForStorage Receipt
func (r *ReceiptForStorage) EncodeRLP(_w io.Writer) error {
w := rlp.NewEncoderBuffer(_w)
outerList := w.List()
- if r.Type == CeloDynamicFeeTxType {
+ if r.Type == CeloDynamicFeeTxV2Type {
// Mark receipt as CeloDynamicFee receipt by starting with an empty list
listIndex := w.List()
w.ListEnd(listIndex)
@@ -455,7 +455,7 @@ func (r *ReceiptForStorage) EncodeRLP(_w io.Writer) error {
w.WriteUint64(*r.DepositReceiptVersion)
}
}
- if r.Type == CeloDynamicFeeTxType {
+ if r.Type == CeloDynamicFeeTxV2Type {
w.WriteBigInt(r.BaseFee)
}
w.ListEnd(outerList)
@@ -576,7 +576,7 @@ func (rs Receipts) EncodeIndex(i int, w *bytes.Buffer) {
switch r.Type {
case AccessListTxType, DynamicFeeTxType, BlobTxType:
rlp.Encode(w, data)
- case CeloDynamicFeeTxType:
+ case CeloDynamicFeeTxV2Type:
celoDynamicData := &celoDynamicReceiptRLP{data.PostStateOrStatus, data.CumulativeGasUsed, data.Bloom, data.Logs, r.BaseFee}
rlp.Encode(w, celoDynamicData)
case DepositTxType:
@@ -608,7 +608,7 @@ func (rs Receipts) DeriveFields(config *params.ChainConfig, hash common.Hash, nu
rs[i].Type = txs[i].Type()
rs[i].TxHash = txs[i].Hash()
// The CeloDynamicFeeTxs set the baseFee in the receipt
- if txs[i].Type() != CeloDynamicFeeTxType {
+ if txs[i].Type() != CeloDynamicFeeTxV2Type {
rs[i].EffectiveGasPrice = txs[i].inner.effectiveGasPrice(new(big.Int), baseFee)
} else {
rs[i].EffectiveGasPrice = txs[i].inner.effectiveGasPrice(new(big.Int), rs[i].BaseFee)
diff --git a/core/types/receipt_test.go b/core/types/receipt_test.go
index 25e468ec86..58c67f3790 100644
--- a/core/types/receipt_test.go
+++ b/core/types/receipt_test.go
@@ -115,7 +115,7 @@ var (
},
},
BaseFee: new(big.Int).SetUint64(1),
- Type: CeloDynamicFeeTxType,
+ Type: CeloDynamicFeeTxV2Type,
}
depositReceiptNoNonce = &Receipt{
Status: ReceiptStatusFailed,
@@ -1094,7 +1094,7 @@ func TestRoundTripReceiptForStorage(t *testing.T) {
require.Equal(t, test.rcpt.Logs, d.Logs)
require.Equal(t, test.rcpt.DepositNonce, d.DepositNonce)
require.Equal(t, test.rcpt.DepositReceiptVersion, d.DepositReceiptVersion)
- if test.rcpt.Type == CeloDynamicFeeTxType {
+ if test.rcpt.Type == CeloDynamicFeeTxV2Type {
require.Equal(t, test.rcpt.EffectiveGasPrice, d.EffectiveGasPrice)
}
})
diff --git a/core/types/transaction.go b/core/types/transaction.go
index 6db82c6430..63f313734f 100644
--- a/core/types/transaction.go
+++ b/core/types/transaction.go
@@ -50,9 +50,6 @@ const (
AccessListTxType = 0x01
DynamicFeeTxType = 0x02
BlobTxType = 0x03
- // CeloDynamicFeeTxType = 0x7c old Celo tx type with gateway fee
- CeloDynamicFeeTxType = 0x7b
- CeloDenominatedTxType = 0x7a
)
// Transaction is an Ethereum transaction.
@@ -108,10 +105,6 @@ type TxData interface {
encode(*bytes.Buffer) error
decode([]byte) error
-
- // Celo specific fields
- feeCurrency() *common.Address
- maxFeeInFeeCurrency() *big.Int
}
// EncodeRLP implements rlp.Encoder
@@ -210,16 +203,17 @@ func (tx *Transaction) decodeTyped(b []byte) (TxData, error) {
if len(b) <= 1 {
return nil, errShortTypedTx
}
+
+ if inner, isCelo, err := celoDecodeTyped(b); isCelo {
+ return inner, err
+ }
+
var inner TxData
switch b[0] {
case AccessListTxType:
inner = new(AccessListTx)
case DynamicFeeTxType:
inner = new(DynamicFeeTx)
- case CeloDynamicFeeTxType:
- inner = new(CeloDynamicFeeTx)
- case CeloDenominatedTxType:
- inner = new(CeloDenominatedTx)
case BlobTxType:
inner = new(BlobTx)
case DepositTxType:
@@ -627,21 +621,6 @@ func (tx *Transaction) WithSignature(signer Signer, sig []byte) (*Transaction, e
return &Transaction{inner: cpy, time: tx.time}, nil
}
-// FeeCurrency returns the fee currency of the transaction. Nil implies paying in CELO.
-func (tx *Transaction) FeeCurrency() *common.Address {
- return copyAddressPtr(tx.inner.feeCurrency())
-}
-
-// MaxFeeInFeeCurrency is only used to guard against very quickly changing exchange rates.
-// Txs must be discarded if MaxFeeInFeeCurrency is exceeded.
-func (tx *Transaction) MaxFeeInFeeCurrency() *big.Int {
- mfifc := tx.inner.maxFeeInFeeCurrency()
- if mfifc == nil {
- return nil
- }
- return new(big.Int).Set(mfifc)
-}
-
// Transactions implements DerivableList for transactions.
type Transactions []*Transaction
diff --git a/core/types/transaction_marshalling.go b/core/types/transaction_marshalling.go
index b800f524e9..3b68418d86 100644
--- a/core/types/transaction_marshalling.go
+++ b/core/types/transaction_marshalling.go
@@ -90,6 +90,9 @@ func (tx *txJSON) yParityValue() (*big.Int, error) {
// MarshalJSON marshals as JSON with a hash.
func (tx *Transaction) MarshalJSON() ([]byte, error) {
+ if marshalled, isCelo, err := celoTransactionMarshal(tx); isCelo {
+ return marshalled, err
+ }
var enc txJSON
// These are set for all tx types.
enc.Hash = tx.Hash()
@@ -142,21 +145,6 @@ func (tx *Transaction) MarshalJSON() ([]byte, error) {
yparity := itx.V.Uint64()
enc.YParity = (*hexutil.Uint64)(&yparity)
- case *CeloDynamicFeeTx:
- enc.ChainID = (*hexutil.Big)(itx.ChainID)
- enc.Nonce = (*hexutil.Uint64)(&itx.Nonce)
- enc.To = tx.To()
- enc.Gas = (*hexutil.Uint64)(&itx.Gas)
- enc.MaxFeePerGas = (*hexutil.Big)(itx.GasFeeCap)
- enc.MaxPriorityFeePerGas = (*hexutil.Big)(itx.GasTipCap)
- enc.FeeCurrency = tx.FeeCurrency()
- enc.Value = (*hexutil.Big)(itx.Value)
- enc.Input = (*hexutil.Bytes)(&itx.Data)
- enc.AccessList = &itx.AccessList
- enc.V = (*hexutil.Big)(itx.V)
- enc.R = (*hexutil.Big)(itx.R)
- enc.S = (*hexutil.Big)(itx.S)
-
case *BlobTx:
enc.ChainID = (*hexutil.Big)(itx.ChainID.ToBig())
enc.Nonce = (*hexutil.Uint64)(&itx.Nonce)
@@ -206,6 +194,12 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
// Decode / verify fields according to transaction type.
var inner TxData
+
+ if isCelo, err := celoTransactionUnmarshal(dec, &inner); isCelo {
+ tx.setDecoded(inner, 0)
+ return err
+ }
+
switch dec.Type {
case LegacyTxType:
var itx LegacyTx
@@ -369,63 +363,6 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
}
}
- case CeloDynamicFeeTxType:
- var itx CeloDynamicFeeTx
- inner = &itx
- if dec.ChainID == nil {
- return errors.New("missing required field 'chainId' in transaction")
- }
- itx.ChainID = (*big.Int)(dec.ChainID)
- if dec.Nonce == nil {
- return errors.New("missing required field 'nonce' in transaction")
- }
- itx.Nonce = uint64(*dec.Nonce)
- if dec.To != nil {
- itx.To = dec.To
- }
- if dec.Gas == nil {
- return errors.New("missing required field 'gas' for txdata")
- }
- itx.Gas = uint64(*dec.Gas)
- if dec.MaxPriorityFeePerGas == nil {
- return errors.New("missing required field 'maxPriorityFeePerGas' for txdata")
- }
- itx.GasTipCap = (*big.Int)(dec.MaxPriorityFeePerGas)
- if dec.MaxFeePerGas == nil {
- return errors.New("missing required field 'maxFeePerGas' for txdata")
- }
- itx.GasFeeCap = (*big.Int)(dec.MaxFeePerGas)
- if dec.Value == nil {
- return errors.New("missing required field 'value' in transaction")
- }
- itx.FeeCurrency = dec.FeeCurrency
- itx.Value = (*big.Int)(dec.Value)
- if dec.Input == nil {
- return errors.New("missing required field 'input' in transaction")
- }
- itx.Data = *dec.Input
- if dec.V == nil {
- return errors.New("missing required field 'v' in transaction")
- }
- if dec.AccessList != nil {
- itx.AccessList = *dec.AccessList
- }
- itx.V = (*big.Int)(dec.V)
- if dec.R == nil {
- return errors.New("missing required field 'r' in transaction")
- }
- itx.R = (*big.Int)(dec.R)
- if dec.S == nil {
- return errors.New("missing required field 's' in transaction")
- }
- itx.S = (*big.Int)(dec.S)
- withSignature := itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0
- if withSignature {
- if err := sanityCheckSignature(itx.V, itx.R, itx.S, false); err != nil {
- return err
- }
- }
-
case BlobTxType:
var itx BlobTx
inner = &itx
diff --git a/core/types/tx_access_list.go b/core/types/tx_access_list.go
index 618b3de863..59880b0eab 100644
--- a/core/types/tx_access_list.go
+++ b/core/types/tx_access_list.go
@@ -128,6 +128,3 @@ func (tx *AccessListTx) encode(b *bytes.Buffer) error {
func (tx *AccessListTx) decode(input []byte) error {
return rlp.DecodeBytes(input, tx)
}
-
-func (tx *AccessListTx) feeCurrency() *common.Address { return nil }
-func (tx *AccessListTx) maxFeeInFeeCurrency() *big.Int { return nil }
diff --git a/core/types/tx_blob.go b/core/types/tx_blob.go
index 728cb2b952..ceaeedb20d 100644
--- a/core/types/tx_blob.go
+++ b/core/types/tx_blob.go
@@ -237,6 +237,3 @@ func (tx *BlobTx) decode(input []byte) error {
}
return nil
}
-
-func (tx *BlobTx) feeCurrency() *common.Address { return nil }
-func (tx *BlobTx) maxFeeInFeeCurrency() *big.Int { return nil }
diff --git a/core/types/tx_dynamic_fee.go b/core/types/tx_dynamic_fee.go
index e23accb299..9c52cde577 100644
--- a/core/types/tx_dynamic_fee.go
+++ b/core/types/tx_dynamic_fee.go
@@ -124,6 +124,3 @@ func (tx *DynamicFeeTx) encode(b *bytes.Buffer) error {
func (tx *DynamicFeeTx) decode(input []byte) error {
return rlp.DecodeBytes(input, tx)
}
-
-func (tx *DynamicFeeTx) feeCurrency() *common.Address { return nil }
-func (tx *DynamicFeeTx) maxFeeInFeeCurrency() *big.Int { return nil }
diff --git a/core/types/tx_legacy.go b/core/types/tx_legacy.go
index d1489d5292..a5e30522b8 100644
--- a/core/types/tx_legacy.go
+++ b/core/types/tx_legacy.go
@@ -25,13 +25,25 @@ import (
// LegacyTx is the transaction data of the original Ethereum transactions.
type LegacyTx struct {
- Nonce uint64 // nonce of sender account
- GasPrice *big.Int // wei per gas
- Gas uint64 // gas limit
- To *common.Address `rlp:"nil"` // nil means contract creation
- Value *big.Int // wei amount
- Data []byte // contract invocation input data
- V, R, S *big.Int // signature values
+ Nonce uint64 // nonce of sender account
+ GasPrice *big.Int // wei per gas
+ Gas uint64 // gas limit
+
+ // Celo-specific fields
+ FeeCurrency *common.Address // nil means native currency
+ GatewayFeeRecipient *common.Address // nil means no gateway fee is paid
+ GatewayFee *big.Int
+
+ To *common.Address `rlp:"nil"` // nil means contract creation
+ Value *big.Int // wei amount
+ Data []byte // contract invocation input data
+ V, R, S *big.Int // signature values
+
+ // This is only used when marshaling to JSON.
+ Hash *common.Hash `rlp:"-"`
+
+ // Whether this is a celo legacy transaction (i.e. with FeeCurrency, GatewayFeeRecipient and GatewayFee)
+ CeloLegacy bool `rlp:"-"`
}
// NewTransaction creates an unsigned legacy transaction.
@@ -124,6 +136,3 @@ func (tx *LegacyTx) encode(*bytes.Buffer) error {
func (tx *LegacyTx) decode([]byte) error {
panic("decode called on LegacyTx)")
}
-
-func (tx *LegacyTx) feeCurrency() *common.Address { return nil }
-func (tx *LegacyTx) maxFeeInFeeCurrency() *big.Int { return nil }
diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go
index e67fee25f3..3594bccc10 100644
--- a/internal/ethapi/api.go
+++ b/internal/ethapi/api.go
@@ -1544,7 +1544,7 @@ func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber
result.ChainID = (*hexutil.Big)(tx.ChainId())
result.YParity = &yparity
- case types.DynamicFeeTxType, types.CeloDynamicFeeTxType, types.CeloDenominatedTxType:
+ case types.DynamicFeeTxType, types.CeloDynamicFeeTxV2Type, types.CeloDenominatedTxType:
al := tx.AccessList()
yparity := hexutil.Uint64(v.Sign())
result.Accesses = &al
diff --git a/internal/ethapi/api_test.go b/internal/ethapi/api_test.go
index adee570938..4dd2d5649d 100644
--- a/internal/ethapi/api_test.go
+++ b/internal/ethapi/api_test.go
@@ -2314,7 +2314,7 @@ func TestCeloTransaction_RoundTripRpcJSON(t *testing.T) {
}
func celoTransactionTypes(addr common.Address, config *params.ChainConfig) []types.TxData {
return []types.TxData{
- &types.CeloDynamicFeeTx{
+ &types.CeloDynamicFeeTxV2{
ChainID: config.ChainID,
Nonce: 5,
GasTipCap: big.NewInt(6),
@@ -2334,7 +2334,7 @@ func celoTransactionTypes(addr common.Address, config *params.ChainConfig) []typ
R: big.NewInt(10),
S: big.NewInt(11),
},
- &types.CeloDynamicFeeTx{
+ &types.CeloDynamicFeeTxV2{
ChainID: config.ChainID,
Nonce: 5,
GasTipCap: big.NewInt(6),
diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go
index c75be987f1..5026761ee3 100644
--- a/internal/ethapi/transaction_args.go
+++ b/internal/ethapi/transaction_args.go
@@ -556,7 +556,7 @@ func (args *TransactionArgs) toTransaction() *types.Transaction {
}
if args.FeeCurrency != nil {
if args.IsFeeCurrencyDenominated() {
- data = &types.CeloDynamicFeeTx{
+ data = &types.CeloDynamicFeeTxV2{
To: args.To,
ChainID: (*big.Int)(args.ChainID),
Nonce: uint64(*args.Nonce),