Skip to content

Commit

Permalink
Cancun Hardfork: support for new Transaction type (#12063)
Browse files Browse the repository at this point in the history
* testing block unparsing

* Pdded arsing tests for 0x3

* Adding type 0x3 to gas estimator

* Sonar cube code quality fix

---------

Co-authored-by: Prashant Yadav <[email protected]>
  • Loading branch information
2 people authored and anirudhwarrier committed Mar 1, 2024
1 parent 71998db commit 96154fe
Show file tree
Hide file tree
Showing 3 changed files with 378 additions and 31 deletions.
60 changes: 32 additions & 28 deletions core/chains/evm/gas/block_history_estimator.go
Original file line number Diff line number Diff line change
Expand Up @@ -858,42 +858,46 @@ func (b *BlockHistoryEstimator) EffectiveGasPrice(block evmtypes.Block, tx evmty
switch tx.Type {
case 0x0, 0x1:
return tx.GasPrice
case 0x2:
if block.BaseFeePerGas == nil || tx.MaxPriorityFeePerGas == nil || tx.MaxFeePerGas == nil {
b.logger.Warnw("Got transaction type 0x2 but one of the required EIP1559 fields was missing, falling back to gasPrice", "block", block, "tx", tx)
return tx.GasPrice
}
if tx.GasPrice != nil {
// Always use the gas price if provided
return tx.GasPrice
}
if tx.MaxFeePerGas.Cmp(block.BaseFeePerGas) < 0 {
b.logger.AssumptionViolationw("MaxFeePerGas >= BaseFeePerGas", "block", block, "tx", tx)
return nil
}
if tx.MaxFeePerGas.Cmp(tx.MaxPriorityFeePerGas) < 0 {
b.logger.AssumptionViolationw("MaxFeePerGas >= MaxPriorityFeePerGas", "block", block, "tx", tx)
return nil
}

// From: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md
priorityFeePerGas := tx.MaxPriorityFeePerGas
maxFeeMinusBaseFee := tx.MaxFeePerGas.Sub(block.BaseFeePerGas)
if maxFeeMinusBaseFee.Cmp(priorityFeePerGas) < 0 {
priorityFeePerGas = maxFeeMinusBaseFee
}

effectiveGasPrice := priorityFeePerGas.Add(block.BaseFeePerGas)
return effectiveGasPrice
case 0x2, 0x3:
return b.getEffectiveGasPrice(block, tx)
default:
b.logger.Warnw(fmt.Sprintf("Ignoring unknown transaction type %v", tx.Type), "block", block, "tx", tx)
return nil
}
}

func (b *BlockHistoryEstimator) getEffectiveGasPrice(block evmtypes.Block, tx evmtypes.Transaction) *assets.Wei {
if block.BaseFeePerGas == nil || tx.MaxPriorityFeePerGas == nil || tx.MaxFeePerGas == nil {
b.logger.Warnw("Got transaction type 0x2 but one of the required EIP1559 fields was missing, falling back to gasPrice", "block", block, "tx", tx)
return tx.GasPrice
}
if tx.GasPrice != nil {
// Always use the gas price if provided
return tx.GasPrice
}
if tx.MaxFeePerGas.Cmp(block.BaseFeePerGas) < 0 {
b.logger.AssumptionViolationw("MaxFeePerGas >= BaseFeePerGas", "block", block, "tx", tx)
return nil
}
if tx.MaxFeePerGas.Cmp(tx.MaxPriorityFeePerGas) < 0 {
b.logger.AssumptionViolationw("MaxFeePerGas >= MaxPriorityFeePerGas", "block", block, "tx", tx)
return nil
}

// From: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md
priorityFeePerGas := tx.MaxPriorityFeePerGas
maxFeeMinusBaseFee := tx.MaxFeePerGas.Sub(block.BaseFeePerGas)
if maxFeeMinusBaseFee.Cmp(priorityFeePerGas) < 0 {
priorityFeePerGas = maxFeeMinusBaseFee
}

effectiveGasPrice := priorityFeePerGas.Add(block.BaseFeePerGas)
return effectiveGasPrice
}

func (b *BlockHistoryEstimator) EffectiveTipCap(block evmtypes.Block, tx evmtypes.Transaction) *assets.Wei {
switch tx.Type {
case 0x2:
case 0x2, 0x3:
return tx.MaxPriorityFeePerGas
case 0x0, 0x1:
if tx.GasPrice == nil {
Expand Down
35 changes: 32 additions & 3 deletions core/chains/evm/gas/block_history_estimator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1396,7 +1396,7 @@ func TestBlockHistoryEstimator_EffectiveTipCap(t *testing.T) {
res := bhe.EffectiveTipCap(eipblock, tx)
assert.Equal(t, "42 wei", res.String())
})
t.Run("tx type 2 should calculate gas price", func(t *testing.T) {
t.Run("tx type 2 & type 3 should calculate gas price", func(t *testing.T) {
// 0x2 transaction (should use MaxPriorityFeePerGas)
tx := evmtypes.Transaction{Type: 0x2, MaxPriorityFeePerGas: assets.NewWeiI(200), MaxFeePerGas: assets.NewWeiI(250), GasLimit: 42, Hash: utils.NewHash()}
res := bhe.EffectiveTipCap(eipblock, tx)
Expand All @@ -1405,14 +1405,23 @@ func TestBlockHistoryEstimator_EffectiveTipCap(t *testing.T) {
tx = evmtypes.Transaction{Type: 0x2, GasPrice: assets.NewWeiI(400), MaxPriorityFeePerGas: assets.NewWeiI(200), MaxFeePerGas: assets.NewWeiI(350), GasLimit: 42, Hash: utils.NewHash()}
res = bhe.EffectiveTipCap(eipblock, tx)
assert.Equal(t, "200 wei", res.String())

// 0x3 transaction (should use MaxPriorityFeePerGas)
tx = evmtypes.Transaction{Type: 0x3, MaxPriorityFeePerGas: assets.NewWeiI(100), MaxFeePerGas: assets.NewWeiI(250), GasLimit: 42, Hash: utils.NewHash()}
res = bhe.EffectiveTipCap(eipblock, tx)
assert.Equal(t, "100 wei", res.String())
// 0x3 transaction (should use MaxPriorityFeePerGas, ignoring gas price)
tx = evmtypes.Transaction{Type: 0x3, GasPrice: assets.NewWeiI(400), MaxPriorityFeePerGas: assets.NewWeiI(100), MaxFeePerGas: assets.NewWeiI(350), GasLimit: 42, Hash: utils.NewHash()}
res = bhe.EffectiveTipCap(eipblock, tx)
assert.Equal(t, "100 wei", res.String())
})
t.Run("missing field returns nil", func(t *testing.T) {
tx := evmtypes.Transaction{Type: 0x2, GasPrice: assets.NewWeiI(132), MaxFeePerGas: assets.NewWeiI(200), GasLimit: 42, Hash: utils.NewHash()}
res := bhe.EffectiveTipCap(eipblock, tx)
assert.Nil(t, res)
})
t.Run("unknown type returns nil", func(t *testing.T) {
tx := evmtypes.Transaction{Type: 0x3, GasPrice: assets.NewWeiI(55555), MaxPriorityFeePerGas: assets.NewWeiI(200), MaxFeePerGas: assets.NewWeiI(250), GasLimit: 42, Hash: utils.NewHash()}
tx := evmtypes.Transaction{Type: 0x4, GasPrice: assets.NewWeiI(55555), MaxPriorityFeePerGas: assets.NewWeiI(200), MaxFeePerGas: assets.NewWeiI(250), GasLimit: 42, Hash: utils.NewHash()}
res := bhe.EffectiveTipCap(eipblock, tx)
assert.Nil(t, res)
})
Expand Down Expand Up @@ -1466,14 +1475,34 @@ func TestBlockHistoryEstimator_EffectiveGasPrice(t *testing.T) {
res = bhe.EffectiveGasPrice(eipblock, tx)
assert.Equal(t, "32 wei", res.String())
})

t.Run("tx type 3 should calculate gas price", func(t *testing.T) {
// 0x3 transaction (should calculate to 250)
tx := evmtypes.Transaction{Type: 0x3, MaxPriorityFeePerGas: assets.NewWeiI(100), MaxFeePerGas: assets.NewWeiI(110), GasLimit: 42, Hash: utils.NewHash()}
res := bhe.EffectiveGasPrice(eipblock, tx)
assert.Equal(t, "110 wei", res.String())
// 0x3 transaction (should calculate to 300)
tx = evmtypes.Transaction{Type: 0x3, MaxPriorityFeePerGas: assets.NewWeiI(200), MaxFeePerGas: assets.NewWeiI(350), GasLimit: 42, Hash: utils.NewHash()}
res = bhe.EffectiveGasPrice(eipblock, tx)
assert.Equal(t, "300 wei", res.String())
// 0x3 transaction (should calculate to 300, ignoring gas price)
tx = evmtypes.Transaction{Type: 0x3, MaxPriorityFeePerGas: assets.NewWeiI(200), MaxFeePerGas: assets.NewWeiI(350), GasLimit: 42, Hash: utils.NewHash()}
res = bhe.EffectiveGasPrice(eipblock, tx)
assert.Equal(t, "300 wei", res.String())
// 0x3 transaction (should fall back to gas price since MaxFeePerGas is missing)
tx = evmtypes.Transaction{Type: 0x3, GasPrice: assets.NewWeiI(5), MaxPriorityFeePerGas: assets.NewWeiI(200), GasLimit: 42, Hash: utils.NewHash()}
res = bhe.EffectiveGasPrice(eipblock, tx)
assert.Equal(t, "5 wei", res.String())
})

t.Run("tx type 2 has block missing base fee (should never happen but must handle gracefully)", func(t *testing.T) {
// 0x2 transaction (should calculate to 250)
tx := evmtypes.Transaction{Type: 0x2, GasPrice: assets.NewWeiI(55555), MaxPriorityFeePerGas: assets.NewWeiI(200), MaxFeePerGas: assets.NewWeiI(250), GasLimit: 42, Hash: utils.NewHash()}
res := bhe.EffectiveGasPrice(block, tx)
assert.Equal(t, "55.555 kwei", res.String())
})
t.Run("unknown type returns nil", func(t *testing.T) {
tx := evmtypes.Transaction{Type: 0x3, GasPrice: assets.NewWeiI(55555), MaxPriorityFeePerGas: assets.NewWeiI(200), MaxFeePerGas: assets.NewWeiI(250), GasLimit: 42, Hash: utils.NewHash()}
tx := evmtypes.Transaction{Type: 0x4, GasPrice: assets.NewWeiI(55555), MaxPriorityFeePerGas: assets.NewWeiI(200), MaxFeePerGas: assets.NewWeiI(250), GasLimit: 42, Hash: utils.NewHash()}
res := bhe.EffectiveGasPrice(block, tx)
assert.Nil(t, res)
})
Expand Down
Loading

0 comments on commit 96154fe

Please sign in to comment.