Repository navigation
feat(typewriter): reject apps whose mutations can execute differently offchain - #120
Merged
Merged
Conversation
… offchain parseSolidity now walks every function, modifier, and operator reachable from the app contract's functions and each XMutation.execute, and rejects block.* (except chainid), blockhash/blobhash, msg.*/tx.*, gasleft, external calls, account members (.call, .balance, .code, ...), contract creation, selfdestruct, inline assembly, and use of Typewriter's own state and functions. Typewriter.sol is trusted. The README's Determinism section now matches what is enforced. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ing checks Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kyscott18
marked this pull request as ready for review
November 2, 2026 21:07
A constructor could store a function in state that mutations then call, bypassing the determinism check, which doesn't walk the constructor. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up to #116.
parseSoliditynow rejects app code that can compute a different result in typewriter's offchain revm than onchain. The check runs on the solc AST, not the bytecode. Bytecode mixes in Typewriter.sol, which itself usesTIMESTAMP,CHAINID,CALLER, aSTATICCALLto P256, and assembly. Separating app opcodes from those would need source maps, which depend on the optimizer. The AST also lets the error name the function and the expression.Scope: every function, modifier, and user-defined operator reachable from the app contract's functions (constructor excluded) and each
XMutation.execute. It follows calls,using … forattached calls, operators, and function references. Typewriter.sol is trusted and skipped. Library code a mutation never reaches, such as an unused assembly helper, isn't checked.What's rejected, and why (offchain env from
typewriter-evm/src/harness.rsandtypewriter.ts)block.*exceptchainid,number,timestamp;blockhash,blobhashmsg.*,tx.*forceExecutereplaysfrom: app.account.address; onchain anyone calls it. Settlement batches calldata.tx.gaspriceis 0 offchaingasleft()gas_limit(u64::MAX).call/.staticcall/.delegatecall/.send/.transfer,.balance,.code/.codehash,new C(),selfdestructgas(),coinbase(),call…)accounts,queue,executionIndex,_execute, …SCHEDULERstay allowedstateErrors name the function and the expression, e.g.
Helpers.time uses `block.timestamp`, which can differ between offchain and onchain execution.Behavior change vs. the old README
block.numberandblock.timestampstay allowed, as before. They lag the inclusion block, so a check that reverts (e.g. a deadline) is safe: typewriter drops mutations whose settlement reverts. A branch that doesn't revert can still give different state offchain and onchain. The README says this.msg.sender/tx.originare now rejected. The README called them "stable", but offchainforceExecuteruns as the scheduler (typewriter.ts:1060), while onchain the caller is whoever forces it.No app (Token, OrderBook, Assessment) uses any rejected construct. All three load through
loadSolidityApp(forge) unchanged.Test plan
bun test src: 93 pass, 3 skip, 0 failexecute, and reachability (dispatch, transitive call, attached call, operator, library modifier, Typewriter internals, plus allowed:block.chainid,address(this),keccak256,verifySignature,SCHEDULER, unused library assembly)tsc --noEmit,biome checkloadSolidityApp🤖 Generated with Claude Code