Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

AlphaPrecompile view functions perform Substrate work without charging EVM gas #2741

Open
Assignees

Description

Description

The AlphaPrecompile (precompiles/src/alpha.rs, EVM address 2056) exposes several #[precompile::view] functions that perform non-trivial Substrate-side work — storage reads, full swap simulations through transactional::with_transaction, and unbounded iteration over all subnets — without calling handle.record_cost(...) to charge the EVM caller for that work.

Compare this against neighbouring precompiles which explicitly charge per DB read:

  • precompiles/src/subnet.rs:173 (get_network_registration_block) calls handle.record_cost(RuntimeHelper::<R>::db_read_gas_cost())?;
  • precompiles/src/staking.rs:499-500, 525-526, 550-552, 581-583, 616-618 carefully record one record_cost per DB read / write.

AlphaPrecompile, in the same workspace, does NOT:

  • get_alpha_price (alpha.rs:35-47) — 1+ reads, uncharged.
  • get_moving_alpha_price (alpha.rs:49-61) — read, uncharged.
  • get_tao_in_pool, get_alpha_in_pool, get_alpha_out_pool, get_alpha_issuance, get_tao_weight, get_ck_burn, get_subnet_mechanism, get_ema_price_halving_blocks, get_subnet_volume, get_tao_in_emission, get_alpha_in_emission, get_alpha_out_emission — all simple reads, all uncharged.
  • sim_swap_tao_for_alpha (alpha.rs:101-115) and sim_swap_alpha_for_tao (alpha.rs:117-131) — invoke SwapHandler::sim_swapdo_swap(simulate=true)transactional::with_transactionswap_inner. Inside the rollback transaction this performs: nested transactional layer push/pop, maybe_initialize_palswap (read+conditional 2 writes, even though rolled back), reserve reads, balancer math, SwapStep::execute (more reads). All uncharged.
  • get_sum_alpha_price (alpha.rs:190-215) — iterates NetworksAdded::<R>::iter() and per-iteration calls current_alpha_price (which reads SwapBalancer + SubnetTAO + SubnetAlphaIn). With the default SubnetLimit = 128 (pallets/subtensor/src/lib.rs:1092), this is up to ~128*3 ≈ 384 trie reads per call. All uncharged. Even worse, NetworksAdded::iter() is a full prefix iteration, which uses additional read cost per entry beyond the named storage map (one read per iteration step on top of the key decoding).

Recommendation

For each #[precompile::view] function in precompiles/src/alpha.rs, add handle.record_cost(RuntimeHelper::<R>::db_read_gas_cost())? calls reflecting the actual number of storage reads performed, mirroring the pattern in precompiles/src/staking.rs and precompiles/src/subnet.rs:173. For get_sum_alpha_price and sim_swap_*, the charge must scale with iteration / nested work — i.e. charge inside the loop, and charge for the writes done by maybe_initialize_palswap that would be rolled back but still consume execution weight.

Also consider returning a static extra_cost from is_precompile for compute-heavy precompile addresses, or wrapping these specific selectors with an additional gas-floor guard at dispatcher level.

Metadata

Metadata

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      AltStyle によって変換されたページ (->オリジナル) /