From d7f773c7ae3e8f35e2c243d2c4974c7ec578aa30 Mon Sep 17 00:00:00 2001 From: William Morriss Date: Sat, 9 May 2026 05:28:36 -0500 Subject: [PATCH 1/4] feat(rpc): implement eth_baseFee method Assisted-by: Claude:claude-sonnet-4-6 --- src/rpc/methods/eth.rs | 34 ++++++++++++++++++- src/rpc/mod.rs | 1 + .../forest__rpc__tests__rpc__v0.snap | 16 +++++++++ .../forest__rpc__tests__rpc__v1.snap | 16 +++++++++ .../forest__rpc__tests__rpc__v2.snap | 16 +++++++++ 5 files changed, 82 insertions(+), 1 deletion(-) diff --git a/src/rpc/methods/eth.rs b/src/rpc/methods/eth.rs index 2c5c6a712712..bfee4a0b499d 100644 --- a/src/rpc/methods/eth.rs +++ b/src/rpc/methods/eth.rs @@ -18,7 +18,7 @@ use self::trace::types::*; use self::types::*; use super::gas; use crate::blocks::{Tipset, TipsetKey}; -use crate::chain::{ChainStore, index::ResolveNullTipset}; +use crate::chain::{ChainStore, compute_base_fee, index::ResolveNullTipset}; use crate::chain_sync::NodeSyncStatus; use crate::cid_collections::CidHashSet; use crate::eth::{ @@ -27,6 +27,7 @@ use crate::eth::{ }; use crate::lotus_json::{HasLotusJson, lotus_json_with_self}; use crate::message::{ChainMessage, MessageRead as _, MessageReadWrite as _, SignedMessage}; +use crate::networks::Height; use crate::rpc::{ ApiPaths, Ctx, EthEventHandler, LOOKBACK_NO_LIMIT, Permission, RpcMethod, RpcMethodExt as _, error::ServerError, @@ -805,6 +806,37 @@ impl RpcMethod<0> for EthAccounts { } } +pub enum EthBaseFee {} +impl RpcMethod<0> for EthBaseFee { + const NAME: &'static str = "Filecoin.EthBaseFee"; + const NAME_ALIAS: Option<&'static str> = Some("eth_baseFee"); + const PARAM_NAMES: [&'static str; 0] = []; + const API_PATHS: BitFlags = ApiPaths::all_with_v2(); + const PERMISSION: Permission = Permission::Read; + + type Params = (); + type Ok = EthBigInt; + + async fn handle( + ctx: Ctx, + (): Self::Params, + _: &http::Extensions, + ) -> Result { + let ts = ctx.chain_store().heaviest_tipset(); + let heights = &ctx.chain_config().height_infos; + let smoke_height = heights + .get(&Height::Smoke) + .context("Missing Smoke height")? + .epoch; + let firehorse_height = heights + .get(&Height::FireHorse) + .context("Missing FireHorse height")? + .epoch; + let base_fee = compute_base_fee(ctx.store(), &ts, smoke_height, firehorse_height)?; + Ok(EthBigInt(base_fee.atto().clone())) + } +} + pub enum EthBlockNumber {} impl RpcMethod<0> for EthBlockNumber { const NAME: &'static str = "Filecoin.EthBlockNumber"; diff --git a/src/rpc/mod.rs b/src/rpc/mod.rs index 1d56d72c5310..76dd4284c03a 100644 --- a/src/rpc/mod.rs +++ b/src/rpc/mod.rs @@ -105,6 +105,7 @@ macro_rules! for_each_rpc_method { $callback!($crate::rpc::eth::EthAccounts); $callback!($crate::rpc::eth::EthAddressToFilecoinAddress); $callback!($crate::rpc::eth::FilecoinAddressToEthAddress); + $callback!($crate::rpc::eth::EthBaseFee); $callback!($crate::rpc::eth::EthBlockNumber); $callback!($crate::rpc::eth::EthCall); $callback!($crate::rpc::eth::EthChainId); diff --git a/src/rpc/snapshots/forest__rpc__tests__rpc__v0.snap b/src/rpc/snapshots/forest__rpc__tests__rpc__v0.snap index 32520218cef0..041d8ddad437 100644 --- a/src/rpc/snapshots/forest__rpc__tests__rpc__v0.snap +++ b/src/rpc/snapshots/forest__rpc__tests__rpc__v0.snap @@ -525,6 +525,22 @@ methods: schema: $ref: "#/components/schemas/EthAddress" paramStructure: by-position + - name: Filecoin.EthBaseFee + params: [] + result: + name: Filecoin.EthBaseFee.Result + required: true + schema: + $ref: "#/components/schemas/EthBigInt" + paramStructure: by-position + - name: eth_baseFee + params: [] + result: + name: eth_baseFee.Result + required: true + schema: + $ref: "#/components/schemas/EthBigInt" + paramStructure: by-position - name: Filecoin.EthBlockNumber params: [] result: diff --git a/src/rpc/snapshots/forest__rpc__tests__rpc__v1.snap b/src/rpc/snapshots/forest__rpc__tests__rpc__v1.snap index 4e56933fb47a..172213db8ce3 100644 --- a/src/rpc/snapshots/forest__rpc__tests__rpc__v1.snap +++ b/src/rpc/snapshots/forest__rpc__tests__rpc__v1.snap @@ -521,6 +521,22 @@ methods: schema: $ref: "#/components/schemas/EthAddress" paramStructure: by-position + - name: Filecoin.EthBaseFee + params: [] + result: + name: Filecoin.EthBaseFee.Result + required: true + schema: + $ref: "#/components/schemas/EthBigInt" + paramStructure: by-position + - name: eth_baseFee + params: [] + result: + name: eth_baseFee.Result + required: true + schema: + $ref: "#/components/schemas/EthBigInt" + paramStructure: by-position - name: Filecoin.EthBlockNumber params: [] result: diff --git a/src/rpc/snapshots/forest__rpc__tests__rpc__v2.snap b/src/rpc/snapshots/forest__rpc__tests__rpc__v2.snap index aa7575b18234..d759e4ccfa7b 100644 --- a/src/rpc/snapshots/forest__rpc__tests__rpc__v2.snap +++ b/src/rpc/snapshots/forest__rpc__tests__rpc__v2.snap @@ -125,6 +125,22 @@ methods: schema: $ref: "#/components/schemas/EthAddress" paramStructure: by-position + - name: Filecoin.EthBaseFee + params: [] + result: + name: Filecoin.EthBaseFee.Result + required: true + schema: + $ref: "#/components/schemas/EthBigInt" + paramStructure: by-position + - name: eth_baseFee + params: [] + result: + name: eth_baseFee.Result + required: true + schema: + $ref: "#/components/schemas/EthBigInt" + paramStructure: by-position - name: Filecoin.EthBlockNumber params: [] result: From bbd1e5f0b90329488a18e518cb018cbc872e04b7 Mon Sep 17 00:00:00 2001 From: William Morriss Date: Sat, 9 May 2026 05:51:57 -0500 Subject: [PATCH 2/4] chore: add rpc failure context Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- src/rpc/methods/eth.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/rpc/methods/eth.rs b/src/rpc/methods/eth.rs index bfee4a0b499d..38f809d9097c 100644 --- a/src/rpc/methods/eth.rs +++ b/src/rpc/methods/eth.rs @@ -832,7 +832,8 @@ impl RpcMethod<0> for EthBaseFee { .get(&Height::FireHorse) .context("Missing FireHorse height")? .epoch; - let base_fee = compute_base_fee(ctx.store(), &ts, smoke_height, firehorse_height)?; + let base_fee = compute_base_fee(ctx.store(), &ts, smoke_height, firehorse_height) + .context("failed to compute base fee for eth_baseFee")?; Ok(EthBigInt(base_fee.atto().clone())) } } From 2fc96190e4b6de9717966a1159811dccd2b69f76 Mon Sep 17 00:00:00 2001 From: William Morriss Date: Mon, 11 May 2026 19:50:47 -0500 Subject: [PATCH 3/4] fix(rpc): add EthBaseFee description and CI ignore entry Assisted-by: Claude:claude-sonnet-4-6 --- src/rpc/methods/eth.rs | 2 ++ src/tool/subcommands/api_cmd/test_snapshots_ignored.txt | 1 + 2 files changed, 3 insertions(+) diff --git a/src/rpc/methods/eth.rs b/src/rpc/methods/eth.rs index 38f809d9097c..7f96ca25c173 100644 --- a/src/rpc/methods/eth.rs +++ b/src/rpc/methods/eth.rs @@ -813,6 +813,8 @@ impl RpcMethod<0> for EthBaseFee { const PARAM_NAMES: [&'static str; 0] = []; const API_PATHS: BitFlags = ApiPaths::all_with_v2(); const PERMISSION: Permission = Permission::Read; + const DESCRIPTION: Option<&'static str> = + Some("Returns the calculated base fee of the upcoming tipset in attoFIL"); type Params = (); type Ok = EthBigInt; diff --git a/src/tool/subcommands/api_cmd/test_snapshots_ignored.txt b/src/tool/subcommands/api_cmd/test_snapshots_ignored.txt index d2181d5ccc37..4e7fd4ab7fbb 100644 --- a/src/tool/subcommands/api_cmd/test_snapshots_ignored.txt +++ b/src/tool/subcommands/api_cmd/test_snapshots_ignored.txt @@ -15,6 +15,7 @@ Filecoin.ChainExport Filecoin.ChainGetEvents Filecoin.ChainGetFinalizedTipset Filecoin.ChainSetHead +Filecoin.EthBaseFee Filecoin.EthEstimateGas Filecoin.EthGetFilterChanges Filecoin.EthGetFilterLogs From ef8cd7bcea4bde5d7b5733ef18e9598bdcc036b2 Mon Sep 17 00:00:00 2001 From: William Morriss Date: Wed, 13 May 2026 19:43:03 -0500 Subject: [PATCH 4/4] chore: insta accept --- src/rpc/snapshots/forest__rpc__tests__rpc__v0.snap | 2 ++ src/rpc/snapshots/forest__rpc__tests__rpc__v1.snap | 2 ++ src/rpc/snapshots/forest__rpc__tests__rpc__v2.snap | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/rpc/snapshots/forest__rpc__tests__rpc__v0.snap b/src/rpc/snapshots/forest__rpc__tests__rpc__v0.snap index 041d8ddad437..023cc57db302 100644 --- a/src/rpc/snapshots/forest__rpc__tests__rpc__v0.snap +++ b/src/rpc/snapshots/forest__rpc__tests__rpc__v0.snap @@ -526,6 +526,7 @@ methods: $ref: "#/components/schemas/EthAddress" paramStructure: by-position - name: Filecoin.EthBaseFee + description: Returns the calculated base fee of the upcoming tipset in attoFIL params: [] result: name: Filecoin.EthBaseFee.Result @@ -534,6 +535,7 @@ methods: $ref: "#/components/schemas/EthBigInt" paramStructure: by-position - name: eth_baseFee + description: Returns the calculated base fee of the upcoming tipset in attoFIL params: [] result: name: eth_baseFee.Result diff --git a/src/rpc/snapshots/forest__rpc__tests__rpc__v1.snap b/src/rpc/snapshots/forest__rpc__tests__rpc__v1.snap index 172213db8ce3..d8eecc2fbd54 100644 --- a/src/rpc/snapshots/forest__rpc__tests__rpc__v1.snap +++ b/src/rpc/snapshots/forest__rpc__tests__rpc__v1.snap @@ -522,6 +522,7 @@ methods: $ref: "#/components/schemas/EthAddress" paramStructure: by-position - name: Filecoin.EthBaseFee + description: Returns the calculated base fee of the upcoming tipset in attoFIL params: [] result: name: Filecoin.EthBaseFee.Result @@ -530,6 +531,7 @@ methods: $ref: "#/components/schemas/EthBigInt" paramStructure: by-position - name: eth_baseFee + description: Returns the calculated base fee of the upcoming tipset in attoFIL params: [] result: name: eth_baseFee.Result diff --git a/src/rpc/snapshots/forest__rpc__tests__rpc__v2.snap b/src/rpc/snapshots/forest__rpc__tests__rpc__v2.snap index d759e4ccfa7b..96f90c734bb4 100644 --- a/src/rpc/snapshots/forest__rpc__tests__rpc__v2.snap +++ b/src/rpc/snapshots/forest__rpc__tests__rpc__v2.snap @@ -126,6 +126,7 @@ methods: $ref: "#/components/schemas/EthAddress" paramStructure: by-position - name: Filecoin.EthBaseFee + description: Returns the calculated base fee of the upcoming tipset in attoFIL params: [] result: name: Filecoin.EthBaseFee.Result @@ -134,6 +135,7 @@ methods: $ref: "#/components/schemas/EthBigInt" paramStructure: by-position - name: eth_baseFee + description: Returns the calculated base fee of the upcoming tipset in attoFIL params: [] result: name: eth_baseFee.Result