tolk-less
May 22, 2026 · View on GitHub
tolk-less is a Tolk compiler fuzzer. It demonstrates a zero-effort way to find nasty math bugs in the compiler.
- Key idea: sound EMI mutations + bitwise diff of TVM outputs across Tolk/FunC × optimized/non-optimized builds
- Target: arithmetic miscompilations
- Effort: <1 hour to vibecode a 1k-loc script, 2 hours to execute and review
- Result: 13 semantic drifts in arithmetic, 6 ICEs
Usage
Clone with submodules, build ./third-party/ton and execute:
SEED=0 MKL=10 MKH=20 N=195000 MD=4 MK=3 Z3=1 ABORT=0 ZINP=1 ZIT=500
python3 tl.py
Findings
⚠️ Note: No Tolk contracts on mainnet, no bug bounty coverage. Nothing exploitable.
Commit: 4539cfab
Miscompiles
- assert-K-eq-flipped —
assert(K != 0)always throws,assert(K == 0)always passes - bitwise-noop-keeps-denorm —
K | 0/K & -1preserve a BigInt denorm and re-arm the const-shift bug family - cancel-from-both-sides —
K > (K - a)rewritten toK > -a - const-shift-eq-broken —
(K + 0) == Kfolds to false - drop-const-from-add —
a + Ksilently drops K, body becomes empty - if-K-eq-0 —
if (K == 0) { throw }always throws even when K is non-zero - muldiv-zeroed —
mulDivFloor/Ceil/Round(K, a, b)folds to 0 - neg-K-vs-K-cmp —
(-K) < Kfolds to wrong constant - pushnegpow2-zero — Tolk emits invalid
0 PUSHNEGPOW2bytecode - repeat-skipped —
repeat (K) { body }body silently elided - ternary-inverted —
(K != 0) ? a : bpicks the wrong branch - throwarg-bigimm — Tolk emits
<big-K> THROWARG, Fift assembler rejects - while-skipped —
while (K != 0 && cond) { body }body silently dropped
ICE
- tolk-bool-and-chain —
true && true && true && true && exprcrashes Tolk (tolk.h:892) - tolk-codegen-208 — nested
!((true||false) != true)shape crashes Tolk (codegen.cpp:208) - tolk-codegen-578 — duplicated
false ? K : aternary +(0<<3)>>3shape crashes Tolk (codegen.cpp:578) - func-stack-validate —
a + ((a + (-1 ? 0 : 1)) * 0)crashes FunC (func.h:1622) - func-codegen-168 —
(a + (0 ? c : a*0)) * 0crashes FunC (codegen.cpp:168)
Further work
If you are serious about spending time on this, look at:
- Better oracles: anything is better than the FunC oracle, some sane alternatives:
- hand-written concrete interpreter
- translation validation TVM/Fift→SMT for equivalence checks