Assessment reports>Radix>Medium findings>Gas-accounting discrepancy for infinite loops
Category: Optimization

Gas-accounting discrepancy for infinite loops

Medium Severity
Medium Impact
Medium Likelihood

Description

A loop {} instruction takes approximately 5.2 seconds to reach the LimitExceeded error, despite the system's baseline costing rule being designed for 1μs = 100 cost units (implying ~1 second execution for the default 100m limit).

The issue stems from the WASM instrumentation process generating inefficient gas-accounting code for simple loops:

pub fn fn() {
    loop {
      std::hint::black_box(());
    }
}

It generates WASM with the following structure:

loop  ;; label = @2
  i64.const 3529    // Gas cost per iteration
  call 11           // Gas accounting function call
  br 0 (;@2;)       // Branch back to start
end

The overhead of the gas-accounting function call (call 11) dominates the execution time since the original loop body is empty, making the actual runtime significantly exceed the intended cost limits.

Impact

Transactions can consume up to 5x more wall-clock time than intended by the gas limits, and there is also the potential for transaction-processing delays in blocks.

Recommendations

Several approaches can be taken to address this issue:

  1. Gas cost adjustments

    Add a base cost for each gas metering operation. Adjust the gas-cost unit multiplier to better reflect actual execution costs.

  2. Loop optimization

    Implement loop unrolling during instrumentation to reduce the frequency of gas-accounting calls. Here is an example transformation:

loop
  i64.const 14116  // Combined cost for multiple iterations
  call 11
  br 0
end
  1. Gas function optimization

    Optimize the gas-accounting host function for the common case.

Remediation

This issue has been acknowledged by Radix Publishing Limited, and a fix was implemented in commit 86828df1.

Zellic © 2025Back to top ↑