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
runs = expected number of calls per function over the contract lifetime
Low runs → smaller bytecode, costlier per call
High runs → bigger bytecode, cheaper per call
Default 200 balances both
via-IR routes through Yul for stronger optimization
The Reentrancy Reaper attacks — common mistakes
Tuning runs without measuring actual call patterns
Cranking runs very high and hitting the 24KB code-size limit
Assuming via-IR is always better — it is slower to compile
Forgetting the optimizer trades deploy cost for runtime cost
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>