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

feat: check basefee in Curie #770

Merged
merged 20 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions accounts/abi/bind/backends/simulated.go
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
if call.GasPrice != nil && (call.GasFeeCap != nil || call.GasTipCap != nil) {
return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
}
if !b.blockchain.Config().IsLondon(header.Number) {
if !b.blockchain.Config().IsCurie(header.Number) {
// If there's no basefee, then it must be a non-1559 execution
if call.GasPrice == nil {
call.GasPrice = new(big.Int)
Expand All @@ -668,7 +668,11 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
// Backfill the legacy gasPrice for EVM execution, unless we're all zeroes
call.GasPrice = new(big.Int)
if call.GasFeeCap.BitLen() > 0 || call.GasTipCap.BitLen() > 0 {
call.GasPrice = math.BigMin(new(big.Int).Add(call.GasTipCap, header.BaseFee), call.GasFeeCap)
if header.BaseFee != nil {
call.GasPrice = math.BigMin(new(big.Int).Add(call.GasTipCap, header.BaseFee), call.GasFeeCap)
} else {
call.GasPrice = math.BigMin(call.GasTipCap, call.GasFeeCap)
}
}
}
}
Expand Down Expand Up @@ -980,3 +984,7 @@ func nullSubscription() event.Subscription {
return nil
})
}

