oak_techniques: [OAK-T3.002]
spec_id: oak-detection-T3.002
version: 0.1.0
maturity: stable
maintainer: "@iZonex"
license: Apache-2.0

scope: |
  Detect per-pair counterparty cycles on DEX swap activity that indicate
  self-financed wash-trade volume inflation. Operator goal: distort
  price-discovery to attract real third-party demand at manufactured
  prices. Excludes: T7.x (laundering through self-financed swaps —
  same shape, different goal); T12.001 (NFT-marketplace wash — different
  on-chain artefact); incentive-farming wash where reward extraction is
  the goal (overlapping pattern, different mitigation set).

data_sources: [dex_trades, address_funding_trace]

detection_logic:
  description: |
    Build the per-pair counterparty graph over a rolling window. Two
    addresses belong to the same self-financed cluster if their funding
    ancestors within `trace_hops` overlap. Cycle-share = fraction of
    pair volume on edges inside one cluster.
  pseudocode: |
    for each pair P observed in dex_trades over `window`:
      G ← graph()
      for each trade T with T.pair == P:
        G.add_edge(T.taker → T.maker, weight = T.volume_usd)

      clusters ← partition_by_shared_funding_ancestor(
        graph = G, hops = trace_hops, min_value = funding_threshold_usd)

      cycle_volume ← Σ edge.weight for edge in G.edges
                       where cluster(edge.from) == cluster(edge.to)
                         and cluster(edge.from) ≠ singleton

      total_volume ← Σ edge.weight for edge in G.edges
      if total_volume == 0: continue
      cycle_share ← cycle_volume / total_volume

      if cycle_share > flagging_threshold:
        emit(pair = P, cycle_share, cycle_volume, total_volume,
             top_clusters = top_k_by_volume(clusters, k=3))

parameters:
  window: { type: duration, default: 30d }
  trace_hops: { type: integer, default: 3 }
  funding_threshold_usd: { type: number, default: 1000 }
  flagging_threshold: { type: number, default: 0.4 }

output_alert: [oak_technique, pair_address, chain, cycle_share,
               total_volume_usd, self_financed_volume_usd, top_clusters]

test_fixtures:
  positive:
    - 2023-02-blur-airdrop-wash-cohort
    - 2022-11-x2y2-looksrare-royalty-optional
  negative:
    - "Uniswap V3 WETH/USDC 0.05% pool — high volume, low cycle"
    - "Market-maker (Wintermute / GSR / Jump) inventory rebalance across owned wallets"

false_positive_modes:
  - market-maker multi-wallet inventory rebalance (high cluster volume, legitimate)
  - low-liquidity organic pair where small clusters dominate by chance
  - aggregator-routed arbitrage cycles (same address on both sides via multi-hop route)

mitigations: [OAK-M04, OAK-M11, OAK-M12, OAK-M26]

reference_implementations:
  - { target: dune, chain: evm, url: "" }
  - { target: forta-bot, chain: evm, url: "" }
  - { target: goldsky-subgraph, chain: evm, url: "" }
