{
  "id": "m2-send-ens",
  "title": "The ENS Send",
  "extends": "m1-send-metamask",
  "context": {
    "wallet": "MetaMask extension",
    "platform": "desktop Chrome",
    "network": "mainnet",
    "settings": "defaults",
    "captures": [
      {
        "run": "20260824-191831-send-ens-mainnet",
        "tx": "0x8ef0a2289537d3b378b168e10a1fff9086ebc52d5ebc5cddf176c5c87288a3cf"
      }
    ],
    "observed": "2026-08-24"
  },
  "_comment": "Prepends the resolve phase, then runs the whole M1 track. The recipient lane opens at EN1 — the resolver's answer IS the destination.",
  "prepend_steps": [
    {
      "id": "resolve-ens",
      "phase": "resolve",
      "name": "Infura · resolve name",
      "host": "mainnet.infura.io",
      "actor": "infura",
      "purpose": "eth_call to ENS registry + resolver",
      "need": "RT",
      "carries": [
        "ip",
        "ens_name"
      ],
      "births": [
        "recipient"
      ],
      "returns": "the address you send to",
      "can_block": true,
      "on_failure": "blocks",
      "worst_lie": {
        "outcome": "funds_lost",
        "note": "a lying answer sends the money to the wrong address"
      },
      "removable_by": "custom_rpc",
      "provenance": {
        "status": "observed",
        "ref": "20260821-214213-send-ens · core/ens-controller"
      },
      "notes": "Direct eth_call, no MetaMask name API in front by default; local name cache.",
      "tx_input": "field",
      "fixed_by": [
        "verifiable-rpc",
        "private-rpc"
      ]
    },
    {
      "id": "ccip-gateway",
      "phase": "resolve",
      "name": "CCIP gateway (offchain names)",
      "host": "(gateway URL chosen by the name issuer)",
      "actor": "ccip-issuer",
      "purpose": "CCIP-Read resolution for offchain subnames",
      "need": "RT",
      "carries": [
        "ip",
        "ens_name"
      ],
      "births": [
        "recipient"
      ],
      "returns": "the address you send to",
      "can_block": true,
      "on_failure": "blocks",
      "worst_lie": {
        "outcome": "funds_lost",
        "note": "the issuer's answer is the destination"
      },
      "removable_by": "none",
      "provenance": {
        "status": "inferred",
        "ref": "CCIP-Read spec; not yet traced in MetaMask source"
      },
      "notes": "Only fires for offchain subnames. The issuer learns who is paying this name.",
      "tx_input": "field",
      "optional": true
    },
    {
      "id": "avatar-fetch",
      "phase": "resolve",
      "name": "Avatar fetch — the trap",
      "host": "(any URL the name owner set)",
      "actor": "avatar-host",
      "purpose": "Fetch the name's avatar record",
      "need": "T",
      "carries": [
        "ip",
        "ens_name"
      ],
      "returns": "a profile picture",
      "can_block": false,
      "on_failure": "silent",
      "worst_lie": {
        "outcome": "none",
        "note": "pure surveillance: whoever set the record harvests your IP"
      },
      "removable_by": "none",
      "provenance": {
        "status": "inferred",
        "ref": "ENS avatar text record mechanics; wallet fetch path not yet traced"
      },
      "notes": "The avatar record can point at any server."
    }
  ],
  "own_node": {
    "node": "192.168.68.54",
    "runs": [
      "20260924-212931-send-ens-localnode"
    ],
    "steps": {
      "resolve-ens": {
        "state": "local",
        "ref": "192.168.68.54 · eth_call; mainnet.infura.io got 0 after switch"
      },
      "ccip-gateway": {
        "state": "unseen",
        "ref": "not in these runs"
      },
      "avatar-fetch": {
        "state": "unseen",
        "ref": "not in these runs"
      },
      "ext-update": {
        "state": "unseen",
        "ref": "clients2.google.com seen before the switch only, not after"
      },
      "feature-flags": {
        "state": "out",
        "ref": "client-config.api.cx.metamask.io · 1 req after switch"
      },
      "phishing-list": {
        "state": "unseen",
        "ref": "phishing-detection.api.cx.metamask.io seen before the switch only, not after"
      },
      "c2-list": {
        "state": "unseen",
        "ref": "client-side-detection.api.cx.metamask.io seen before the switch only, not after"
      },
      "token-list": {
        "state": "unseen",
        "ref": "token.api.cx.metamask.io seen before the switch only, not after"
      },
      "spot-prices": {
        "state": "out",
        "ref": "price.api.cx.metamask.io · 7 req after switch · /v3/spot-prices"
      },
      "fiat-rates": {
        "state": "unseen",
        "ref": "price.api.cx.metamask.io still contacted (7 req) but this exact call wasn't singled out"
      },
      "accounts-balances": {
        "state": "out",
        "ref": "accounts.api.cx.metamask.io · 8 req after switch · /v4/multiaccount/balances"
      },
      "balance-fallback": {
        "state": "local",
        "ref": "192.168.68.54 · eth_call; mainnet.infura.io got 0 after switch"
      },
      "nft-detection": {
        "state": "unseen",
        "ref": "nft.api.cx.metamask.io seen before the switch only, not after"
      },
      "defi-positions": {
        "state": "unseen",
        "ref": "defiadapters.api.cx.metamask.io seen before the switch only, not after"
      },
      "icons": {
        "state": "unseen",
        "ref": "static.cx.metamask.io seen before the switch only, not after"
      },
      "block-poll": {
        "state": "local",
        "ref": "192.168.68.54 · eth_blockNumber; mainnet.infura.io got 0 after switch"
      },
      "segment": {
        "state": "out",
        "ref": "api.segment.io · 4 req after switch"
      },
      "sentry": {
        "state": "out",
        "ref": "sentry.io · 21 req after switch"
      },
      "screen-recipient": {
        "state": "out",
        "ref": "security-alerts.api.cx.metamask.io · 2 req after switch · /address/evm/scan"
      },
      "nonce": {
        "state": "unseen",
        "ref": "mainnet.infura.io seen before the switch only, not after"
      },
      "gas-fees": {
        "state": "out",
        "ref": "gas.api.cx.metamask.io · 2 req after switch · suggestedgasfees"
      },
      "estimate-gas": {
        "state": "local",
        "ref": "192.168.68.54 · eth_estimateGas; mainnet.infura.io got 0 after switch"
      },
      "simulation": {
        "state": "out",
        "ref": "tx-sentinel-ethereum-mainnet.api.cx.metamask.io · 6 req after switch"
      },
      "security-alert": {
        "state": "out",
        "ref": "security-alerts.api.cx.metamask.io · 2 req after switch · /validate"
      },
      "stx-broadcast": {
        "state": "unseen",
        "ref": "not in these runs"
      },
      "inclusion": {
        "state": "unseen",
        "ref": "not in these runs"
      },
      "stx-status": {
        "state": "unseen",
        "ref": "not in these runs"
      },
      "receipt-poll": {
        "state": "unseen",
        "ref": "mainnet.infura.io seen before the switch only, not after"
      },
      "etherscan-check": {
        "state": "unseen",
        "ref": "not in these runs"
      },
      "balance-refresh": {
        "state": "unseen",
        "ref": "accounts.api.cx.metamask.io still contacted (8 req) but this exact call wasn't singled out"
      }
    },
    "unmapped": [
      "tron-mainnet.infura.io",
      "solana-mainnet.infura.io",
      "bitcoin-mainnet.infura.io",
      "user-storage.api.cx.metamask.io",
      "monad-mainnet.infura.io",
      "subscription.api.cx.metamask.io",
      "tokens.api.cx.metamask.io",
      "testnet-rpc.monad.xyz",
      "sepolia.infura.io",
      "linea-sepolia.infura.io",
      "api.merkl.xyz",
      "carrot.megaeth.com",
      "base-mainnet.infura.io",
      "arbitrum-mainnet.infura.io",
      "optimism-mainnet.infura.io",
      "bsc-mainnet.infura.io",
      "linea-mainnet.infura.io",
      "polygon-mainnet.infura.io",
      "notification.api.cx.metamask.io",
      "geolocation.api.cx.metamask.io",
      "on-ramp-cache.api.cx.metamask.io",
      "authentication.api.cx.metamask.io",
      "metamask.github.io",
      "cdn.contentful.com",
      "gateway.api.cx.metamask.io"
    ]
  }
}
