Skip to content
Closed
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
77 changes: 69 additions & 8 deletions consensus/misc/eip1559.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,13 @@ func VerifyEip1559Header(config *params.ChainConfig, parent, header *types.Heade
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)
scalar, overhead := ReadL2BaseFeeCoefficients()

expectedEIP1559 := calcBaseFeeEIP1559(config, parent, scalar, overhead)
expectedHeaderBaseFee := calcBaseFee(scalar, overhead, expectedEIP1559)

if header.BaseFee.Cmp(expectedHeaderBaseFee) != 0 {
return fmt.Errorf("invalid baseFee: got %s, want %s", header.BaseFee, expectedHeaderBaseFee)
}
return nil
}
Expand All @@ -108,7 +110,66 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header, parentL1BaseF
}

scalar, overhead := ReadL2BaseFeeCoefficients()
return calcBaseFee(scalar, overhead, parentL1BaseFee)
if !config.IsFeynman(big.NewInt(0).Add(parent.Number, common.Big1)) {
return calcBaseFee(scalar, overhead, parentL1BaseFee)
}
baseFeeEIP1559 := calcBaseFeeEIP1559(config, parent, scalar, overhead)
return calcBaseFee(scalar, overhead, baseFeeEIP1559)
}

// CalcBaseFee calculates the basefee of the header.
func calcBaseFeeEIP1559(config *params.ChainConfig, parent *types.Header, scalar *big.Int, overhead *big.Int) *big.Int {
// If the current block is the first EIP-1559 block, return the InitialBaseFee.
if !config.IsFeynman(parent.Number) {
return new(big.Int).SetUint64(params.InitialBaseFee)
}

parentBaseFeeEIP1559 := extractBaseFeeEIP1559(parent.BaseFee, scalar, overhead)
parentGasTarget := parent.GasLimit / config.ElasticityMultiplier()
// If the parent gasUsed is the same as the target, the baseFee remains unchanged.
if parent.GasUsed == parentGasTarget {
return new(big.Int).Set(parentBaseFeeEIP1559)
}

var (
num = new(big.Int)
denom = new(big.Int)
)

if parent.GasUsed > parentGasTarget {
// If the parent block used more gas than its target, the baseFee should increase.
// max(1, parentBaseFee * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator)
num.SetUint64(parent.GasUsed - parentGasTarget)
num.Mul(num, parentBaseFeeEIP1559)
num.Div(num, denom.SetUint64(parentGasTarget))
num.Div(num, denom.SetUint64(config.BaseFeeChangeDenominator()))
if num.Cmp(common.Big1) < 0 {
return num.Add(parentBaseFeeEIP1559, common.Big1)
}
return num.Add(parentBaseFeeEIP1559, num)
} else {
// Otherwise if the parent block used less gas than its target, the baseFee should decrease.
// max(0, parentBaseFee * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator)
num.SetUint64(parentGasTarget - parent.GasUsed)
num.Mul(num, parentBaseFeeEIP1559)
num.Div(num, denom.SetUint64(parentGasTarget))
num.Div(num, denom.SetUint64(config.BaseFeeChangeDenominator()))

baseFee := num.Sub(parentBaseFeeEIP1559, num)
if baseFee.Cmp(common.Big0) < 0 {
baseFee = common.Big0
}
return baseFee
}
}

func extractBaseFeeEIP1559(baseFee *big.Int, scalar *big.Int, overhead *big.Int) *big.Int {
baseFeeEIP := new(big.Int).Set(baseFee)
baseFeeEIP.Sub(baseFeeEIP, overhead)
baseFeeEIP.Mul(baseFeeEIP, BaseFeePrecision)
baseFeeEIP.Div(baseFeeEIP, scalar)

return baseFeeEIP
}

// MinBaseFee calculates the minimum L2 base fee based on the current coefficients.
Expand All @@ -117,8 +178,8 @@ func MinBaseFee() *big.Int {
return calcBaseFee(scalar, overhead, big.NewInt(0))
}

