Skip to content

Translate Enso delegate routes into guarded Scripter batches - #4

Draft
0xdewy wants to merge 8 commits into
release/multicall-hardeningfrom
experiment/enso-routes
Draft

0xdewy wants to merge 8 commits into
release/multicall-hardeningfrom
experiment/enso-routes

Conversation

@0xdewy

@0xdewy 0xdewy commented Sep 6, 2026

Copy link
Copy Markdown
Owner

Problem

Enso's delegate routes contain a Weiroll command program, but executing that program through Enso's VM gives up the gas advantage of MulticallScripter. Passing the API response straight to another executor would also trust third-party targets, approvals, recipients, ETH values, and format upgrades without an application-level authorization boundary.

This PR decodes the supported Weiroll subset into direct Scripter calls and adds fail-closed checks before a batch can be signed. It is stacked on #3 (release/multicall-hardening).

What changed

  • Add inspectEnsoDelegateRoute for non-authorizing inspection and buildEnsoDelegateBatch for policy-checked construction.
  • Translate calls, static calls, fixed-value calls, literal dynamic arguments, extended commands, pre-transactions, and scalar return chaining. Scalar fan-out above three destinations is expanded through the identity precompile.
  • Pin compatibility to Ethereum, Enso Weiroll 1.4.1 at commit 9002501, and the exact deployed Enso EIP-7702 implementation code hash. Unknown chains or changed bytecode fail until reviewed.
  • Require a maximum aggregate ETH spend, expected input/output assets and recipient, an independent target allowlist, and explicit bounds for recognized approvals. Permit-style authorization is rejected.
  • Return a hash of the complete source transaction sequence and require same-block Enso/Scripter simulations with exact input/output balance deltas, minimum output, and maximum input before signing.
  • Add a versioned live-query matrix covering a direct swap, vault deposit, LP zap, and 2/4/8-leg bundles. The manual fork workflow runs it when ENSO_API_KEY is configured; no key or API response is committed.
  • Document the supported subset, signing workflow, trust boundary, and unsupported semantics.

Validation

  • cd js && bun test: 80 passed, including 1,024 generated fan-out programs and 8,274 assertions.
  • cd rust && cargo test && cargo clippy --all-targets -- -D warnings: 21 passed; Clippy clean.
  • forge test --summary: 126 passed; the two RPC-dependent swap tests skipped there and passed in the fork rehearsal.
  • forge snapshot --fuzz-seed 0x51c7 --check --tolerance 5 ...: 109 gas checks passed with no contract gas regression.
  • uv run script/check-memory-bounds.py: all four scoped bounds queries were unsatisfiable.
  • SKIP_ENSO_LIVE=1 bash script/rehearse.sh at Ethereum block 25,920,099: deployment, protocol, rollback, EIP-7702, bytecode-integrity, and six Solidity fork checks passed.
  • Eight generated programs ran against Enso's deployed Weiroll VM from identical fork state. Outputs matched in every case and Scripter was cheaper in every case; at fan-out 20, gas was 105,620 versus 136,611, saving 30,991 gas (22.68%).

Review notes

The adapter deliberately rejects delegatecall, computed ETH values, runtime-sized returned values, state replacement, composite Weiroll indices, permit and Permit2 authorization, and non-Ethereum routes. Address-presence checks are tripwires rather than proof of arbitrary calldata semantics, so an independent target registry and exact fork simulation remain required. This code has extensive internal and differential testing but has not received an independent security audit; keep the PR in draft until another reviewer examines the final decoder and policy boundary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant