Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cancun Hardfork: support for new Transaction type #12063

Merged
merged 9 commits into from
Feb 26, 2024
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 @@ -855,42 +855,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:
simsonraj marked this conversation as resolved.
Show resolved Hide resolved
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:
simsonraj marked this conversation as resolved.
Show resolved Hide resolved
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
Loading