Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,52 @@ public async Task<string> Eth_blobBaseFee_ShouldGiveCorrectResult(ulong? excessB
return await ctx.Test.TestEthRpc("eth_blobBaseFee");
}

[TestCaseSource(nameof(GetBaseFeeTestCases))]
public async Task<string> Eth_baseFee_ShouldGiveCorrectResult(UInt256 baseFeePerGas, long gasLimit, long gasUsed, bool londonEnabled)
{
ISpecProvider specProvider = londonEnabled
? new TestSpecProvider(London.Instance)
: GetSpecProviderWithEip1559EnabledAs(false);
using Context ctx = await Context.Create(specProvider);
Block[] blocks = [
Build.A.Block.WithNumber(0).WithBaseFeePerGas(baseFeePerGas).WithGasLimit(gasLimit).WithGasUsed(gasUsed).TestObject,
];
BlockTree blockTree = Build.A.BlockTree(blocks[0]).WithBlocks(blocks).TestObject;
ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockFinder(blockTree).Build(specProvider);

return await ctx.Test.TestEthRpc("eth_baseFee");
}

public static IEnumerable<TestCaseData> GetBaseFeeTestCases
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Low — missing null-head test case

All four test cases supply a non-empty block tree, so the if (head is null) guard in the implementation is never exercised. Consider adding:

yield return new TestCaseData(UInt256.Zero, 0L, 0L, false)
{
    TestName = "Empty blockchain returns null",
    ExpectedResult = NullResult
};

with a corresponding ctx.Test built from an empty block tree (or simply leaving the default block tree with no explicit head). The guard is correct — this is just an untested branch.

{
get
{
static string Success(UInt256 result) => $"{{\"jsonrpc\":\"2.0\",\"result\":\"{result.ToHexString(true)}\",\"id\":67}}";
const string NullResult = "{\"jsonrpc\":\"2.0\",\"result\":null,\"id\":67}";

yield return new TestCaseData(UInt256.Zero, 30_000_000L, 0L, false)
{
TestName = "Pre-London block returns null",
ExpectedResult = NullResult
};
yield return new TestCaseData((UInt256)1_000_000_000, 30_000_000L, 15_000_000L, true)
{
TestName = "Block at gas target returns same base fee",
ExpectedResult = Success(1_000_000_000)
};
yield return new TestCaseData((UInt256)1_000_000_000, 30_000_000L, 30_000_000L, true)
{
TestName = "Block over gas target increases base fee by 12.5%",
ExpectedResult = Success(1_125_000_000)
};
yield return new TestCaseData((UInt256)1_000_000_000, 30_000_000L, 0L, true)
{
TestName = "Block under gas target decreases base fee by 12.5%",
ExpectedResult = Success(875_000_000)
};
}
}

[TestCase(true, "0x3")] //Gas Prices: 1,2,3,3,4,5 | Max Index: 5 | 60th Percentile: 5 * (3/5) = 3 | Result: 3 (0x3)
[TestCase(false, "0x2")] //Gas Prices: 0,1,1,2,2,3 | Max Index: 5 | 60th Percentile: 5 * (3/5) = 3 | Result: 2 (0x2)
public async Task Eth_gasPrice_BlocksAvailableLessThanBlocksToCheckWith1559Tx_ShouldGiveCorrectResult(bool eip1559Enabled, string expected)
Expand Down
17 changes: 17 additions & 0 deletions src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,23 @@ public ResultWrapper<string> eth_protocolVersion()
return ResultWrapper<UInt256?>.Success(feePerBlobGas);
}

public ResultWrapper<UInt256?> eth_baseFee()
{
BlockHeader? head = _blockFinder.Head?.Header;
if (head is null)
{
return ResultWrapper<UInt256?>.Success(null);
}

IEip1559Spec specFor1559 = _specProvider.GetSpecFor1559(head.Number + 1);
Comment thread
svlachakis marked this conversation as resolved.
if (!specFor1559.IsEip1559Enabled)
{
return ResultWrapper<UInt256?>.Success(null);
}

return ResultWrapper<UInt256?>.Success(BaseFeeCalculator.Calculate(head, specFor1559));
}

public ResultWrapper<UInt256?> eth_maxPriorityFeePerGas()
{
UInt256 gasPriceWithBaseFee = _gasPriceOracle.GetMaxPriorityGasFeeEstimate();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ public interface IEthRpcModule : IRpcModule
ExampleResponse = "0x1")]
ResultWrapper<UInt256?> eth_blobBaseFee();

[JsonRpcMethod(IsImplemented = true,
Description = "Returns the base fee of the next block in wei",
IsSharable = true,
ExampleResponse = "0x3b9aca00")]
ResultWrapper<UInt256?> eth_baseFee();

[JsonRpcMethod(IsImplemented = false,
Description = "Returns accounts",
IsSharable = true,
Expand Down