func calcBaseFee(scalar, overhead, parentL1BaseFee *big.Int) *big.Int {
baseFee := new(big.Int).Set(parentL1BaseFee)
func calcBaseFee(scalar, overhead, l2BaseFee *big.Int) *big.Int {
baseFee := new(big.Int).Set(l2BaseFee)
baseFee.Mul(baseFee, scalar)
baseFee.Div(baseFee, BaseFeePrecision)
baseFee.Add(baseFee, overhead)
Expand Down
15 changes: 15 additions & 0 deletions params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -988,6 +988,11 @@ func (c *ChainConfig) IsEuclidV2(now uint64) bool {
return isForkedTime(now, c.EuclidV2Time)
}

// IsFeynman returns whether time is either equal to the Feyman fork time or greater.
func (c *ChainConfig) IsFeynman(num *big.Int) bool {
return false // placeholder
}

// IsTerminalPoWBlock returns whether the given block is the last block of PoW stage.
func (c *ChainConfig) IsTerminalPoWBlock(parentTotalDiff *big.Int, totalDiff *big.Int) bool {
if c.TerminalTotalDifficulty == nil {
Expand All @@ -1014,6 +1019,16 @@ func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64) *Confi
return lasterr
}

// BaseFeeChangeDenominator bounds the amount the base fee can change between blocks.
func (c *ChainConfig) BaseFeeChangeDenominator() uint64 {
return DefaultBaseFeeChangeDenominator
}

// ElasticityMultiplier bounds the maximum gas limit an EIP-1559 block may have.
func (c *ChainConfig) ElasticityMultiplier() uint64 {
return DefaultElasticityMultiplier
}

// CheckConfigForkOrder checks that we don't "skip" any forks, geth isn't pluggable enough
// to guarantee that forks can be implemented in a different order than on official networks
func (c *ChainConfig) CheckConfigForkOrder() error {
Expand Down
6 changes: 3 additions & 3 deletions params/protocol_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ const (
// Introduced in Tangerine Whistle (Eip 150)
CreateBySelfdestructGas uint64 = 25000

BaseFeeChangeDenominator = 8 // Bounds the amount the base fee can change between blocks.
ElasticityMultiplier = 2 // Bounds the maximum gas limit an EIP-1559 block may have.
InitialBaseFee = 1000000000 // Initial base fee for EIP-1559 blocks.
DefaultBaseFeeChangeDenominator = 8 // Bounds the amount the base fee can change between blocks.
DefaultElasticityMultiplier = 2 // Bounds the maximum gas limit an EIP-1559 block may have.
InitialBaseFee = 1000000000 // Initial base fee for EIP-1559 blocks.

MaxCodeSize = 24576 // Maximum bytecode to permit for a contract
MaxInitCodeSize = 2 * MaxCodeSize // Maximum initcode to permit in a creation transaction and create instructions
Expand Down
2 changes: 1 addition & 1 deletion params/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
const (
VersionMajor = 5 // Major version component of the current release
VersionMinor = 8 // Minor version component of the current release
VersionPatch = 51 // Patch version component of the current release
VersionPatch = 52 // Patch version component of the current release
VersionMeta = "mainnet" // Version metadata to append to the version string
)

Expand Down
6 changes: 6 additions & 0 deletions rollup/da_syncer/blob_client/blob_scan_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ func (c *BlobScanClient) GetBlobByVersionedHashAndBlockTime(ctx context.Context,
if err != nil {
return nil, fmt.Errorf("failed to decode result into struct, err: %w", err)
}

// check that blob data is not empty
if len(result.Data) < 2 {
return nil, fmt.Errorf("blob data is too short to be valid, expected at least 2 characters, got: %s, versioned hash: %s", result.Data, versionedHash.String())
}

blobBytes, err := hex.DecodeString(result.Data[2:])
if err != nil {
return nil, fmt.Errorf("failed to decode data to bytes, err: %w", err)
Expand Down
6 changes: 6 additions & 0 deletions rollup/da_syncer/blob_client/block_native_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ func (c *BlockNativeClient) GetBlobByVersionedHashAndBlockTime(ctx context.Conte
if err != nil {
return nil, fmt.Errorf("failed to decode result into struct, err: %w", err)
}

// check that blob data is not empty
if len(result.Blob.Data) < 2 {
return nil, fmt.Errorf("blob data is too short to be valid, expected at least 2 characters, got: %s, versioned hash: %s", result.Blob.Data, versionedHash.String())
}

blobBytes, err := hex.DecodeString(result.Blob.Data[2:])
if err != nil {
return nil, fmt.Errorf("failed to decode data to bytes, err: %w", err)
Expand Down
Loading