func (fb *filterBackend) StateAt(root common.Hash) (*state.StateDB, error) {
return fb.bc.StateAt(root)
}
14 changes: 9 additions & 5 deletions accounts/abi/bind/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,10 +277,14 @@ func (c *BoundContract) createDynamicTx(opts *TransactOpts, contract *common.Add
// Estimate FeeCap
gasFeeCap := opts.GasFeeCap
if gasFeeCap == nil {
gasFeeCap = new(big.Int).Add(
gasTipCap,
new(big.Int).Mul(head.BaseFee, big.NewInt(basefeeWiggleMultiplier)),
)
if head.BaseFee != nil {
gasFeeCap = new(big.Int).Add(
gasTipCap,
new(big.Int).Mul(head.BaseFee, big.NewInt(basefeeWiggleMultiplier)),
)
} else {
gasFeeCap = new(big.Int).Set(gasTipCap)
}
}
if gasFeeCap.Cmp(gasTipCap) < 0 {
return nil, fmt.Errorf("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)", gasFeeCap, gasTipCap)
Expand Down Expand Up @@ -313,7 +317,7 @@ func (c *BoundContract) createDynamicTx(opts *TransactOpts, contract *common.Add

func (c *BoundContract) createLegacyTx(opts *TransactOpts, contract *common.Address, input []byte) (*types.Transaction, error) {
if opts.GasFeeCap != nil || opts.GasTipCap != nil {
return nil, errors.New("maxFeePerGas or maxPriorityFeePerGas specified but london is not active yet")
return nil, errors.New("maxFeePerGas or maxPriorityFeePerGas specified but curie is not active yet")
}
// Normalize value
value := opts.Value
Expand Down
13 changes: 9 additions & 4 deletions cmd/evm/internal/t8ntool/transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ type input struct {
Env *stEnv `json:"env,omitempty"`
Txs []*txWithKey `json:"txs,omitempty"`
TxRlp string `json:"txsRlp,omitempty"`

ParentL1BaseFee *big.Int `json:"parentL1BaseFee,omitempty"`
}

func Transition(ctx *cli.Context) error {
Expand Down Expand Up @@ -195,7 +197,7 @@ func Transition(ctx *cli.Context) error {
if txs, err = loadTransactions(txStr, inputData, prestate.Env, chainConfig); err != nil {
return err
}
if err := applyLondonChecks(&prestate.Env, chainConfig); err != nil {
if err := applyCurieChecks(&prestate.Env, chainConfig, inputData.ParentL1BaseFee); err != nil {
return err
}
if err := applyShanghaiChecks(&prestate.Env, chainConfig); err != nil {
Expand Down Expand Up @@ -338,8 +340,8 @@ func loadTransactions(txStr string, inputData *input, env stEnv, chainConfig *pa
return signUnsignedTransactions(txsWithKeys, signer)
}

func applyLondonChecks(env *stEnv, chainConfig *params.ChainConfig) error {
if !chainConfig.IsLondon(big.NewInt(int64(env.Number))) {
func applyCurieChecks(env *stEnv, chainConfig *params.ChainConfig, parentL1BaseFee *big.Int) error {
if !chainConfig.IsCurie(big.NewInt(int64(env.Number))) {
return nil
}
// Sanity check, to not `panic` in state_transition
Expand All @@ -350,12 +352,15 @@ func applyLondonChecks(env *stEnv, chainConfig *params.ChainConfig) error {
if env.ParentBaseFee == nil || env.Number == 0 {
return NewError(ErrorConfig, errors.New("EIP-1559 config but missing 'currentBaseFee' in env section"))
}
if parentL1BaseFee == nil {
return errors.New("EIP-1559 config but missing 'parentL1BaseFee' for calculating basefee")
}
env.BaseFee = eip1559.CalcBaseFee(chainConfig, &types.Header{
Number: new(big.Int).SetUint64(env.Number - 1),
BaseFee: env.ParentBaseFee,
GasUsed: env.ParentGasUsed,
GasLimit: env.ParentGasLimit,
})
}, parentL1BaseFee)
return nil
}

Expand Down
2 changes: 1 addition & 1 deletion consensus/clique/clique.go
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ func (c *Clique) verifyCascadingFields(chain consensus.ChainHeaderReader, header
if header.GasUsed > header.GasLimit {
return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit)
}
if !chain.Config().IsLondon(header.Number) {
if !chain.Config().IsCurie(header.Number) {
// Verify BaseFee not present before EIP-1559 fork.
if header.BaseFee != nil {
return fmt.Errorf("invalid baseFee before fork: have %d, want <nil>", header.BaseFee)
Expand Down
2 changes: 1 addition & 1 deletion consensus/ethash/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainHeaderReader, header, pa
return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit)
}
// Verify the block's gas usage and (if applicable) verify the base fee.
if !chain.Config().IsLondon(header.Number) {
if !chain.Config().IsCurie(header.Number) {
// Verify BaseFee not present before EIP-1559 fork.
if header.BaseFee != nil {
return fmt.Errorf("invalid baseFee before fork: have %d, expected 'nil'", header.BaseFee)
Expand Down
4 changes: 4 additions & 0 deletions consensus/misc/eip1559/eip1559.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package eip1559

/*

import (
"errors"
"fmt"
Expand Down Expand Up @@ -93,3 +95,5 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int {
return math.BigMax(baseFee, common.Big0)
}
}

*/
73 changes: 73 additions & 0 deletions consensus/misc/eip1559/eip1559_scroll.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Copyright 2021 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum 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,
// 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 <http://www.gnu.org/licenses/>.

package eip1559

import (
"fmt"
"math/big"

"github.com/ethereum/go-ethereum/consensus/misc"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
)

// Protocol-enforced maximum L2 base fee.
// We would only go above this if L1 base fee hits 700 Gwei.
const MaximumL2BaseFee = 10000000000

// VerifyEIP1559Header verifies some header attributes which were changed in EIP-1559,
// - gas limit check
// - basefee check
func VerifyEIP1559Header(config *params.ChainConfig, parent, header *types.Header) error {
// Verify that the gas limit remains within allowed bounds
if err := misc.VerifyGaslimit(parent.GasLimit, header.GasLimit); err != nil {
return err
}
// Verify the header is not malformed
if header.BaseFee == nil {
return fmt.Errorf("header is missing baseFee")
}
// note: we do not verify L2 base fee, the sequencer has the
// right to set any base fee below the maximum. L2 base fee
// is not subject to L2 consensus or zk verification.
if header.BaseFee.Cmp(big.NewInt(MaximumL2BaseFee)) > 0 {
return fmt.Errorf("invalid baseFee: have %s, maximum %d", header.BaseFee, MaximumL2BaseFee)
}
return nil
}

// CalcBaseFee calculates the basefee of the header.
func CalcBaseFee(config *params.ChainConfig, parent *types.Header, parentL1BaseFee *big.Int) *big.Int {
l2SequencerFee := big.NewInt(10000000) // 0.01 Gwei
provingFee := big.NewInt(140000000) // 0.14 Gwei

// L1_base_fee * 0.014
verificationFee := parentL1BaseFee
verificationFee = new(big.Int).Mul(verificationFee, big.NewInt(14))
verificationFee = new(big.Int).Div(verificationFee, big.NewInt(1000))

baseFee := big.NewInt(0)
baseFee.Add(baseFee, l2SequencerFee)
baseFee.Add(baseFee, provingFee)
baseFee.Add(baseFee, verificationFee)

if baseFee.Cmp(big.NewInt(MaximumL2BaseFee)) > 0 {
baseFee = big.NewInt(MaximumL2BaseFee)
}

return baseFee
}
4 changes: 4 additions & 0 deletions consensus/misc/eip1559/eip1559_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package eip1559

/*

import (
"math/big"
"testing"
Expand Down Expand Up @@ -129,3 +131,5 @@ func TestCalcBaseFee(t *testing.T) {
}
}
}

*/
25 changes: 12 additions & 13 deletions core/chain_makers.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rollup/fees"
"github.com/ethereum/go-ethereum/trie"
)

Expand Down Expand Up @@ -179,7 +180,11 @@ func (b *BlockGen) Timestamp() uint64 {

// BaseFee returns the EIP-1559 base fee of the block being generated.
func (b *BlockGen) BaseFee() *big.Int {
return new(big.Int).Set(b.header.BaseFee)
if b.header.BaseFee != nil {
return new(big.Int).Set(b.header.BaseFee)
} else {
return big.NewInt(0)
}
}

// AddUncheckedReceipt forcefully adds a receipts to the block without a
Expand Down Expand Up @@ -217,12 +222,9 @@ func (b *BlockGen) AddUncle(h *types.Header) {

// The gas limit and price should be derived from the parent
h.GasLimit = parent.GasLimit
if b.config.IsLondon(h.Number) {
h.BaseFee = eip1559.CalcBaseFee(b.config, parent)
if !b.config.IsLondon(parent.Number) {
parentGasLimit := parent.GasLimit * b.config.ElasticityMultiplier()
h.GasLimit = CalcGasLimit(parentGasLimit, parentGasLimit)
}
if b.config.IsCurie(h.Number) {
parentL1BaseFee := fees.GetL1BaseFee(b.statedb)
h.BaseFee = eip1559.CalcBaseFee(b.config, parent, parentL1BaseFee)
}
b.uncles = append(b.uncles, h)
}
Expand Down Expand Up @@ -409,12 +411,9 @@ func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.S
Number: new(big.Int).Add(parent.Number(), common.Big1),
Time: time,
}
if chain.Config().IsLondon(header.Number) {
header.BaseFee = eip1559.CalcBaseFee(chain.Config(), parent.Header())
if !chain.Config().IsLondon(parent.Number()) {
parentGasLimit := parent.GasLimit() * chain.Config().ElasticityMultiplier()
header.GasLimit = CalcGasLimit(parentGasLimit, parentGasLimit)
}
if chain.Config().IsCurie(header.Number) {
parentL1BaseFee := fees.GetL1BaseFee(state)
header.BaseFee = eip1559.CalcBaseFee(chain.Config(), parent.Header(), parentL1BaseFee)
}
if chain.Config().IsCancun(header.Number, header.Time) {
var (
Expand Down
16 changes: 8 additions & 8 deletions core/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
Expand Down Expand Up @@ -450,14 +451,13 @@ func (g *Genesis) ToBlock() *types.Block {
if g.Difficulty == nil && g.Mixhash == (common.Hash{}) {
head.Difficulty = params.GenesisDifficulty
}
// TODO: fix basefee
// if g.Config != nil && g.Config.IsLondon(common.Big0) {
// if g.BaseFee != nil {
// head.BaseFee = g.BaseFee
// } else {
// head.BaseFee = new(big.Int).SetUint64(params.InitialBaseFee)
// }
// }
if g.Config != nil && g.Config.IsCurie(common.Big0) {
if g.BaseFee != nil {
head.BaseFee = g.BaseFee
} else {
head.BaseFee = eip1559.CalcBaseFee(g.Config, nil, big.NewInt(0))
}
}
var withdrawals []*types.Withdrawal
// if conf := g.Config; conf != nil {
// num := big.NewInt(int64(g.Number))
Expand Down
5 changes: 3 additions & 2 deletions core/state_processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -376,8 +376,9 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr
Time: parent.Time() + 10,
UncleHash: types.EmptyUncleHash,
}
if config.IsLondon(header.Number) {
header.BaseFee = eip1559.CalcBaseFee(config, parent.Header())
if config.IsCurie(header.Number) {
parentL1BaseFee := big.NewInt(1000000000) // 1 gwei
header.BaseFee = eip1559.CalcBaseFee(config, parent.Header(), parentL1BaseFee)
}
if config.IsShanghai(header.Number, header.Time) {
header.WithdrawalsHash = &types.EmptyWithdrawalsHash
Expand Down
11 changes: 9 additions & 2 deletions core/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ func (st *StateTransition) preCheck() error {
}

// Make sure that transaction gasFeeCap is greater than the baseFee (post london)
// Note: Logically, this should be `IsCurie`, but we keep `IsLondon` to ensure backward compatibility.
if st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) {
// Skip the checks if gas fields are zero and baseFee was explicitly disabled (eth_call)
if !st.evm.Config.NoBaseFee || msg.GasFeeCap.BitLen() > 0 || msg.GasTipCap.BitLen() > 0 {
Expand All @@ -352,7 +353,11 @@ func (st *StateTransition) preCheck() error {
}
// This will panic if baseFee is nil, but basefee presence is verified
// as part of header validation.
if msg.GasFeeCap.Cmp(st.evm.Context.BaseFee) < 0 {
if st.evm.Context.BaseFee != nil && msg.GasFeeCap.Cmp(st.evm.Context.BaseFee) < 0 {
return fmt.Errorf("%w: address %v, maxFeePerGas: %s baseFee: %s", ErrFeeCapTooLow,
msg.From.Hex(), msg.GasFeeCap, st.evm.Context.BaseFee)
}
if st.evm.Context.BaseFee == nil && msg.GasFeeCap.Cmp(big.NewInt(0)) < 0 {
return fmt.Errorf("%w: address %v, maxFeePerGas: %s baseFee: %s", ErrFeeCapTooLow,
msg.From.Hex(), msg.GasFeeCap, st.evm.Context.BaseFee)
}
Expand Down Expand Up @@ -479,7 +484,9 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
st.refundGas(params.RefundQuotientEIP3529)
}
effectiveTip := msg.GasPrice
if rules.IsLondon {

// only burn the base fee if the fee vault is not enabled
if rules.IsCurie && !st.evm.ChainConfig().Scroll.FeeVaultEnabled() {
effectiveTip = cmath.BigMin(msg.GasTipCap, new(big.Int).Sub(msg.GasFeeCap, st.evm.Context.BaseFee))
}

Expand Down
5 changes: 3 additions & 2 deletions core/txpool/blobpool/blobpool.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import (
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rollup/fees"
"github.com/holiman/billy"
"github.com/holiman/uint256"
)
Expand Down Expand Up @@ -399,7 +400,7 @@ func (p *BlobPool) Init(gasTip *big.Int, head *types.Header, reserve txpool.Addr
p.recheck(addr, nil)
}
var (
basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), p.head))
basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), p.head, fees.GetL1BaseFee(p.state)))
blobfee = uint256.MustFromBig(big.NewInt(params.BlobTxMinBlobGasprice))
)
if p.head.ExcessBlobGas != nil {
Expand Down Expand Up @@ -782,7 +783,7 @@ func (p *BlobPool) Reset(oldHead, newHead *types.Header) {
}
// Reset the price heap for the new set of basefee/blobfee pairs
var (
basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), newHead))
basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), newHead, fees.GetL1BaseFee(p.state)))
blobfee = uint256.MustFromBig(big.NewInt(params.BlobTxMinBlobGasprice))
)
if newHead.ExcessBlobGas != nil {
Expand Down
3 changes: 2 additions & 1 deletion core/txpool/blobpool/blobpool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,13 @@ func (bc *testBlockChain) CurrentBlock() *types.Header {
mid := new(big.Int).Add(lo, hi)
mid.Div(mid, big.NewInt(2))

parentL1BaseFee := big.NewInt(1000000000) // 1 gwei
if eip1559.CalcBaseFee(bc.config, &types.Header{
Number: blockNumber,
GasLimit: gasLimit,
GasUsed: 0,
BaseFee: mid,
}).Cmp(bc.basefee.ToBig()) > 0 {
}, parentL1BaseFee).Cmp(bc.basefee.ToBig()) > 0 {
hi = mid
} else {
lo = mid
Expand Down
Loading
Loading