Skip to content

fix: estimate gas for bounded substrate accounts#1409

Open
mrq1911 wants to merge 5 commits intomasterfrom
eth_estimate_fix
Open

fix: estimate gas for bounded substrate accounts#1409
mrq1911 wants to merge 5 commits intomasterfrom
eth_estimate_fix

Conversation

@mrq1911
Copy link
Copy Markdown
Member

@mrq1911 mrq1911 commented Apr 5, 2026

problem

the frontier fork (moonbeam-foundation/frontier, branch moonbeam-polkadot-stable2506) with rpc-binary-search-estimate feature enabled since #1387

with this feature, eth_estimateGas sets estimate = false during its binary search loop to get accurate gas measurements. the original check (if !estimate && ...) assumed estimate = true would be passed for gas estimation, which was true with the default frontier behavior but not with this feature flag.

so after enabling rpc-binary-search-estimate, eth_estimateGas from bound addresses started returning BoundAddressCannotBeUsed — same error as eth_call.

fix

moved the BoundAddressCannotBeUsed check from the runtime api (EthereumRuntimeRPCApi::call/create) to pre_dispatch_self_contained, which only runs for actual on-chain ethereum transactions.

the runtime api is only called from rpc (eth_call, eth_estimateGas), and with the rpc-binary-search-estimate frontier feature, estimate is always false — causing all rpc calls from bound addresses to fail.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 5, 2026

Crate versions that have been updated:

  • runtime-integration-tests: v1.75.1 -> v1.75.2
  • pallet-evm-accounts: v1.6.0 -> v1.6.1
  • hydradx-runtime: v405.0.0 -> v406.0.0

Runtime version has been increased.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adjusts HydraDX’s Frontier integration to ensure eth_estimateGas and other RPC calls work correctly when the Frontier rpc-binary-search-estimate feature forces estimate = false, while still preventing on-chain Ethereum transactions from using bound Substrate accounts.

Changes:

  • Move the “bound address cannot be used” restriction from the Frontier runtime RPC APIs (call/create) to self-contained extrinsic pre-dispatch validation for on-chain Ethereum transactions.
  • Update integration tests to assert RPC calls succeed for bound addresses (for both estimate=true/false) and that on-chain Ethereum transactions are rejected when the sender is bound.
  • Expose AccountExtension storage map publicly to enable direct storage setup in integration tests.

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 2 comments.

File Description
runtime/hydradx/src/lib.rs Enforces bound-address restriction at self-contained tx pre-dispatch; removes bound-address restriction from RPC runtime APIs.
pallets/evm-accounts/src/lib.rs Makes AccountExtension storage type public (used by integration tests).
integration-tests/src/evm.rs Updates/extends tests to cover RPC behavior from bound addresses and on-chain tx rejection behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

RuntimeCall::Ethereum(call) => {
// don't allow on-chain EVM transactions from a bound address
if EVMAccounts::bound_account_id(*info).is_some() {
return Some(Err(TransactionValidityError::Invalid(InvalidTransaction::BadSigner)));
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

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

InvalidTransaction::BadSigner is typically reserved for signature/account mismatches. Here the signature can be valid, but the sender is rejected solely because the address is bound; using BadSigner can be misleading for clients and any error mapping/telemetry. Consider using a more semantically correct validity error (e.g., InvalidTransaction::Call or a Custom code) to represent the bound-address restriction distinctly.

Suggested change
return Some(Err(TransactionValidityError::Invalid(InvalidTransaction::BadSigner)));
return Some(Err(TransactionValidityError::Invalid(InvalidTransaction::Call)));

Copilot uses AI. Check for mistakes.
Comment on lines +137 to 138
pub type AccountExtension<T: Config> = StorageMap<_, Blake2_128Concat, EvmAddress, AccountIdLast12Bytes>;

Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

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

Changing AccountExtension from pub(super) to pub exposes the raw storage map as part of the pallet’s Rust API, making it easier for other runtime code to write to it directly and bypass invariants/events (inc_sufficients, Bound event, etc.). If this is only needed for integration tests, prefer a narrowly-scoped test helper (e.g., a function behind a dedicated cfg(feature = "testing")/cfg(test) or a helper in the integration test harness that writes storage by key) to avoid broadening the pallet’s public surface area.

Suggested change
pub type AccountExtension<T: Config> = StorageMap<_, Blake2_128Concat, EvmAddress, AccountIdLast12Bytes>;
pub(super) type AccountExtension<T: Config> = StorageMap<_, Blake2_128Concat, EvmAddress, AccountIdLast12Bytes>;
#[cfg(any(test, feature = "testing"))]
impl<T: Config> Pallet<T> {
/// Test-only helper for seeding account-extension storage without exposing the
/// raw storage map in the pallet's public production API.
pub fn insert_account_extension_for_testing(evm_address: EvmAddress, account_extension: AccountIdLast12Bytes) {
AccountExtension::<T>::insert(evm_address, account_extension);
}
}

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 5, 2026

Quick benchmark at commit a46e75c has been executed successfully.
View results

@mrq1911 mrq1911 enabled auto-merge April 10, 2026 13:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants