// TINL · WALLET_SECURITY · BLIND_SIGNING
Every wallet presents raw, machine-encoded transaction data for a human to sign — expecting authorization of a machine-readable state transition nobody can actually read. TINL — the Transaction Intent Normalization Layer — decodes that intent, checks it against a policy, and can block the worst patterns before the wallet signs — when it successfully sits in front of the wallet. It is a real safety layer, not a magic shield. Read the plain-language limits below before you install anything from a store.
Where TINL runs: a Chrome browser extension for desktop wallets (MetaMask / Phantom), and an Android mobile app path (in-wallet WalletConnect demo in the same monorepo). Same policy engine; separate install and UAT tracks. Edge and iPhone follow later — see Platform Support below.
Arrived without context? How this sits in a game or platform is the layer above this page: what the Transaction Intent Normalization Layer is, where it can be placed behind an action you already own, and which half of it ships today.
The evaluator connects a real MetaMask + Solana wallet on public testnets — no real funds involved. Requires evaluator access.
// READ_THIS_BEFORE_YOU_INSTALL
If you only remember one thing: always read your wallet's own confirmation screen (MetaMask / Phantom). TINL is an extra guard in front of that screen — not a replacement for it, and not a guarantee that every bad site is stopped.
Full technical write-up for reviewers: in the TINL repo, doc/TINL_THREAT_MODEL_AND_SAFEGUARDS.md and doc/CHROME_WEB_STORE_RELEASE.md. Evaluators: see the decision table in the TINL evaluator brief (WARN/NORMALIZE marked advisory).
// ROADMAP · CLOSING_THE_GAPS
These are real product commitments tracked in the TINL engineering backlog — not vaporware marketing. Until an item is marked shipped, assume the limits above still apply.
| Priority | What users feel | Engineering work | Status |
|---|---|---|---|
| P0 | Warnings and "fix my approval amount" cannot be faked by an evil website | Consent moved out of the page's JavaScript world (MessagePort between the ISOLATED and MAIN worlds, extension-owned popup). Still open: binding proceed to a digest of the exact bytes TINL approved | Partial — the page-forged proceed path was closed 2026-08-08; digest-bind remains |
| P0 | Fewer cases where a site talks to MetaMask/Phantom without TINL noticing | Stronger provider wrap / re-wrap; diagnostics when wrap failed; document residual browser limits | Partial today — residual races documented |
| P1 | Store install cannot be quietly swapped for a tampered engine on disk | Load-time check of the on-device policy engine (WASM hash pin); store-only retail distribution | Partial — the load-time SHA-256 pin ships (Wave 2). Store-only retail distribution does not |
| P1 | First visit to a brand-new site is treated more carefully | Stricter defaults for unknown origins; optional "hostile site mode" (WARN → BLOCK) | Planned |
| P1 | Phone path where evil sites cannot skip TINL or fake consent | In-wallet TINL (WalletConnect) inside the same TINL monorepo — demos on Android/iOS emulators and physical iPhone | Building — monorepo mobile demo (not a separate product repo) |
| P2 | Edge browser + Solana Seeker device polish | Edge extension port; Seeker = Android + Solana Mobile APIs (same app family) | Roadmap |
// MOBILE · IN_WALLET_PATH
The Chrome browser extension is real and useful — and it has honest limits (browser script order; warnings weaker on hostile sites). The architectural fix is not "more clever page scripts." It is a mobile app form factor: TINL on the wallet's own signing path (WalletConnect), before any confirm UI, with no dependency on who loaded first on a website. Android demo first; same monorepo as the extension.
Mobile lives in the same TINL repository as the Chrome extension and policy engine — not a disconnected rewrite. Shared engine: decode + policy in Rust/WASM. Separate package folders so different developers can own extension vs mobile without stepping on each other.
A WalletConnect policy hook already evaluates EVM and Solana session requests and returns proceed / reject / normalize before a wallet should show its sign screen. The next step is a demo wallet app in-repo that calls that hook end-to-end.
Development and demos use Android and iOS emulators and a physical iPhone (dev build / TestFlight-style install as needed). Solana Seeker is the same Android app family plus Solana Mobile APIs later — not a third product from scratch.
The mobile demo wallet is specified to use A3E9's Deep Signal design system — dark navy backgrounds, electric teal actions, Space Grotesk / Inter / JetBrains Mono — so demos and future store builds feel continuous with a3e9.com, not a generic app template. Token reference lives in the TINL repo as doc/A3E9_DEEP_SIGNAL_THEME.md.
// PLATFORM_SUPPORT
TINL is not "a website feature only." v0.1 is the Chrome browser extension: real BLOCK when the wrapper is on the path; WARN/NORMALIZE advisory as a whole against a hostile page (see limits above). v0.2 is the Android mobile app (in-wallet path in the same monorepo) — the route that removes browser script races for users who sign through that app. Edge and Seeker follow the same family, not a rewrite.
The primary browser form factor. Intercepts before either wallet's own extension ever sees the signing request. BLOCK is enforced; WARN and NORMALIZE remain advisory as a whole against a hostile page — the page-forged proceed path was closed in August 2026, but digest-bind and MAIN-world wrap races remain, so wallet confirmation is the backstop for those two. Scope is complete for independent evaluator UAT — not a claim of public Chrome Web Store GA.
A real mobile app form factor in the same TINL monorepo: demo wallet that runs policy on the WalletConnect sign path (no page inject). Android-first on Linux emulators; optional iPhone via Expo EAS later. Edge browser extension port remains planned. Solana Seeker uses the Android app family + Solana Mobile APIs later.
A MetaMask Snap also exists in the TINL codebase, but Snap sandboxing makes it insight/warning-only by design — it can show a warning inside MetaMask's own confirmation screen but cannot block a transaction or rewrite a payload. The browser extension is the only surface that can enforce BLOCK today; its WARN and NORMALIZE decisions remain advisory as a whole against a hostile page — the consent channel left the page's JavaScript world in August 2026, but digest-bind and MAIN-world wrap races are still open — so the wallet's own confirmation screen is the real backstop for those two decisions.
// THE_PROBLEM · BLIND_SIGNING
Token drainer kits, unlimited approvals, and malicious permit signatures aren't exotic exploits — they're the direct, predictable consequence of asking a human to authorize hex they cannot read. Four patterns account for most of it.
The 98.6% figure is specific to Pump.fun, Solana's dominant meme-token launchpad — not every token ever created on Solana. Precision matters more to us than the punchier rounded-off numbers that circulate.
A DApp requests approve(spender, uint256_max) — technically a single line of calldata, functionally a blank check. The wallet shows a hex string. Most users sign it. The spender can now drain that token from the wallet at any point in the future, with no further signature required.
permit() moves approval off-chain into a typed-data signature — no gas, no on-chain trace until it's used. A phishing site can request a permit signature that looks like routine DApp interaction and looks nothing like a transaction, because it isn't one yet.
One signature grants an operator control over an entire NFT collection in a wallet, not just one token. Drainer kits default to this call because it's the highest-value single signature available.
Every wallet on the market presents the same raw, machine-encoded transaction data for human sign-off, regardless of what it actually authorizes. The wallet isn't broken — it's doing exactly what it was built to do. That's the gap TINL closes.
// IN_PLAIN_ENGLISH
Everything below is a real rule from the product engine — not a simplified summary. Decisions shown are the retail-strict posture's real defaults — what a first-time holder gets automatically.
| What's Happening | In Plain English | TINL's Default Move |
|---|---|---|
Unlimited spending permission | A site asks for permission to spend an unlimited amount of one of your tokens — forever, without asking again. Blocking this outright would break the legitimate swap it's usually part of, so TINL proposes a capped, exact-amount version and asks you to confirm — you can still cancel entirely. Always check the wallet confirmation before signing. | NORMALIZE |
Handing over your whole NFT collection | One click grants control over every NFT you own, not just the one you're looking at. | BLOCK |
A "free" signature that isn't free | You're asked to sign a message — no gas fee, easy to mistake for something harmless — that secretly grants unlimited spending power. | NORMALIZE |
A known scam pattern | The action matches something already caught being used by real attackers, not a guess. | BLOCK |
Something TINL has never seen before | The action doesn't match any pattern TINL recognizes — safe or dangerous. | WARN |
A signature request with a strange shape | You're asked to sign something whose structure doesn't match any known safe pattern. | BLOCK |
TINL can't verify who's involved | One of the accounts in a Solana transaction can't be checked. | BLOCK |
Spending past your own limit | The dollar value of what's being approved is higher than the cap you set for yourself. | BLOCK |
A specific, limited approval | A site asks to spend a specific, capped amount — e.g. approving $50 for one swap. | ALLOW |
Sending tokens to someone | You're sending a specific amount directly — the way a normal payment works. | ALLOW |
Taking back a permission | You're revoking access you previously granted. | ALLOW |
A well-known, everyday action | The action matches a standard, widely-used operation TINL already recognizes as safe. | ALLOW |
This reflects the product's real rule set — broader than the simplified evaluator below — and its intended default behavior; a stale value in the deployed profile config is being corrected to match. Every profile is user-adjustable — a trader or developer sees a lighter touch; this is the out-of-the-box default for a first-time holder.
// TINL_ARCHITECTURE
The same separation-of-concerns principle A3E9 applies at the HSM boundary applies here: the interceptor, the normalization engine, and the audit logger are loosely coupled — no single module has complete end-to-end control.
| Layer | Component | What It Does |
|---|---|---|
| Client-Side | Provider Interceptor | A lightweight proxy that wraps the wallet's JSON-RPC surface (eth_sendTransaction, eth_signTypedData_v4, and the Solana equivalents). It halts execution before the signing enclave is invoked and sends the raw request to the Normalization Engine. |
| Execution Layer | Normalization Engine | Identifies exactly what a transaction or signature request will do, checks it against a continuously updated registry of known operations, and evaluates it against the active policy profile — before any signature exists. Runs in one of two deployment modes (below): compiled to WASM and embedded in the wallet, or called as a REST service. |
| Cryptographic Layer | HMAC-Chained Audit Logger | Every policy decision — ALLOW, WARN, BLOCK, or NORMALIZE — is written to an append-only log before the API returns. Each record embeds the previous record's HMAC, so deleting or editing any entry breaks the chain from that point forward. If the write fails, the request fails closed. |
// DUAL-MODE_DEPLOYMENT
A centralized REST API alone adds latency a high-frequency trader can't absorb and a single point of failure a self-sovereign holder shouldn't have to trust. The same core engine compiles to two co-equal deployment targets — neither is a fallback for the other, they target different user classes.
Normalization Engine compiled to WASM, bundled in the wallet/extension
Target: Retail investors, active DeFi traders, developer bots
Provider Interceptor calls an authenticated REST API (A3E9-hosted or self-hosted)
Target: Enterprise custody platforms, institutional wallets, regulated entities
In Mode B, a remote service can become unreachable. What happens next is bound to the active profile, not a system-wide default — the user's own risk tolerance decides.
| Profile | service_outage_behavior | Rationale |
|---|---|---|
| retail_strict | FAIL_TO_LAST_KNOWN_GOOD | Protects without locking the user out |
| trader_balanced | FAIL_TO_LAST_KNOWN_GOOD | Maintains some protection; a trader cannot afford a frozen wallet |
| institutional_strict | FAIL_CLOSED | Regulator-grade: security over availability |
institutional_strict is a Mode-B deployment profile for regulator-grade fail-closed enforcement — documented here for its outage behavior specifically, distinct from the three base profiles below.
// MULTI-CHAIN_DECODING_MODELS
The Normalization Engine abstracts these differences from the Policy Engine — every decoded intent lands in the same shape before evaluation — but the analysis itself is chain-native, not a lowest-common-denominator guess. Both models read the transaction directly, immune to the kind of spoofing that defeats wallet security tools relying on network-based transaction previews.
A transaction carries its full instruction in a single encoded field. TINL identifies exactly which operation it represents and decodes its parameters before evaluating it. Off-chain signature requests — like token-spending permits — are recognized directly from their structure, without needing a network lookup.
A transaction carries a list of instructions, each targeting a different on-chain program. TINL evaluates every instruction in the transaction. Standard token operations are recognized directly, with no network lookup required; less common program interactions are checked against a registry.
Registry-based recognition for less common program interactions is on the roadmap — standard token operations and native transfers are fully enforced today. Anything not yet recognized is treated as unverified rather than silently allowed.
// HYBRID_REGISTRY
New drainer contracts and novel permit variants appear constantly — a registry frozen at release time decays fast. But a purely proprietary registry means standard operations stop working the moment a subscription lapses. TINL splits the difference.
Open-source and community-maintained, covering standard operations across every supported chain. Always available offline, without a subscription — no vendor lock-in.
A continuously updated feed aggregating multiple security research sources: newly identified drainer patterns, zero-day permit variants, and flagged malicious contract addresses, pushed within a 24-hour SLA of identification in the wild.
When TINL encounters an operation in neither registry tier, that's a first-class rule in the same profile matrix as everything else, not a hardcoded default. A retail investor gets a visible warning on an unrecognized action; a developer bot's traffic passes through untouched — either way, the decision is logged to the audit chain.
// TIERED_POLICY_PROFILES
A retail investor needs maximum protection against phishing. A DApp developer or arbitrage operator needs zero friction. Both are the same wallet, running the same engine, pointed at a different profile — a per-rule matrix, not a single global switch. This is the exact matrix the backend enforces.
| Rule | Retail — Strict | Active DeFi User — Balanced | DApp Operator / Bot — Passthrough |
|---|---|---|---|
| ERC-20 unlimited approve() | NORMALIZE | NORMALIZE | ALLOW |
| ERC-20 bounded approve() | ALLOW | ALLOW | ALLOW |
| ERC-20 transfer() | ALLOW | ALLOW | ALLOW |
| ERC-20 transferFrom() (self) | ALLOW | ALLOW | ALLOW |
| ERC-20 transferFrom() pulling a third party's funds | BLOCK | WARN | ALLOW |
| ERC-721 setApprovalForAll() | BLOCK | WARN | ALLOW |
| ERC-721 revoke setApprovalForAll() | ALLOW | ALLOW | ALLOW |
| EIP-2612 unlimited permit | NORMALIZE | WARN | ALLOW |
| EIP-2612 bounded permit | ALLOW | ALLOW | ALLOW |
| EIP-2612 permit with a far-future deadline | WARN | WARN | ALLOW |
| Unrecognized function selector | WARN | ALLOW | ALLOW |
| Native ETH transfer (no calldata) | ALLOW | ALLOW | ALLOW |
| Unrecognized EIP-712 typed data | BLOCK | WARN | ALLOW |
| SPL Token unlimited Approve (delegate) | NORMALIZE | NORMALIZE | ALLOW |
| SPL Token bounded Approve (delegate) | ALLOW | ALLOW | ALLOW |
| SPL Token transfer | ALLOW | ALLOW | ALLOW |
| SPL Token Revoke | ALLOW | ALLOW | ALLOW |
| Unrecognized SPL Token instruction | BLOCK | WARN | ALLOW |
| SPL account not resolvable (address lookup table) | BLOCK | WARN | ALLOW |
| Transaction contains no SPL Token instructions | BLOCK | WARN | ALLOW |
| Native SOL transfer (no other instructions) | ALLOW | ALLOW | ALLOW |
| Solana durable-nonce transaction (no expiry) | WARN | WARN | ALLOW |
| Solana off-chain message signature | ALLOW | ALLOW | ALLOW |
| Solana message is not valid UTF-8 | WARN | ALLOW | ALLOW |
| Solana 'message' is actually a transaction | BLOCK | WARN | ALLOW |
| Token-2022 transfer with a fee extension | WARN | ALLOW | ALLOW |
| Recognized standard function selector | ALLOW | ALLOW | ALLOW |
| Selector flagged by A3E9 Threat Intelligence | BLOCK | WARN | ALLOW |
| Transaction value over the profile's spending cap | BLOCK | WARN | ALLOW |
| Constant-product swap detected | ALLOW | ALLOW | ALLOW |
| Concentrated-liquidity swap detected (not scored offline) | ALLOW | ALLOW | ALLOW |
| Swap detected but could not be priced — not the same as safe | WARN | ALLOW | ALLOW |
| Elevated price impact for pool depth | WARN | WARN | ALLOW |
| Severe price impact — mathematically guaranteed loss | BLOCK | BLOCK | ALLOW |
| A cheaper route existed among the pools supplied | ALLOW | ALLOW | ALLOW |
| How much better the best route was | ALLOW | ALLOW | ALLOW |
Default-hostile posture for a first-time or non-expert holder. Dangerous intents are BLOCKed outright or NORMALIZEd down to a capped amount the user must confirm — never passed through silently.
For an active trader or arbitrage operator who understands the risk but still wants a visible warning before signing.
Zero friction for a DApp developer or CI environment. Every intent is allowed; every decision is still written to the audit chain.
CONTRACT_UNVERIFIED is part of the documented profile schema above; live enforcement requires a contract-verification data source that isn't wired into the engine yet — every other rule shown is enforced today.
A request for an unlimited token allowance — an on-chain approve(), an EIP-2612 permit signature, or an SPL Token delegate Approve on Solana — isn't simply refused, and it isn't silently rewritten either. TINL proposes a modified value / amount field capped to what the transaction actually needs, then discloses what would change — original request, rewritten amount — in the Normalization Consent Dialog: Approve Once, Approve All Future (revocable any time), or Cancel. retail_strict and trader_balanced both normalize the on-chain approve cases — an unlimited allowance left sitting on a contract is a standing drainer target regardless of how careful the user who approved it was. The EIP-2612 permit case stays a plain WARN under trader_balanced: a permit is a one-time-use off-chain signature, not a standing on-chain allowance, so it doesn't carry the same residual risk. When the user accepts the rewrite, what reaches the wallet is the capped payload — and the wallet's own confirmation screen remains the last line of defense. Against a cooperative demo or a wallet-integrated hook that is true end to end; against a hostile page WARN and NORMALIZE stay advisory as a whole — the consent channel itself no longer lives in the page's JavaScript world, but the payload can still be swapped after the decision — so always read the wallet confirmation before signing.
// WHY_THE_USUAL_ADVICE_DOESNT_WORK
They require the user to already know drainers exist, remember to periodically check, and find and correctly operate a third-party revocation site — itself a documented phishing target. This only protects someone who already survived one scare and got paranoid.
Understanding what a burner wallet is, remembering to actually use it instead of the main one, and funding it separately every time is expert workflow discipline — not something a first-time user does correctly under a "mint ends in 2 minutes" countdown.
They cost money, have to be bought and set up before the incident, and even then only stop the signature step — they don't explain what's being approved. A hardware wallet will still make you press the button to sign an unlimited approval you don't understand.
All three assume the user already has the literacy to know they're at risk. The people getting drained are, by definition, the ones who don't. TINL removes the requirement that the user understand anything — the decision moves in front of them automatically, at the moment it matters, in the wallet they already have open. No separate tool, no separate wallet, no separate hardware, no after-the-fact cleanup.
TINL protects against the attack patterns it has rules for: unlimited approvals, malicious permits, setApprovalForAll, and the Solana SPL Approve equivalent. BLOCK is enforced in the browser extension — a blocked request never reaches the wallet. WARN and NORMALIZE remain advisory as a whole against a hostile page. The page-forged proceed path is closed: since 2026-08-08 consent resolves over a MessagePort between the ISOLATED and MAIN worlds, in an extension-owned popup a page cannot answer for itself. What keeps the pair advisory is what is still open — the decision is not yet bound to a digest of the exact bytes, and MAIN-world wrap and inject races remain — so the wallet's own confirmation screen is still the real backstop for those two decisions, and no interception percentage is claimed. TINL also does not protect against a user manually typing an amount into a legitimate-looking-but-malicious DApp UI with no drainer signature involved, address-poisoning scams, fake airdrops the user actively chooses to interact with, or a WARN the user clicks through anyway. It narrows the blind-signing gap. It is not a complete answer to social-engineering loss.
The TINL Evaluator (separate from the HSM evaluator) includes a live wallet demo: connect a real MetaMask (Sepolia) and Phantom (Solana devnet), switch policy profiles, and watch TINL's own decision popup appear before the wallet's real confirmation dialog — for every ALLOW, WARN, BLOCK, and NORMALIZE case.