freecoding.school100% FREE · NO SIGNUP
The EVM CoreISSUE #34 of 48

the optimizer · runs · via-ir pipeline

SoliaVSThe Reentrancy Reaper
Solia saysThe optimizer’s "runs" parameter tunes the bytecode vs runtime-cost trade-off; via-IR routes through Yul for better cross-function optimization at the cost of build time.

The Solidity compiler’s optimizer takes two knobs. runs tells it how many times each function is expected to be called over the contract’s lifetime. Low runs = smaller bytecode, expensive per-call; high runs = bigger bytecode, cheaper per-call. The default 200 balances both. The right value depends on whether you care more about deploy cost (low) or operational cost (high).

via-IR routes compilation through a Yul intermediate representation before generating bytecode, enabling cross-function inlining and dead-code elimination the old pipeline could not do. Slower to compile, often noticeably cheaper at runtime. The demo models the deploy vs per-call trade-off across a range of runs values (stylized — real optimizer effect is contract-specific).

Power-ups you unlock

The Reentrancy Reaper attacks — common mistakes

Boss battleModel the total gas (deploy + N calls) at runs = 1, 200, and 10000 for a contract expected to be called 10000 times.

Example code

<!doctype html><html><head><meta charset="utf-8"></head>
<body style="background:#06040d;color:#e6e0ff;font-family:monospace;padding:20px"><pre id="o"></pre>
<script>
// STYLIZED cost model: real optimizer effect is non-linear and contract-specific.
function model(runs){
  const deployBytes = 8000 + Math.min(runs, 10000) * 0.6;     // more runs → more inlined bytecode
  const perCall     = 8000 - Math.min(runs, 10000) * 0.5;     // more runs → less work per call
  return { deployBytes, perCall };
}
const expectedCalls = 10000;
const cases = [1, 200, 10000];
const rows = cases.map(r => {
  const m = model(r);
  const deployGas = Math.round(m.deployBytes * 200);
  const runtimeGas = Math.round(m.perCall * expectedCalls);
  const total = deployGas + runtimeGas;
  return '  runs=' + String(r).padStart(5) + '  deploy=' + deployGas.toLocaleString().padStart(11) + '  runtime=' + runtimeGas.toLocaleString().padStart(11) + '  total=' + total.toLocaleString();
});
document.getElementById('o').textContent = [
  'optimizer trade-off (' + expectedCalls.toLocaleString() + ' expected calls, stylized model):',
  ...rows,
  '',
  'low runs = small deploy + costly calls',
  'high runs = bigger deploy + cheaper calls',
  'tune runs to your real call pattern'
].join('\n');
</script></body></html>
▶ Open the interactive comic issue
‹ Immutable Vs Constant · Bytecode PlacementCreate2 Factories · Counterfactual Deploys ›