I’m Josh, CEO of Gas Killer (https://gaskiller.xyz). We replayed four recent updateStateKzgDA calls to the Starknet Core contract on mainnet. Our estimate is that Gas Killer would cut gas by 54–75%, about 306,000 gas per update on average.
Gas Killer runs a contract’s computation off-chain through a network of operators. The operators sign the exact storage changes the function would make, and the contract checks one signature and applies them. A wrong result can be proven, and the operators who signed it are slashed. updateStateKzgDA makes no external calls, so only the Core contract would need to integrate.
The full report, with the transactions and how we measured them:
I would love to hear thoughts from the community on the possibility of an integration like this and maybe hear from the technical team.
Hi Josh, nice to see real mainnet replays behind the numbers. I read the report next to Starknet.sol and a few things stood out.
updateStateKzgDA does make external calls. updateStateInternal calls IFactRegistry(verifier()).isValid(sharpFact), the check that a STARK proof for this exact output was verified. verifyKzgProofs staticcalls the point evaluation precompile (0x0A) once per blob. And processMessages sends the L1 to L2 message fees to the fee collector with a plain call.
That fact registry check is the line that makes Starknet a validity rollup. If operators attest to it instead of the contract reading it, the new state root and the l2ToL1Messages counters stop being backed by the proof and start being backed by operator stake. There is no delay in the Core contract, so StarkGate withdrawals can consume those messages as soon as the update lands, before any fraud proof does. To be safe, the slashable stake would have to cover everything withdrawable during the challenge window.
blobhash(i) only exists inside the blob transaction itself. Operators replaying against the same chain state off-chain can’t read it, so the signature has to commit to the versioned hashes and the contract still has to compare them on-chain.
A split I’d find easier to reason about: keep isValid, the blobhash comparison and the precompile call on-chain (the precompile is a fixed 50,000 gas per blob), and only move the output parsing, hashing and message loops off-chain. Would be great to see the replay numbers for that version, and what exactly sits in the ~58.7k that stays on-chain today.