Evzi
Read between the transactions
The problem Evzi solves
Wallet popups ask "approve this transaction?" — a question users can't actually answer. They can't read the calldata, can't tell whether the contract is real, can't tell whether the website is who it claims to be, and have no idea what will happen if they sign. This is how drainers work: the page says "free NFT mint", the wallet shows opaque hex, and the user signs.
Evzi closes that loop. Before any signature reaches a wallet, we infer what the user is trying to do (from page context, click target, and a small LLM), decode the calldata or EIP-712 typed data into a structured action, look the contract up against a hand-curated cross-chain registry, query Sourcify for source verification, simulate the transaction against a live Tenderly fork, classify the origin domain against known phishing patterns, and ask an LLM judge to compare every signal against the stated intent.
The verdict is one sentence and a checklist of every signal — so the user sees the work, learns the patterns, and can disagree. Two-way constraint: the LLM can't soften a deterministic DANGER (UNLIMITED_APPROVAL stays DANGER), and can't escalate a vetted protocol to DANGER on a hunch.
What we explicitly catch today:
- "Free NFT mint" that's actually
USDC.approve(0xdEaD…, MAX_UINT256)— page description doesn't match the calldata. - Permit2 batch-transfer signatures to unknown spenders — the off-chain drainer that bypasses simulation entirely.
- Lookalike origin domains:
unisvvap.org, punycode/IDN homographs,aavve.com. - Unverified-but-canonical routers — fresh Uniswap deployments that outpace Sourcify verification.
Challenges we ran into
Three problems stand out.
1. Off-chain Permit2 batch-transfer drainers. The worst class of attack today because they bypass simulation entirely — there's no on-chain transaction to simulate, just a signed message that authorizes a third party to move multiple tokens. We built a typed-data decoder that recognizes Permit2 single + batch shapes (and Seaport zero-price offers) and explicitly emits PERMIT2_SPENDER_UNKNOWN as a deterministic finding the LLM can't soften.
2. The "verified vs trusted" tension. Sourcify is the right way to check source-availability, but Uniswap deploys faster than Sourcify verifies — so a strictly Sourcify-driven verdict would flag the most-used router on Ethereum as suspicious. We treat the protocol registry and Sourcify as separate signals and explain the trade-off in the verdict: "Sourcify: not verified, but this matches a canonical Uniswap UR address." The end user sees both facts and the resolution.
3. Two-way LLM constraint. We give the LLM judge enough context to flag subtle intent/action mismatches the deterministic layer can't articulate. But we don't let it soften deterministic DANGERs (UNLIMITED_APPROVAL stays DANGER even if the LLM finds the request "reasonable"), and we don't let it escalate vetted protocols based on a hunch. Safety floor + trust ceiling.
Bonus: Uniswap UR sentinel addresses (0x…0001 = msg.sender, 0x…0002 = router-self) used to be flagged as "third-party drain" by naive analyzers. We resolve them so normal Uniswap routing reads as normal.
Tracks Applied (4)
Ethereum Core
Future Society
Sourcify Bounty
Sourcify
Best Agentic Venture
Umia
