Commit 4f2e1063 authored by Mark Tyneway's avatar Mark Tyneway Committed by GitHub

Merge pull request #1266 from ethereum-optimism/fix/prevent-too-low-fees

l2geth: prevent too low of fees from getting through
parents fc297257 735ef774
---
'@eth-optimism/l2geth': patch
---
Fix a bug in the fee logic that allowed for fees that were too low to get through
...@@ -3,6 +3,7 @@ package fees ...@@ -3,6 +3,7 @@ package fees
import ( import (
"errors" "errors"
"fmt" "fmt"
"math"
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -115,7 +116,7 @@ func PaysEnough(opts *PaysEnoughOpts) error { ...@@ -115,7 +116,7 @@ func PaysEnough(opts *PaysEnoughOpts) error {
return fmt.Errorf("%w: no expected fee", errMissingInput) return fmt.Errorf("%w: no expected fee", errMissingInput)
} }
fee := opts.ExpectedFee fee := new(big.Int).Set(opts.ExpectedFee)
// Allow for a downward buffer to protect against L1 gas price volatility // Allow for a downward buffer to protect against L1 gas price volatility
if opts.ThresholdDown != nil { if opts.ThresholdDown != nil {
fee = mulByFloat(fee, opts.ThresholdDown) fee = mulByFloat(fee, opts.ThresholdDown)
...@@ -129,7 +130,7 @@ func PaysEnough(opts *PaysEnoughOpts) error { ...@@ -129,7 +130,7 @@ func PaysEnough(opts *PaysEnoughOpts) error {
if opts.ThresholdUp != nil { if opts.ThresholdUp != nil {
// overpaying = user fee - expected fee // overpaying = user fee - expected fee
overpaying := new(big.Int).Sub(opts.UserFee, opts.ExpectedFee) overpaying := new(big.Int).Sub(opts.UserFee, opts.ExpectedFee)
threshold := mulByFloat(overpaying, opts.ThresholdUp) threshold := mulByFloat(opts.ExpectedFee, opts.ThresholdUp)
// if overpaying > threshold, return error // if overpaying > threshold, return error
if overpaying.Cmp(threshold) == 1 { if overpaying.Cmp(threshold) == 1 {
return ErrFeeTooHigh return ErrFeeTooHigh
...@@ -140,9 +141,10 @@ func PaysEnough(opts *PaysEnoughOpts) error { ...@@ -140,9 +141,10 @@ func PaysEnough(opts *PaysEnoughOpts) error {
func mulByFloat(num *big.Int, float *big.Float) *big.Int { func mulByFloat(num *big.Int, float *big.Float) *big.Int {
n := new(big.Float).SetUint64(num.Uint64()) n := new(big.Float).SetUint64(num.Uint64())
n = n.Mul(n, float) product := n.Mul(n, float)
value, _ := float.Uint64() pfloat, _ := product.Float64()
return new(big.Int).SetUint64(value) rounded := math.Ceil(pfloat)
return new(big.Int).SetUint64(uint64(rounded))
} }
// calculateL1GasLimit computes the L1 gasLimit based on the calldata and // calculateL1GasLimit computes the L1 gasLimit based on the calldata and
......
...@@ -157,13 +157,40 @@ func TestPaysEnough(t *testing.T) { ...@@ -157,13 +157,40 @@ func TestPaysEnough(t *testing.T) {
}, },
"fee-threshold-up": { "fee-threshold-up": {
opts: &PaysEnoughOpts{ opts: &PaysEnoughOpts{
UserFee: common.Big3, UserFee: common.Big256,
ExpectedFee: common.Big1, ExpectedFee: common.Big1,
ThresholdUp: new(big.Float).SetFloat64(1.5), ThresholdUp: new(big.Float).SetFloat64(1.5),
ThresholdDown: nil, ThresholdDown: nil,
}, },
err: ErrFeeTooHigh, err: ErrFeeTooHigh,
}, },
"fee-too-low-high": {
opts: &PaysEnoughOpts{
UserFee: new(big.Int).SetUint64(10_000),
ExpectedFee: new(big.Int).SetUint64(1),
ThresholdUp: new(big.Float).SetFloat64(3),
ThresholdDown: new(big.Float).SetFloat64(0.8),
},
err: ErrFeeTooHigh,
},
"fee-too-low-down": {
opts: &PaysEnoughOpts{
UserFee: new(big.Int).SetUint64(1),
ExpectedFee: new(big.Int).SetUint64(10_000),
ThresholdUp: new(big.Float).SetFloat64(3),
ThresholdDown: new(big.Float).SetFloat64(0.8),
},
err: ErrFeeTooLow,
},
"fee-too-low-down-2": {
opts: &PaysEnoughOpts{
UserFee: new(big.Int).SetUint64(0),
ExpectedFee: new(big.Int).SetUint64(10_000),
ThresholdUp: new(big.Float).SetFloat64(3),
ThresholdDown: new(big.Float).SetFloat64(0.8),
},
err: ErrFeeTooLow,
},
} }
for name, tt := range tests { for name, tt := range tests {
......
...@@ -858,9 +858,6 @@ func (s *SyncService) verifyFee(tx *types.Transaction) error { ...@@ -858,9 +858,6 @@ func (s *SyncService) verifyFee(tx *types.Transaction) error {
// Only count the calldata here as the overhead of the fully encoded // Only count the calldata here as the overhead of the fully encoded
// RLP transaction is handled inside of EncodeL2GasLimit // RLP transaction is handled inside of EncodeL2GasLimit
expectedTxGasLimit := fees.EncodeTxGasLimit(tx.Data(), l1GasPrice, l2GasLimit, l2GasPrice) expectedTxGasLimit := fees.EncodeTxGasLimit(tx.Data(), l1GasPrice, l2GasLimit, l2GasPrice)
if err != nil {
return err
}
// This should only happen if the unscaled transaction fee is greater than 18.44 ETH // This should only happen if the unscaled transaction fee is greater than 18.44 ETH
if !expectedTxGasLimit.IsUint64() { if !expectedTxGasLimit.IsUint64() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment