This site is being rebuilt and some pages are out of date. For current details, write to [email protected]. This notice goes away when the rebuild is done.

No analytics unless you allow it, no tracking. This site keeps in your browser the language you pick, the theme, its colour, which site you chose, the currency on the pricing page and that you closed this notice; signing in adds session cookies. The legal page has the details.

Sign in

Radar · Solidity · Archive · Week 28 · Jul 6 – 12, 2026

Yul Optimizer Call Graph Fix

Nice to knowecosystem

What changed
Fixed call graph analysis in the Yul optimizer.
Production impact
The source does not say.
Try it
Run a Yul contract that previously caused incorrect call graph behavior.
Source
github.com/argotorg/solidity/releases/tag/v0.8.36

Understand it, then run it

The Solidity compiler has a component called the Yul optimizer that rewrites low‑level code to make contracts faster. In version 0.8.36 the optimizer had a bug: when two functions called each other, the optimizer sometimes failed to recognize that they were part of a recursive cycle. That meant the optimizer could miss opportunities to simplify the code or, in rare cases, generate incorrect bytecode. The fix ensures that the optimizer now correctly detects mutually recursive functions and treats them as a single recursive group.

Run it now

Todaysolidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.37;

/// @notice Demonstrates that the Yul optimizer now correctly handles mutually recursive functions.
/// The contract compiles and runs on 0.8.37, which includes the 0.8.36 fix.
contract Main {
    /// @dev Recursively computes the factorial of `n` using two mutually recursive functions.
    function fact(uint256 n) public pure returns (uint256) {
        return _factHelper(n);
    }

    /// @dev Helper that calls the other helper to illustrate recursion.
    function _factHelper(uint256 n) internal pure returns (uint256) {
        if (n == 0) return 1;
        return _factHelper2(n - 1) * n;
    }

    /// @dev Second helper that calls the first helper.
    function _factHelper2(uint256 n) internal pure returns (uint256) {
        if (n == 0) return 1;
        return _factHelper(n - 1) * n;
    }
}

Tests

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.37;
import "./main.sol";

contract MainTest {
    Main main;

    constructor() {
        main = new Main();
    }

    function test_factZero() public {
        require(main.fact(0) == 1, "fact(0) should be 1");
    }

    function test_factFive() public {
        require(main.fact(5) == 120, "fact(5) should be 120");
    }
}

The test report when we ran it on Solidity 0.8.37 (solc)

2 of 2 tests passed.

  • test_factFive27,651 gas
  • test_factZero26,497 gas
  • MainTest: 940 bytes of bytecode, deployed for 282,646 gas

solc 0.8.37 · prague

Run sends this program (for Solidity, the contract and its tests) to our own sandbox, where it is compiled and run once, with no network, and what it printed or the test report comes back here. Nothing is kept. Runs are counted per visitor for the day so everyone gets a turn; the details are on the legal page.

Written by gpt-oss-20b from the linked source · claims checked against the sources · archive, not individually reviewed