Skip to content
Merged
1 change: 1 addition & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- Add pending releases here
- Upgrade to Go version 1.24
- Implement ACP-226: Set expected block gas cost to 0 in Granite network upgrade, removing block gas cost requirements for block building.

## [v0.7.9](https://github.com/ava-labs/subnet-evm/releases/tag/v0.7.9)

Expand Down
12 changes: 6 additions & 6 deletions core/blockchain_ext_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1395,7 +1395,7 @@ func GenerateChainInvalidBlockFee(t *testing.T, create createFunc) {
// Ensure that key1 has some funds in the genesis block.
genesisBalance := new(big.Int).Mul(big.NewInt(1000000), big.NewInt(params.Ether))
gspec := &Genesis{
Config: params.TestChainConfig,
Config: params.TestFortunaChainConfig,
Alloc: GenesisAlloc{addr1: {Balance: genesisBalance}},
}

Expand All @@ -1404,10 +1404,10 @@ func GenerateChainInvalidBlockFee(t *testing.T, create createFunc) {
t.Cleanup(blockchain.Stop)

// This call generates a chain of 3 blocks.
signer := types.LatestSigner(params.TestChainConfig)
signer := types.LatestSigner(params.TestFortunaChainConfig)
_, _, _, err = GenerateChainWithGenesis(gspec, blockchain.engine, 3, extras.TestChainConfig.FeeConfig.TargetBlockRate-1, func(_ int, gen *BlockGen) {
tx := types.NewTx(&types.DynamicFeeTx{
ChainID: params.TestChainConfig.ChainID,
ChainID: params.TestFortunaChainConfig.ChainID,
Nonce: gen.TxNonce(addr1),
To: &addr2,
Gas: ethparams.TxGas,
Expand Down Expand Up @@ -1436,7 +1436,7 @@ func InsertChainInvalidBlockFee(t *testing.T, create createFunc) {
// Ensure that key1 has some funds in the genesis block.
genesisBalance := new(big.Int).Mul(big.NewInt(1000000), big.NewInt(params.Ether))
gspec := &Genesis{
Config: params.TestChainConfig,
Config: params.TestFortunaChainConfig,
Alloc: GenesisAlloc{addr1: {Balance: genesisBalance}},
}

Expand All @@ -1445,11 +1445,11 @@ func InsertChainInvalidBlockFee(t *testing.T, create createFunc) {
t.Cleanup(blockchain.Stop)

// This call generates a chain of 3 blocks.
signer := types.LatestSigner(params.TestChainConfig)
signer := types.LatestSigner(params.TestFortunaChainConfig)
eng := dummy.NewFakerWithMode(dummy.Mode{ModeSkipBlockFee: true, ModeSkipCoinbase: true})
_, chain, _, err := GenerateChainWithGenesis(gspec, eng, 3, extras.TestChainConfig.FeeConfig.TargetBlockRate-1, func(_ int, gen *BlockGen) {
tx := types.NewTx(&types.DynamicFeeTx{
ChainID: params.TestChainConfig.ChainID,
ChainID: params.TestFortunaChainConfig.ChainID,
Nonce: gen.TxNonce(addr1),
To: &addr2,
Gas: ethparams.TxGas,
Expand Down
73 changes: 56 additions & 17 deletions eth/gasprice/gasprice_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,12 +228,12 @@ func testGenBlock(t *testing.T, tip int64, numTx int) func(int, *core.BlockGen)
b.SetCoinbase(common.Address{1})

txTip := big.NewInt(tip * params.GWei)
signer := types.LatestSigner(params.TestChainConfig)
signer := types.LatestSigner(params.TestFortunaChainConfig)
baseFee := b.BaseFee()
feeCap := new(big.Int).Add(baseFee, txTip)
for j := 0; j < numTx; j++ {
tx := types.NewTx(&types.DynamicFeeTx{
ChainID: params.TestChainConfig.ChainID,
ChainID: params.TestFortunaChainConfig.ChainID,
Nonce: b.TxNonce(addr),
To: &common.Address{},
Gas: ethparams.TxGas,
Expand Down Expand Up @@ -265,7 +265,7 @@ func TestSuggestTipCapNetworkUpgrades(t *testing.T) {

func TestSuggestTipCapSimple(t *testing.T) {
applyGasPriceTest(t, suggestTipCapTest{
chainConfig: params.TestChainConfig,
chainConfig: params.TestFortunaChainConfig,
numBlocks: 3,
genBlock: testGenBlock(t, 55, 370),
expectedTip: big.NewInt(1_287_001_288),
Expand All @@ -274,7 +274,7 @@ func TestSuggestTipCapSimple(t *testing.T) {

func TestSuggestTipCapSimpleFloor(t *testing.T) {
applyGasPriceTest(t, suggestTipCapTest{
chainConfig: params.TestChainConfig,
chainConfig: params.TestFortunaChainConfig,
numBlocks: 1,
genBlock: testGenBlock(t, 55, 370),
expectedTip: big.NewInt(643_500_644),
Expand All @@ -284,17 +284,17 @@ func TestSuggestTipCapSimpleFloor(t *testing.T) {
func TestSuggestTipCapSmallTips(t *testing.T) {
tip := big.NewInt(550 * params.GWei)
applyGasPriceTest(t, suggestTipCapTest{
chainConfig: params.TestChainConfig,
chainConfig: params.TestFortunaChainConfig,
numBlocks: 3,
genBlock: func(i int, b *core.BlockGen) {
b.SetCoinbase(common.Address{1})

signer := types.LatestSigner(params.TestChainConfig)
signer := types.LatestSigner(params.TestFortunaChainConfig)
baseFee := b.BaseFee()
feeCap := new(big.Int).Add(baseFee, tip)
for j := 0; j < 185; j++ {
tx := types.NewTx(&types.DynamicFeeTx{
ChainID: params.TestChainConfig.ChainID,
ChainID: params.TestFortunaChainConfig.ChainID,
Nonce: b.TxNonce(addr),
To: &common.Address{},
Gas: ethparams.TxGas,
Expand All @@ -308,7 +308,7 @@ func TestSuggestTipCapSmallTips(t *testing.T) {
}
b.AddTx(tx)
tx = types.NewTx(&types.DynamicFeeTx{
ChainID: params.TestChainConfig.ChainID,
ChainID: params.TestFortunaChainConfig.ChainID,
Nonce: b.TxNonce(addr),
To: &common.Address{},
Gas: ethparams.TxGas,
Expand All @@ -327,7 +327,7 @@ func TestSuggestTipCapSmallTips(t *testing.T) {

func TestSuggestTipCapMinGas(t *testing.T) {
applyGasPriceTest(t, suggestTipCapTest{
chainConfig: params.TestChainConfig,
chainConfig: params.TestFortunaChainConfig,
numBlocks: 3,
genBlock: testGenBlock(t, 500, 50),
expectedTip: DefaultMinPrice,
Expand All @@ -343,10 +343,10 @@ func TestSuggestGasPriceSubnetEVM(t *testing.T) {
Percentile: 60,
}

backend := newTestBackend(t, params.TestChainConfig, 3, func(i int, b *core.BlockGen) {
backend := newTestBackend(t, params.TestFortunaChainConfig, 3, func(i int, b *core.BlockGen) {
b.SetCoinbase(common.Address{1})

signer := types.LatestSigner(params.TestChainConfig)
signer := types.LatestSigner(params.TestFortunaChainConfig)
gasPrice := big.NewInt(legacy.BaseFee)
for j := 0; j < 50; j++ {
tx := types.NewTx(&types.LegacyTx{
Expand All @@ -370,18 +370,57 @@ func TestSuggestGasPriceSubnetEVM(t *testing.T) {
require.NoError(t, err)
}

// NOTE: [Oracle.SuggestTipCap] does NOT simply return the "required" (minimum) tip.
// The oracle computes a percentile of recent required tips (not observed on-chain tips)
// within a time/blocks lookback window and applies a small floor (e.g., 1 wei in tests):
//
// suggested = max(floor, recent-required-percentile)
//
// After Granite, BlockGasCost is 0 and per-block required tips are 0, so the oracle
// suggestion equals the floor (1 wei) in steady state, regardless of high on-chain tips.
// The cases below exercise behavior across forks using the same percentile logic and floor.
func TestSuggestTipCapMaxBlocksLookback(t *testing.T) {
cases := []struct {
chainConfig *params.ChainConfig
expectedTip *big.Int
}{
// TODO: remove Fortuna case when we activate Granite
{
chainConfig: params.TestFortunaChainConfig,
expectedTip: big.NewInt(1),
},
{
chainConfig: params.TestChainConfig,
expectedTip: big.NewInt(1),
},
}
for _, c := range cases {
applyGasPriceTest(t, suggestTipCapTest{
chainConfig: c.chainConfig,
numBlocks: 200,
genBlock: testGenBlock(t, 550, 80),
expectedTip: c.expectedTip,
}, defaultOracleConfig())
}
}

// Post-Granite, even very high observed tx tips should not affect SuggestTipCap, which
// is computed from required tips. Since required tips are 0 in Granite, the returned
// suggestion should be the floor (1 wei).
func TestSuggestTipCapIgnoresObservedTipsPostGranite(t *testing.T) {
applyGasPriceTest(t, suggestTipCapTest{
chainConfig: params.TestChainConfig,
chainConfig: params.TestChainConfig, // Granite active in TestChainConfig
numBlocks: 20,
genBlock: testGenBlock(t, 550, 370),
expectedTip: big.NewInt(5_807_226_111),
// Generate blocks with very high on-chain tips to ensure they wouldn't bias the result
// if the oracle looked at observed tips. Expectation remains 1 wei.
genBlock: testGenBlock(t, 100_000, 80),
expectedTip: big.NewInt(1),
}, defaultOracleConfig())
}

func TestSuggestTipCapMaxBlocksSecondsLookback(t *testing.T) {
applyGasPriceTest(t, suggestTipCapTest{
chainConfig: params.TestChainConfig,
chainConfig: params.TestFortunaChainConfig,
numBlocks: 20,
genBlock: testGenBlock(t, 550, 370),
expectedTip: big.NewInt(10_384_877_852),
Expand All @@ -398,14 +437,14 @@ func TestEstimateBaseFeeAfterFeeConfigUpdate(t *testing.T) {
}

// create a chain config with fee manager enabled at genesis with [addr] as the admin
chainConfig := params.Copy(params.TestChainConfig)
chainConfig := params.Copy(params.TestFortunaChainConfig)
chainConfigExtra := params.GetExtra(&chainConfig)
chainConfigExtra.GenesisPrecompiles = extras.Precompiles{
feemanager.ConfigKey: feemanager.NewConfig(utils.NewUint64(0), []common.Address{addr}, nil, nil, nil),
}

// create a fee config with higher MinBaseFee and prepare it for inclusion in a tx
signer := types.LatestSigner(params.TestChainConfig)
signer := types.LatestSigner(params.TestFortunaChainConfig)
highFeeConfig := chainConfigExtra.FeeConfig
highFeeConfig.MinBaseFee = big.NewInt(28_000_000_000)
data, err := feemanager.PackSetFeeConfig(highFeeConfig)
Expand Down
5 changes: 5 additions & 0 deletions plugin/evm/customheader/block_gas_cost.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ var (
// BlockGasCost calculates the required block gas cost based on the parent
// header and the timestamp of the new block.
// Prior to Subnet-EVM, the returned block gas cost will be nil.
// In Granite, the returned block gas cost will be 0.
func BlockGasCost(
config *extras.ChainConfig,
feeConfig commontype.FeeConfig,
Expand All @@ -38,6 +39,10 @@ func BlockGasCost(
return nil
}
step := feeConfig.BlockGasCostStep.Uint64()
if config.IsGranite(timestamp) {
return big.NewInt(0)
}

// Treat an invalid parent/current time combination as 0 elapsed time.
//
// TODO: Does it even make sense to handle this? The timestamp should be
Expand Down
12 changes: 10 additions & 2 deletions plugin/evm/customheader/block_gas_cost_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,20 +77,28 @@ func BlockGasCostTest(t *testing.T, feeConfig commontype.FeeConfig) {
},
{
name: "normal",
upgrades: extras.TestChainConfig.NetworkUpgrades,
upgrades: extras.TestFortunaChainConfig.NetworkUpgrades,
parentTime: 10,
parentCost: maxBlockGasCostBig,
timestamp: 10 + targetBlockRate + 1,
expected: new(big.Int).SetUint64(maxBlockGasCost - blockGasCostStep),
},
{
name: "negative_time_elapsed",
upgrades: extras.TestChainConfig.NetworkUpgrades,
upgrades: extras.TestFortunaChainConfig.NetworkUpgrades,
parentTime: 10,
parentCost: feeConfig.MinBlockGasCost,
timestamp: 9,
expected: new(big.Int).SetUint64(minBlockGasCost + blockGasCostStep*targetBlockRate),
},
{
name: "granite_returns_zero",
upgrades: extras.TestGraniteChainConfig.NetworkUpgrades,
parentTime: 10,
parentCost: big.NewInt(int64(maxBlockGasCost)),
timestamp: 10 + targetBlockRate + 1,
expected: big.NewInt(0),
},
}

for _, test := range tests {
Expand Down
Loading