geekmind revised this gist 1 month ago. Go to revision
1 file changed, 333 insertions, 240 deletions
meteora_stale_pool_arb.html
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | <head> | |
| 4 | 4 | <meta charset="UTF-8" /> | |
| 5 | 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
| 6 | - | <title>Solana Meteora 过期池套利拆解:299 万美金消失的 150 秒</title> | |
| 6 | + | <title>299 万美金、150 秒、9 笔交易 —— 一个 Meteora 旧池子被反向 rug 的链上拆解</title> | |
| 7 | 7 | <style> | |
| 8 | 8 | :root { | |
| 9 | 9 | --bg: #0d1117; | |
| @@ -28,7 +28,7 @@ | |||
| 28 | 28 | line-height: 1.7; | |
| 29 | 29 | } | |
| 30 | 30 | .wrap { | |
| 31 | - | max-width: 920px; | |
| 31 | + | max-width: 960px; | |
| 32 | 32 | margin: 0 auto; | |
| 33 | 33 | padding: 48px 28px 96px; | |
| 34 | 34 | } | |
| @@ -49,10 +49,16 @@ | |||
| 49 | 49 | margin-bottom: 16px; | |
| 50 | 50 | border: 1px solid rgba(247, 185, 85, 0.3); | |
| 51 | 51 | } | |
| 52 | + | .tag.verified { | |
| 53 | + | background: rgba(63, 185, 80, 0.12); | |
| 54 | + | color: var(--green); | |
| 55 | + | border-color: rgba(63, 185, 80, 0.3); | |
| 56 | + | margin-left: 8px; | |
| 57 | + | } | |
| 52 | 58 | h1 { | |
| 53 | - | font-size: 34px; | |
| 54 | - | line-height: 1.25; | |
| 55 | - | margin: 0 0 12px; | |
| 59 | + | font-size: 32px; | |
| 60 | + | line-height: 1.3; | |
| 61 | + | margin: 0 0 14px; | |
| 56 | 62 | font-weight: 700; | |
| 57 | 63 | letter-spacing: -0.01em; | |
| 58 | 64 | } | |
| @@ -78,9 +84,10 @@ | |||
| 78 | 84 | border: 1px solid var(--border); | |
| 79 | 85 | padding: 1px 6px; | |
| 80 | 86 | border-radius: 4px; | |
| 81 | - | font-size: 13.5px; | |
| 87 | + | font-size: 13px; | |
| 82 | 88 | color: var(--accent); | |
| 83 | 89 | font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; | |
| 90 | + | word-break: break-all; | |
| 84 | 91 | } | |
| 85 | 92 | .stats { | |
| 86 | 93 | display: grid; | |
| @@ -147,12 +154,13 @@ | |||
| 147 | 154 | width: 100%; | |
| 148 | 155 | border-collapse: collapse; | |
| 149 | 156 | margin: 18px 0; | |
| 150 | - | font-size: 14px; | |
| 157 | + | font-size: 13.5px; | |
| 151 | 158 | } | |
| 152 | 159 | th, td { | |
| 153 | 160 | padding: 10px 12px; | |
| 154 | 161 | border-bottom: 1px solid var(--border); | |
| 155 | 162 | text-align: left; | |
| 163 | + | vertical-align: top; | |
| 156 | 164 | } | |
| 157 | 165 | th { | |
| 158 | 166 | background: var(--panel2); | |
| @@ -162,6 +170,9 @@ | |||
| 162 | 170 | text-transform: uppercase; | |
| 163 | 171 | letter-spacing: 0.03em; | |
| 164 | 172 | } | |
| 173 | + | td.num { font-variant-numeric: tabular-nums; text-align: right; } | |
| 174 | + | td.green { color: var(--green); } | |
| 175 | + | td.red { color: var(--red); } | |
| 165 | 176 | ol.steps { | |
| 166 | 177 | counter-reset: s; | |
| 167 | 178 | list-style: none; | |
| @@ -204,8 +215,13 @@ | |||
| 204 | 215 | background: rgba(248, 81, 73, 0.08); | |
| 205 | 216 | border-color: rgba(248, 81, 73, 0.3); | |
| 206 | 217 | } | |
| 218 | + | .callout.update { | |
| 219 | + | background: rgba(247, 185, 85, 0.08); | |
| 220 | + | border-color: rgba(247, 185, 85, 0.3); | |
| 221 | + | } | |
| 207 | 222 | .callout strong { color: var(--accent2); } | |
| 208 | 223 | .callout.warn strong { color: var(--red); } | |
| 224 | + | .callout.update strong { color: var(--accent); } | |
| 209 | 225 | footer { | |
| 210 | 226 | margin-top: 64px; | |
| 211 | 227 | padding-top: 24px; | |
| @@ -215,10 +231,16 @@ | |||
| 215 | 231 | } | |
| 216 | 232 | footer a { color: var(--accent2); text-decoration: none; } | |
| 217 | 233 | footer a:hover { text-decoration: underline; } | |
| 234 | + | .addr { | |
| 235 | + | font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; | |
| 236 | + | font-size: 12px; | |
| 237 | + | color: var(--accent2); | |
| 238 | + | word-break: break-all; | |
| 239 | + | } | |
| 218 | 240 | ||
| 219 | 241 | @media (max-width: 640px) { | |
| 220 | 242 | .wrap { padding: 28px 16px 64px; } | |
| 221 | - | h1 { font-size: 26px; } | |
| 243 | + | h1 { font-size: 24px; } | |
| 222 | 244 | .stats { grid-template-columns: repeat(2, 1fr); } | |
| 223 | 245 | } | |
| 224 | 246 | </style> | |
| @@ -227,17 +249,18 @@ | |||
| 227 | 249 | <div class="wrap"> | |
| 228 | 250 | ||
| 229 | 251 | <header> | |
| 230 | - | <span class="tag">Solana · MEV · DEX 套利</span> | |
| 231 | - | <h1>299 万美金,150 秒蒸发<br/>—— Meteora 过期池套利完整拆解</h1> | |
| 232 | - | <p class="subtitle">用图解搞懂:DLMM 的 bin 是什么,为什么旧 LP 池会变成"白送代币的提款机",以及套利机器人是怎么把它们一口气吞掉的。</p> | |
| 252 | + | <span class="tag">Solana · MEV · Stale Pool</span> | |
| 253 | + | <span class="tag verified">已用 Solscan 验证 · v2</span> | |
| 254 | + | <h1>299 万美金、150 秒、9 笔交易<br/>—— 一个 Meteora 旧池子被「反向 rug」的链上拆解</h1> | |
| 255 | + | <p class="subtitle">事件发生于 2026-05-01 19:06:54 UTC(slot 416936447 起 3 个连续 slot)。本文基于 Solscan 链上真实数据复盘,颠覆了对"过期池套利"方向的常见误解。</p> | |
| 233 | 256 | </header> | |
| 234 | 257 | ||
| 235 | 258 | <section> | |
| 236 | 259 | <div class="stats"> | |
| 237 | - | <div class="stat"><div class="num">$2.99M</div><div class="lbl">被抽走金额</div></div> | |
| 260 | + | <div class="stat"><div class="num">$2.99M</div><div class="lbl">总抽走金额</div></div> | |
| 238 | 261 | <div class="stat"><div class="num">150s</div><div class="lbl">总耗时</div></div> | |
| 239 | - | <div class="stat"><div class="num">6 + 1</div><div class="lbl">机器人 + 鲸鱼</div></div> | |
| 240 | - | <div class="stat"><div class="num">10 个月</div><div class="lbl">池子无人维护</div></div> | |
| 262 | + | <div class="stat"><div class="num">3 + 4</div><div class="lbl">主力 + 散兵 bot</div></div> | |
| 263 | + | <div class="stat"><div class="num">10 个月</div><div class="lbl">DLMM 池子未维护</div></div> | |
| 241 | 264 | </div> | |
| 242 | 265 | ||
| 243 | 266 | <div class="quote"> | |
| @@ -245,14 +268,19 @@ | |||
| 245 | 268 | <span class="src">—— @anshu_code, X / 2026-05-06</span> | |
| 246 | 269 | </div> | |
| 247 | 270 | ||
| 248 | - | <p>这条推文讲的,是 Solana 链上一个被忽略了 10 个月的 <strong>Meteora DLMM 流动性池</strong>,在 150 秒内被 6 个套利机器人和一个大户合力"洗"了一遍,搬走 299 万美金。本文用图把它拆开讲清楚。</p> | |
| 271 | + | <div class="callout update"> | |
| 272 | + | <strong>v2 更新说明:</strong>本报告 v1 基于推文文字推理,方向<strong>讲反了</strong>。链上实测后已修正:stale 池子里装的不是"等卖的便宜代币",而是"愿意高价收购废纸的 USDC"。机器人不是去捡便宜币,是去把<strong>近乎归零的代币塞进去换真金白银</strong>。下文 §3-§5 全部基于 Solscan 实测数据。 | |
| 273 | + | </div> | |
| 249 | 274 | </section> | |
| 250 | 275 | ||
| 251 | - | <h2>1. 它属于哪一类套利?</h2> | |
| 252 | - | <p>这种玩法的术语叫 <strong>Stale Pool Arbitrage(过期池套利)</strong>。靶子是那些 <em>LP 挂上去就不再维护</em> 的集中流动性池——挂的还是几个月前的"老价格",外部市场早已涨飞,池子却毫无觉察。</p> | |
| 276 | + | <h2>1. 事件一句话总结</h2> | |
| 277 | + | <p>有个 LP 在 2025 年 7 月左右往 Meteora 上一个 ANB-USDC 的 DLMM 池子里塞了至少 <strong>$1.4M 的 USDC</strong>,挂在 ANB ~ $0.01-$0.05/枚的价格档位(bins)上。10 个月后,ANB 真实市价跌到了 <strong>$0.0000113/枚</strong>(缩水 ~1000 倍),LP 没有移除流动性也没人交易这个池子,<strong>active bin 卡在原位不动</strong>。2026/5/1 这个池子被一群套利机器人发现,3 个 slot 内 ~$1.4M USDC 全被搬空,单笔最大利润 <strong>$696,194</strong>。</p> | |
| 278 | + | ||
| 279 | + | <h2>2. 这次的"鲸鱼"是谁,钱是怎么流的?</h2> | |
| 280 | + | <p>推文里说的"1 whale, 6 bots, 9 transactions"——这里的 whale <strong>不是来 swap 的大户</strong>,而是池子的 LP 本人。机器人不是从某个交易者身上薅羊毛,而是<strong>直接把 LP 当年存进去的 USDC 一捆捆拎走</strong>。</p> | |
| 253 | 281 | ||
| 254 | 282 | <figure> | |
| 255 | - | <svg viewBox="0 0 760 280" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="过期池套利示意"> | |
| 283 | + | <svg viewBox="0 0 880 380" xmlns="http://www.w3.org/2000/svg"> | |
| 256 | 284 | <defs> | |
| 257 | 285 | <linearGradient id="bg1" x1="0" x2="0" y1="0" y2="1"> | |
| 258 | 286 | <stop offset="0" stop-color="#1c2330"/> | |
| @@ -261,264 +289,329 @@ | |||
| 261 | 289 | <marker id="arrow" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto"> | |
| 262 | 290 | <path d="M0,0 L8,3 L0,6 z" fill="#f7b955"/> | |
| 263 | 291 | </marker> | |
| 292 | + | <marker id="arrow_red" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto"> | |
| 293 | + | <path d="M0,0 L8,3 L0,6 z" fill="#f85149"/> | |
| 294 | + | </marker> | |
| 264 | 295 | </defs> | |
| 265 | - | <rect width="760" height="280" fill="url(#bg1)" rx="10"/> | |
| 266 | - | ||
| 267 | - | <!-- Raydium box --> | |
| 268 | - | <rect x="40" y="60" width="240" height="160" fill="#0d1117" stroke="#3fb950" stroke-width="1.5" rx="10"/> | |
| 269 | - | <text x="160" y="90" text-anchor="middle" fill="#3fb950" font-size="15" font-weight="700">Raydium / 真实市场</text> | |
| 270 | - | <text x="160" y="135" text-anchor="middle" fill="#e6edf3" font-size="13">代币 X 已涨到</text> | |
| 271 | - | <text x="160" y="170" text-anchor="middle" fill="#3fb950" font-size="32" font-weight="700">$1.00</text> | |
| 272 | - | <text x="160" y="195" text-anchor="middle" fill="#8b949e" font-size="11">活跃交易 · 价格随市场实时更新</text> | |
| 273 | - | ||
| 274 | - | <!-- Meteora box --> | |
| 275 | - | <rect x="480" y="60" width="240" height="160" fill="#0d1117" stroke="#f85149" stroke-width="1.5" rx="10"/> | |
| 276 | - | <text x="600" y="90" text-anchor="middle" fill="#f85149" font-size="15" font-weight="700">Meteora 旧池子</text> | |
| 277 | - | <text x="600" y="135" text-anchor="middle" fill="#e6edf3" font-size="13">10 个月没人交易</text> | |
| 278 | - | <text x="600" y="170" text-anchor="middle" fill="#f85149" font-size="32" font-weight="700">$0.001</text> | |
| 279 | - | <text x="600" y="195" text-anchor="middle" fill="#8b949e" font-size="11">价格停在 LP 创建时的水平</text> | |
| 280 | - | ||
| 281 | - | <!-- Bridge / arrow --> | |
| 282 | - | <text x="380" y="130" text-anchor="middle" fill="#f7b955" font-size="13" font-weight="700">价差 1000×</text> | |
| 283 | - | <line x1="290" y1="150" x2="470" y2="150" stroke="#f7b955" stroke-width="2" marker-end="url(#arrow)"/> | |
| 284 | - | <text x="380" y="180" text-anchor="middle" fill="#8b949e" font-size="11">套利机器人在这里下手</text> | |
| 296 | + | <rect width="880" height="380" fill="url(#bg1)" rx="10"/> | |
| 297 | + | ||
| 298 | + | <!-- LP --> | |
| 299 | + | <rect x="40" y="40" width="170" height="80" fill="#0d1117" stroke="#bc8cff" stroke-width="1.5" rx="10"/> | |
| 300 | + | <text x="125" y="65" text-anchor="middle" fill="#bc8cff" font-size="14" font-weight="700">"鲸鱼" = LP</text> | |
| 301 | + | <text x="125" y="85" text-anchor="middle" fill="#e6edf3" font-size="11">10 个月前</text> | |
| 302 | + | <text x="125" y="103" text-anchor="middle" fill="#bc8cff" font-size="13" font-weight="700">灌入 ≥ $1.4M USDC</text> | |
| 303 | + | ||
| 304 | + | <!-- Stale Pool --> | |
| 305 | + | <rect x="320" y="20" width="240" height="120" fill="#0d1117" stroke="#f85149" stroke-width="2" rx="10"/> | |
| 306 | + | <text x="440" y="48" text-anchor="middle" fill="#f85149" font-size="14" font-weight="700">ANB-USDC DLMM 池子</text> | |
| 307 | + | <text x="440" y="70" text-anchor="middle" fill="#e6edf3" font-size="11">USDC 沉睡在高价 bins</text> | |
| 308 | + | <text x="440" y="92" text-anchor="middle" fill="#8b949e" font-size="11">愿意按 $0.01/ANB 收购</text> | |
| 309 | + | <text x="440" y="114" text-anchor="middle" fill="#f85149" font-size="11">(真实市价仅 $0.0000113)</text> | |
| 310 | + | <text x="440" y="132" text-anchor="middle" fill="#f85149" font-size="11" font-weight="700">10 个月没人动它</text> | |
| 311 | + | ||
| 312 | + | <!-- Arrow LP → Pool --> | |
| 313 | + | <line x1="210" y1="80" x2="316" y2="80" stroke="#bc8cff" stroke-width="2" marker-end="url(#arrow)"/> | |
| 314 | + | ||
| 315 | + | <!-- Source pool (cheap ANB) --> | |
| 316 | + | <rect x="320" y="180" width="240" height="80" fill="#0d1117" stroke="#3fb950" stroke-width="1.5" rx="10"/> | |
| 317 | + | <text x="440" y="208" text-anchor="middle" fill="#3fb950" font-size="14" font-weight="700">ANB-USDC DAMM v2</text> | |
| 318 | + | <text x="440" y="230" text-anchor="middle" fill="#e6edf3" font-size="11">价格紧贴市价</text> | |
| 319 | + | <text x="440" y="250" text-anchor="middle" fill="#3fb950" font-size="11">$0.20 USDC ≈ 25M ANB</text> | |
| 320 | + | ||
| 321 | + | <!-- Bots --> | |
| 322 | + | <rect x="660" y="40" width="180" height="80" fill="#0d1117" stroke="#f7b955" stroke-width="1.5" rx="10"/> | |
| 323 | + | <text x="750" y="65" text-anchor="middle" fill="#f7b955" font-size="14" font-weight="700">7 个套利 bot</text> | |
| 324 | + | <text x="750" y="85" text-anchor="middle" fill="#e6edf3" font-size="11">总投入 ≈ $1.5 USDC</text> | |
| 325 | + | <text x="750" y="105" text-anchor="middle" fill="#f7b955" font-size="13" font-weight="700">总取出 ≈ $2.99M USDC</text> | |
| 326 | + | ||
| 327 | + | <!-- Bot to source pool --> | |
| 328 | + | <line x1="660" y1="105" x2="565" y2="200" stroke="#f7b955" stroke-width="2" marker-end="url(#arrow)"/> | |
| 329 | + | <text x="640" y="160" fill="#f7b955" font-size="11">① 用几毛钱</text> | |
| 330 | + | <text x="640" y="178" fill="#f7b955" font-size="11">买几千万 ANB</text> | |
| 331 | + | ||
| 332 | + | <!-- Bot to stale pool --> | |
| 333 | + | <line x1="565" y1="105" x2="660" y2="80" stroke="#f7b955" stroke-width="2" marker-end="url(#arrow)" stroke-dasharray="0"/> | |
| 334 | + | <text x="563" y="158" fill="#f7b955" font-size="11" text-anchor="end">② 把 ANB 砸进 stale 池</text> | |
| 335 | + | <text x="563" y="176" fill="#f7b955" font-size="11" text-anchor="end">换出 $282K-$696K USDC</text> | |
| 336 | + | ||
| 337 | + | <!-- ANB to stale pool arrow --> | |
| 338 | + | <line x1="440" y1="180" x2="440" y2="142" stroke="#f7b955" stroke-width="2" marker-end="url(#arrow)" stroke-dasharray="4 3"/> | |
| 339 | + | ||
| 340 | + | <!-- Bot grabs USDC --> | |
| 341 | + | <line x1="558" y1="78" x2="660" y2="65" stroke="#f85149" stroke-width="2" marker-end="url(#arrow_red)"/> | |
| 342 | + | ||
| 343 | + | <!-- Footer --> | |
| 344 | + | <line x1="40" y1="305" x2="840" y2="305" stroke="#30363d" stroke-width="1" stroke-dasharray="3 3"/> | |
| 345 | + | <text x="40" y="333" fill="#8b949e" font-size="12">资金净流向:</text> | |
| 346 | + | <text x="160" y="333" fill="#bc8cff" font-size="12" font-weight="700">LP(whale)的 USDC</text> | |
| 347 | + | <text x="320" y="333" fill="#8b949e" font-size="12">→</text> | |
| 348 | + | <text x="345" y="333" fill="#f85149" font-size="12" font-weight="700">stale DLMM 池</text> | |
| 349 | + | <text x="465" y="333" fill="#8b949e" font-size="12">→</text> | |
| 350 | + | <text x="490" y="333" fill="#f7b955" font-size="12" font-weight="700">套利 bots</text> | |
| 351 | + | <text x="40" y="358" fill="#8b949e" font-size="11">机器人付出的成本只有:base fee + Jito tip + 几毛钱用来买 ANB;剩下全是利润。</text> | |
| 285 | 352 | </svg> | |
| 286 | - | <figcaption>同一种代币,两个池子,价格差 1000 倍。差距在 LP 不维护时会一直存在。</figcaption> | |
| 353 | + | <figcaption>真实链上资金流:LP 当年灌入的 USDC,10 个月后被机器人用近乎为零的成本「赎」走。</figcaption> | |
| 287 | 354 | </figure> | |
| 288 | 355 | ||
| 289 | - | <h2>2. 先理解 DLMM:什么是 bin?</h2> | |
| 290 | - | <p>Meteora DLMM(Dynamic Liquidity Market Maker)跟 Uniswap v3 思路一样:把价格切成一格一格的"档位",每一档叫 <strong>bin</strong>。LP 不是在一条曲线上放钱,而是把代币塞进具体某几个 bin 里。</p> | |
| 356 | + | <h2>3. Stale 池子结构(修正版)</h2> | |
| 357 | + | <p>这次的关键是:池子里"过期"的不是代币,是 <strong>USDC</strong>。LP 当时挂的是"<em>限价买单</em>"——把 USDC 塞在 active bin 下方,挂在 ANB = $0.005、$0.01、$0.05 这种<strong>它认为合理</strong>的价格上。ANB 价格崩了 1000 倍后,这些 USDC 还在原位,等着按"老价格"收购 ANB。</p> | |
| 291 | 358 | ||
| 292 | 359 | <figure> | |
| 293 | - | <svg viewBox="0 0 760 320" xmlns="http://www.w3.org/2000/svg"> | |
| 294 | - | <rect width="760" height="320" fill="url(#bg1)" rx="10"/> | |
| 295 | - | ||
| 296 | - | <!-- Active bin marker --> | |
| 297 | - | <line x1="380" y1="40" x2="380" y2="280" stroke="#f7b955" stroke-width="1" stroke-dasharray="4 4"/> | |
| 298 | - | <text x="380" y="32" text-anchor="middle" fill="#f7b955" font-size="13" font-weight="700">↓ Active Bin(当前价)</text> | |
| 299 | - | ||
| 300 | - | <!-- Bins --> | |
| 301 | - | <g font-family="ui-monospace, monospace" font-size="11"> | |
| 302 | - | <!-- Y bins (left, USDC) --> | |
| 303 | - | <g> | |
| 304 | - | <rect x="60" y="180" width="48" height="100" fill="#3fb950" opacity="0.85" rx="3"/> | |
| 305 | - | <rect x="115" y="160" width="48" height="120" fill="#3fb950" opacity="0.85" rx="3"/> | |
| 306 | - | <rect x="170" y="140" width="48" height="140" fill="#3fb950" opacity="0.85" rx="3"/> | |
| 307 | - | <rect x="225" y="120" width="48" height="160" fill="#3fb950" opacity="0.85" rx="3"/> | |
| 308 | - | <rect x="280" y="105" width="48" height="175" fill="#3fb950" opacity="0.85" rx="3"/> | |
| 309 | - | <text x="84" y="298" text-anchor="middle" fill="#8b949e">$0.5</text> | |
| 310 | - | <text x="139" y="298" text-anchor="middle" fill="#8b949e">$0.6</text> | |
| 311 | - | <text x="194" y="298" text-anchor="middle" fill="#8b949e">$0.7</text> | |
| 312 | - | <text x="249" y="298" text-anchor="middle" fill="#8b949e">$0.8</text> | |
| 313 | - | <text x="304" y="298" text-anchor="middle" fill="#8b949e">$0.9</text> | |
| 314 | - | </g> | |
| 315 | - | <!-- Active --> | |
| 316 | - | <rect x="358" y="100" width="44" height="180" fill="#f7b955" opacity="0.9" rx="3"/> | |
| 317 | - | <text x="380" y="298" text-anchor="middle" fill="#f7b955" font-weight="700">$1.0</text> | |
| 318 | - | ||
| 319 | - | <!-- X bins (right, token) --> | |
| 320 | - | <g> | |
| 321 | - | <rect x="430" y="105" width="48" height="175" fill="#bc8cff" opacity="0.85" rx="3"/> | |
| 322 | - | <rect x="485" y="120" width="48" height="160" fill="#bc8cff" opacity="0.85" rx="3"/> | |
| 323 | - | <rect x="540" y="140" width="48" height="140" fill="#bc8cff" opacity="0.85" rx="3"/> | |
| 324 | - | <rect x="595" y="160" width="48" height="120" fill="#bc8cff" opacity="0.85" rx="3"/> | |
| 325 | - | <rect x="650" y="180" width="48" height="100" fill="#bc8cff" opacity="0.85" rx="3"/> | |
| 326 | - | <text x="454" y="298" text-anchor="middle" fill="#8b949e">$1.1</text> | |
| 327 | - | <text x="509" y="298" text-anchor="middle" fill="#8b949e">$1.2</text> | |
| 328 | - | <text x="564" y="298" text-anchor="middle" fill="#8b949e">$1.3</text> | |
| 329 | - | <text x="619" y="298" text-anchor="middle" fill="#8b949e">$1.4</text> | |
| 330 | - | <text x="674" y="298" text-anchor="middle" fill="#8b949e">$1.5</text> | |
| 331 | - | </g> | |
| 360 | + | <svg viewBox="0 0 880 360" xmlns="http://www.w3.org/2000/svg"> | |
| 361 | + | <rect width="880" height="360" fill="url(#bg1)" rx="10"/> | |
| 362 | + | ||
| 363 | + | <!-- Title --> | |
| 364 | + | <text x="440" y="34" text-anchor="middle" fill="#e6edf3" font-size="15" font-weight="700">DLMM bins 真实分布(创建时 vs 被发现时)</text> | |
| 365 | + | ||
| 366 | + | <!-- LP setup time --> | |
| 367 | + | <text x="40" y="78" fill="#bc8cff" font-size="13" font-weight="700">10 个月前 · LP 设置时</text> | |
| 368 | + | <text x="40" y="96" fill="#8b949e" font-size="11">假设当时 ANB 市价 ≈ $0.01</text> | |
| 369 | + | <g> | |
| 370 | + | <rect x="40" y="110" width="50" height="60" fill="#3fb950" opacity="0.85" rx="3"/> | |
| 371 | + | <rect x="95" y="110" width="50" height="60" fill="#3fb950" opacity="0.85" rx="3"/> | |
| 372 | + | <rect x="150" y="110" width="50" height="60" fill="#3fb950" opacity="0.85" rx="3"/> | |
| 373 | + | <rect x="205" y="110" width="50" height="60" fill="#3fb950" opacity="0.85" rx="3"/> | |
| 374 | + | <rect x="260" y="110" width="50" height="60" fill="#f7b955" rx="3"/> | |
| 375 | + | <rect x="315" y="110" width="50" height="60" fill="#bc8cff" opacity="0.6" rx="3"/> | |
| 376 | + | <text x="65" y="188" text-anchor="middle" fill="#8b949e" font-size="10">$0.005</text> | |
| 377 | + | <text x="120" y="188" text-anchor="middle" fill="#8b949e" font-size="10">$0.007</text> | |
| 378 | + | <text x="175" y="188" text-anchor="middle" fill="#8b949e" font-size="10">$0.008</text> | |
| 379 | + | <text x="230" y="188" text-anchor="middle" fill="#8b949e" font-size="10">$0.009</text> | |
| 380 | + | <text x="285" y="188" text-anchor="middle" fill="#f7b955" font-size="10" font-weight="700">$0.01</text> | |
| 381 | + | <text x="340" y="188" text-anchor="middle" fill="#8b949e" font-size="10">$0.012</text> | |
| 382 | + | <text x="65" y="142" text-anchor="middle" fill="#fff" font-size="11">USDC</text> | |
| 383 | + | <text x="120" y="142" text-anchor="middle" fill="#fff" font-size="11">USDC</text> | |
| 384 | + | <text x="175" y="142" text-anchor="middle" fill="#fff" font-size="11">USDC</text> | |
| 385 | + | <text x="230" y="142" text-anchor="middle" fill="#fff" font-size="11">USDC</text> | |
| 332 | 386 | </g> | |
| 333 | - | ||
| 334 | - | <!-- Labels --> | |
| 335 | - | <text x="194" y="80" text-anchor="middle" fill="#3fb950" font-size="13" font-weight="700">下方 bins</text> | |
| 336 | - | <text x="194" y="98" text-anchor="middle" fill="#3fb950" font-size="11">装 USDC(限价买单)</text> | |
| 337 | - | ||
| 338 | - | <text x="564" y="80" text-anchor="middle" fill="#bc8cff" font-size="13" font-weight="700">上方 bins</text> | |
| 339 | - | <text x="564" y="98" text-anchor="middle" fill="#bc8cff" font-size="11">装 代币 X(限价卖单)</text> | |
| 340 | - | </svg> | |
| 341 | - | <figcaption>DLMM 池子结构:active bin 把价格分成左右两半。左边的 bin 装 USDC,右边的装代币。</figcaption> | |
| 342 | - | </figure> | |
| 343 | - | ||
| 344 | - | <div class="callout"> | |
| 345 | - | <strong>关键三点:</strong> | |
| 346 | - | <ol style="margin:8px 0 0; padding-left: 20px;"> | |
| 347 | - | <li>每个 bin 对应一个<strong>固定</strong>的兑换价(创建时算好的常数)。</li> | |
| 348 | - | <li>active bin <strong>下方</strong>的 bins 装 Y(USDC),是"低价等买 X 的限价买单"。</li> | |
| 349 | - | <li>active bin <strong>上方</strong>的 bins 装 X(代币),是"高价等卖出的限价卖单"。</li> | |
| 350 | - | </ol> | |
| 351 | - | </div> | |
| 352 | - | ||
| 353 | - | <h2>3. 为什么 bin 会"老价格存在"?</h2> | |
| 354 | - | <p>这是这次事件最反直觉的地方。<strong>DLMM 池子的价格不会自动跟着外部市场走</strong>——它只在<em>有人在本池子做 swap</em>的时候才移动 active bin。</p> | |
| 355 | - | ||
| 356 | - | <figure> | |
| 357 | - | <svg viewBox="0 0 760 360" xmlns="http://www.w3.org/2000/svg"> | |
| 358 | - | <rect width="760" height="360" fill="url(#bg1)" rx="10"/> | |
| 359 | - | ||
| 360 | - | <!-- Time axis --> | |
| 361 | - | <line x1="60" y1="320" x2="700" y2="320" stroke="#30363d" stroke-width="1"/> | |
| 362 | - | <text x="60" y="345" fill="#8b949e" font-size="11">Day 0</text> | |
| 363 | - | <text x="380" y="345" fill="#8b949e" font-size="11">Day 1 ~ 300(无人交易)</text> | |
| 364 | - | <text x="700" y="345" text-anchor="end" fill="#8b949e" font-size="11">Day 300(被发现)</text> | |
| 365 | - | ||
| 366 | - | <!-- Raydium price line - rising --> | |
| 367 | - | <text x="60" y="48" fill="#3fb950" font-size="12" font-weight="700">Raydium 真实市价</text> | |
| 368 | - | <path d="M60,290 Q200,280 300,200 T700,80" stroke="#3fb950" stroke-width="2.5" fill="none"/> | |
| 369 | - | <circle cx="60" cy="290" r="4" fill="#3fb950"/> | |
| 370 | - | <circle cx="700" cy="80" r="5" fill="#3fb950"/> | |
| 371 | - | <text x="80" y="285" fill="#3fb950" font-size="11">$0.001</text> | |
| 372 | - | <text x="688" y="74" text-anchor="end" fill="#3fb950" font-size="11" font-weight="700">$1.00 ↑↑↑</text> | |
| 373 | - | ||
| 374 | - | <!-- Meteora price line - flat --> | |
| 375 | - | <text x="60" y="200" fill="#f85149" font-size="12" font-weight="700">Meteora 池子 active bin</text> | |
| 376 | - | <line x1="60" y1="290" x2="640" y2="290" stroke="#f85149" stroke-width="2.5" stroke-dasharray="6 4"/> | |
| 377 | - | <circle cx="60" cy="290" r="4" fill="#f85149"/> | |
| 378 | - | <circle cx="640" cy="290" r="4" fill="#f85149"/> | |
| 379 | - | <text x="380" y="282" text-anchor="middle" fill="#f85149" font-size="11">10 个月一动不动 · 一直停在 $0.001</text> | |
| 380 | - | ||
| 381 | - | <!-- Gap arrow --> | |
| 382 | - | <line x1="660" y1="80" x2="660" y2="280" stroke="#f7b955" stroke-width="1.5" stroke-dasharray="3 3"/> | |
| 383 | - | <line x1="650" y1="80" x2="670" y2="80" stroke="#f7b955" stroke-width="1.5"/> | |
| 384 | - | <line x1="650" y1="280" x2="670" y2="280" stroke="#f7b955" stroke-width="1.5"/> | |
| 385 | - | <text x="678" y="180" fill="#f7b955" font-size="13" font-weight="700">价差</text> | |
| 386 | - | <text x="678" y="198" fill="#f7b955" font-size="11">1000×</text> | |
| 387 | + | <text x="40" y="220" fill="#8b949e" font-size="11">↑ active bin 在 $0.01 · 下方 4 格 USDC 等买</text> | |
| 388 | + | ||
| 389 | + | <!-- 10 months later --> | |
| 390 | + | <text x="480" y="78" fill="#f85149" font-size="13" font-weight="700">10 个月后 · 被发现时</text> | |
| 391 | + | <text x="480" y="96" fill="#8b949e" font-size="11">真实市价跌到 $0.0000113,但池子……</text> | |
| 392 | + | <g> | |
| 393 | + | <rect x="480" y="110" width="50" height="60" fill="#3fb950" opacity="0.85" rx="3"/> | |
| 394 | + | <rect x="535" y="110" width="50" height="60" fill="#3fb950" opacity="0.85" rx="3"/> | |
| 395 | + | <rect x="590" y="110" width="50" height="60" fill="#3fb950" opacity="0.85" rx="3"/> | |
| 396 | + | <rect x="645" y="110" width="50" height="60" fill="#3fb950" opacity="0.85" rx="3"/> | |
| 397 | + | <rect x="700" y="110" width="50" height="60" fill="#f7b955" rx="3"/> | |
| 398 | + | <rect x="755" y="110" width="50" height="60" fill="#bc8cff" opacity="0.6" rx="3"/> | |
| 399 | + | <text x="505" y="188" text-anchor="middle" fill="#8b949e" font-size="10">$0.005</text> | |
| 400 | + | <text x="560" y="188" text-anchor="middle" fill="#8b949e" font-size="10">$0.007</text> | |
| 401 | + | <text x="615" y="188" text-anchor="middle" fill="#8b949e" font-size="10">$0.008</text> | |
| 402 | + | <text x="670" y="188" text-anchor="middle" fill="#8b949e" font-size="10">$0.009</text> | |
| 403 | + | <text x="725" y="188" text-anchor="middle" fill="#f7b955" font-size="10" font-weight="700">$0.01</text> | |
| 404 | + | <text x="780" y="188" text-anchor="middle" fill="#8b949e" font-size="10">$0.012</text> | |
| 405 | + | <text x="505" y="142" text-anchor="middle" fill="#fff" font-size="11">USDC</text> | |
| 406 | + | <text x="560" y="142" text-anchor="middle" fill="#fff" font-size="11">USDC</text> | |
| 407 | + | <text x="615" y="142" text-anchor="middle" fill="#fff" font-size="11">USDC</text> | |
| 408 | + | <text x="670" y="142" text-anchor="middle" fill="#fff" font-size="11">USDC</text> | |
| 409 | + | </g> | |
| 410 | + | <text x="480" y="220" fill="#f85149" font-size="11" font-weight="700">↑ active bin 还在 $0.01 · 下方 USDC 一动没动</text> | |
| 411 | + | <text x="480" y="238" fill="#f85149" font-size="11">外部市价已是 $0.0000113,池子按 $0.005-$0.01 一个收</text> | |
| 412 | + | ||
| 413 | + | <!-- Arrow connecting --> | |
| 414 | + | <line x1="380" y1="140" x2="476" y2="140" stroke="#8b949e" stroke-width="1.5" stroke-dasharray="3 3" marker-end="url(#arrow)"/> | |
| 415 | + | <text x="428" y="135" text-anchor="middle" fill="#8b949e" font-size="11">10 个月没人交易</text> | |
| 416 | + | <text x="428" y="155" text-anchor="middle" fill="#8b949e" font-size="11">active bin 不动</text> | |
| 417 | + | ||
| 418 | + | <!-- Bot exploit arrow --> | |
| 419 | + | <text x="640" y="280" text-anchor="middle" fill="#f7b955" font-size="13" font-weight="700">套利 bot 发现:</text> | |
| 420 | + | <text x="640" y="300" text-anchor="middle" fill="#e6edf3" font-size="12">"我手里 50M ANB 在外面只值 $565,"</text> | |
| 421 | + | <text x="640" y="320" text-anchor="middle" fill="#e6edf3" font-size="12">"塞进这个池子能换到 $696,194 的 USDC"</text> | |
| 422 | + | <text x="640" y="340" text-anchor="middle" fill="#f7b955" font-size="12" font-weight="700">→ 一笔 atomic tx 全部搞定</text> | |
| 387 | 423 | </svg> | |
| 388 | - | <figcaption>外部市场涨了 1000 倍,Meteora 池子的 active bin 却没移动半步——因为没人来这里 swap。</figcaption> | |
| 424 | + | <figcaption>关键洞察:DLMM 的"stale"是双向的——这次过期的方向是 USDC bins 在等高价收 ANB,机器人对它做的是「砸盘式套利」而非「捡漏式套利」。</figcaption> | |
| 389 | 425 | </figure> | |
| 390 | 426 | ||
| 391 | - | <p>所以"代币涨了为什么 bin 还能低价存在"的答案是:</p> | |
| 392 | 427 | <div class="callout warn"> | |
| 393 | - | <strong>Solana 链上没有"全局市场价"。</strong>每个 DEX 池子都是独立的小宇宙。Raydium 的价格涨到 $1 跟 Meteora 这个池子毫无机械联系——除非有套利机器人主动来"对齐"它。在它被发现之前,那批挂在 $0.001、$0.0011、$0.005、$0.01 ... 的 X 代币就一直**安静地坐在那儿等买家**。 | |
| 428 | + | <strong>所以:</strong>"代币涨了为什么 bin 还能低价存在"这个问题,在这个事件里其实反过来——是<strong>代币归零了,bin 还在按高价收</strong>。本质都是一回事:<em>DLMM 的 active bin 必须有交易才会移动,外部价格变化跟池子无关</em>。漂移可以是任意方向,stale 一旦形成,被发现的那刻就是清算。 | |
| 394 | 429 | </div> | |
| 395 | 430 | ||
| 396 | - | <h2>4. 攻击是怎么发生的(图解)</h2> | |
| 397 | - | <p>为了讲清楚机器人具体在干什么,下面把那笔 transaction 拆成 4 个画面:</p> | |
| 398 | - | ||
| 399 | - | <figure> | |
| 400 | - | <svg viewBox="0 0 760 480" xmlns="http://www.w3.org/2000/svg"> | |
| 401 | - | <rect width="760" height="480" fill="url(#bg1)" rx="10"/> | |
| 402 | - | ||
| 403 | - | <!-- Frame 1 --> | |
| 404 | - | <text x="20" y="34" fill="#f7b955" font-size="13" font-weight="700">① 池子初始状态:active bin 在 $0.001,上方塞满便宜 X 代币</text> | |
| 405 | - | <g transform="translate(40, 50)"> | |
| 406 | - | <rect x="0" y="0" width="40" height="60" fill="#f7b955" rx="2"/> | |
| 407 | - | <rect x="48" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 408 | - | <rect x="96" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 409 | - | <rect x="144" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 410 | - | <rect x="192" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 411 | - | <rect x="240" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 412 | - | <rect x="288" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 413 | - | <rect x="336" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 414 | - | <text x="20" y="78" text-anchor="middle" fill="#f7b955" font-size="10">$0.001</text> | |
| 415 | - | <text x="68" y="78" text-anchor="middle" fill="#8b949e" font-size="10">$0.002</text> | |
| 416 | - | <text x="116" y="78" text-anchor="middle" fill="#8b949e" font-size="10">$0.005</text> | |
| 417 | - | <text x="164" y="78" text-anchor="middle" fill="#8b949e" font-size="10">$0.01</text> | |
| 418 | - | <text x="212" y="78" text-anchor="middle" fill="#8b949e" font-size="10">$0.05</text> | |
| 419 | - | <text x="260" y="78" text-anchor="middle" fill="#8b949e" font-size="10">$0.2</text> | |
| 420 | - | <text x="308" y="78" text-anchor="middle" fill="#8b949e" font-size="10">$0.5</text> | |
| 421 | - | <text x="356" y="78" text-anchor="middle" fill="#8b949e" font-size="10">$1.0</text> | |
| 422 | - | <text x="450" y="38" fill="#bc8cff" font-size="11">每个紫格里都有大量代币 X,标价远低于市价</text> | |
| 423 | - | </g> | |
| 424 | - | ||
| 425 | - | <!-- Frame 2 --> | |
| 426 | - | <text x="20" y="148" fill="#f7b955" font-size="13" font-weight="700">② 机器人灌入 USDC,吞掉第一格 bin(按 $0.001 买)</text> | |
| 427 | - | <g transform="translate(40, 164)"> | |
| 428 | - | <rect x="0" y="0" width="40" height="60" fill="#3fb950" opacity="0.5" stroke="#3fb950" stroke-width="2" rx="2"/> | |
| 429 | - | <rect x="48" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 430 | - | <rect x="96" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 431 | - | <rect x="144" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 432 | - | <rect x="192" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 433 | - | <rect x="240" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 434 | - | <rect x="288" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 435 | - | <rect x="336" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 436 | - | <text x="20" y="78" text-anchor="middle" fill="#3fb950" font-size="10" font-weight="700">已吃完</text> | |
| 437 | - | <text x="450" y="38" fill="#3fb950" font-size="11">代币 X 进入机器人钱包,bin #1 变成 USDC</text> | |
| 438 | - | </g> | |
| 439 | - | ||
| 440 | - | <!-- Frame 3 --> | |
| 441 | - | <text x="20" y="262" fill="#f7b955" font-size="13" font-weight="700">③ active bin 推到下一格,继续吃(按 $0.002, $0.005, $0.01... 一路买上去)</text> | |
| 442 | - | <g transform="translate(40, 278)"> | |
| 443 | - | <rect x="0" y="0" width="40" height="60" fill="#3fb950" opacity="0.5" stroke="#3fb950" stroke-width="1" rx="2"/> | |
| 444 | - | <rect x="48" y="0" width="40" height="60" fill="#3fb950" opacity="0.5" stroke="#3fb950" stroke-width="1" rx="2"/> | |
| 445 | - | <rect x="96" y="0" width="40" height="60" fill="#3fb950" opacity="0.5" stroke="#3fb950" stroke-width="1" rx="2"/> | |
| 446 | - | <rect x="144" y="0" width="40" height="60" fill="#3fb950" opacity="0.5" stroke="#3fb950" stroke-width="1" rx="2"/> | |
| 447 | - | <rect x="192" y="0" width="40" height="60" fill="#3fb950" opacity="0.5" stroke="#3fb950" stroke-width="1" rx="2"/> | |
| 448 | - | <rect x="240" y="0" width="40" height="60" fill="#f7b955" rx="2"/> | |
| 449 | - | <rect x="288" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 450 | - | <rect x="336" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 451 | - | <text x="450" y="38" fill="#f7b955" font-size="11">active bin 一格格往上推,直到逼近真实市价 $1.0</text> | |
| 452 | - | </g> | |
| 453 | - | ||
| 454 | - | <!-- Frame 4 --> | |
| 455 | - | <text x="20" y="378" fill="#f7b955" font-size="13" font-weight="700">④ 同一笔 transaction 里把吃到的 X 全部发到 Raydium 按 $1.0 卖出</text> | |
| 456 | - | <g transform="translate(40, 394)"> | |
| 457 | - | <rect x="0" y="0" width="80" height="60" fill="#161b22" stroke="#bc8cff" stroke-width="1.5" rx="6"/> | |
| 458 | - | <text x="40" y="26" text-anchor="middle" fill="#bc8cff" font-size="11" font-weight="700">Meteora</text> | |
| 459 | - | <text x="40" y="44" text-anchor="middle" fill="#8b949e" font-size="10">买 X · 极便宜</text> | |
| 431 | + | <h2>4. 链上真实数据(3 笔顶级 tx)</h2> | |
| 432 | + | <p>所有数据来自 Solscan 的 transaction explorer。这三笔合计 <strong>$1.38M</strong>(占总额 46%),其余 6 笔是更小的尾单。</p> | |
| 460 | 433 | ||
| 461 | - | <text x="160" y="34" fill="#f7b955" font-size="20">→</text> | |
| 434 | + | <table> | |
| 435 | + | <thead> | |
| 436 | + | <tr> | |
| 437 | + | <th>#</th> | |
| 438 | + | <th>利润 (USDC)</th> | |
| 439 | + | <th>Slot</th> | |
| 440 | + | <th>Bot 钱包</th> | |
| 441 | + | <th>路径</th> | |
| 442 | + | <th>抢量</th> | |
| 443 | + | <th>消耗</th> | |
| 444 | + | </tr> | |
| 445 | + | </thead> | |
| 446 | + | <tbody> | |
| 447 | + | <tr> | |
| 448 | + | <td>1</td> | |
| 449 | + | <td class="num green">+$696,194</td> | |
| 450 | + | <td>416936448</td> | |
| 451 | + | <td><span class="addr">ESuvjv…cJbg8</span></td> | |
| 452 | + | <td>USDC → ANX → ANB → USDC<br/><span style="color:var(--text-dim); font-size:12px">3 跳,绕 ANX 中转</span></td> | |
| 453 | + | <td>Jito 2.3 SOL<br/>($205)</td> | |
| 454 | + | <td>1.25M CU</td> | |
| 455 | + | </tr> | |
| 456 | + | <tr> | |
| 457 | + | <td>2</td> | |
| 458 | + | <td class="num green">+$403,294</td> | |
| 459 | + | <td>416936447</td> | |
| 460 | + | <td><span class="addr">2QfBNK…nWW2T</span></td> | |
| 461 | + | <td>USDC → ANB → USDC<br/><span style="color:var(--text-dim); font-size:12px">2 跳,自定义 arb 程序 sattC</span></td> | |
| 462 | + | <td>Priority<br/>0.5 SOL ($45)</td> | |
| 463 | + | <td>0.65M CU</td> | |
| 464 | + | </tr> | |
| 465 | + | <tr> | |
| 466 | + | <td>3</td> | |
| 467 | + | <td class="num green">+$282,761</td> | |
| 468 | + | <td>416936449</td> | |
| 469 | + | <td><span class="addr">MRiYA4…JvoCsa</span></td> | |
| 470 | + | <td>USDC → ANB → USDC<br/><span style="color:var(--text-dim); font-size:12px">2 跳,nonce 账户 + 自定义 arb 程序</span></td> | |
| 471 | + | <td>Jito 5 SOL<br/>($447)</td> | |
| 472 | + | <td>0.36M CU</td> | |
| 473 | + | </tr> | |
| 474 | + | </tbody> | |
| 475 | + | </table> | |
| 462 | 476 | ||
| 463 | - | <rect x="200" y="0" width="80" height="60" fill="#161b22" stroke="#3fb950" stroke-width="1.5" rx="6"/> | |
| 464 | - | <text x="240" y="26" text-anchor="middle" fill="#3fb950" font-size="11" font-weight="700">Raydium</text> | |
| 465 | - | <text x="240" y="44" text-anchor="middle" fill="#8b949e" font-size="10">卖 X · 市价</text> | |
| 477 | + | <h3>解剖 #1:$696,194 那一笔</h3> | |
| 478 | + | <p>这是单笔最大利润。<strong>3 跳路径</strong>,绕了一个中间币 ANX 来增加每一步的"汇率优势":</p> | |
| 466 | 479 | ||
| 467 | - | <text x="320" y="34" fill="#f7b955" font-size="20">→</text> | |
| 480 | + | <ol class="steps"> | |
| 481 | + | <li><strong>付 $0.227 USDC,从 ANX-USDC DAMM v2 池换出 72,793 个 ANX</strong>(这就是 bot 唯一掏的"本金")</li> | |
| 482 | + | <li><strong>把 72,793 ANX 塞进 ANX-ANB DAMM v2 池,换出 50,011,673 ANB</strong>(这步在正常池子完成,价格紧贴市价)</li> | |
| 483 | + | <li><strong>把 50,011,673 ANB 塞进 stale 的 ANB-USDC DLMM 池,换出 $696,194 USDC</strong>(这就是 stale 池被薅的一刻)</li> | |
| 484 | + | <li><strong>给 Jitotip 5 转 2.3 SOL($205)抢落地</strong></li> | |
| 485 | + | </ol> | |
| 468 | 486 | ||
| 469 | - | <rect x="360" y="0" width="120" height="60" fill="#161b22" stroke="#f7b955" stroke-width="1.5" rx="6"/> | |
| 470 | - | <text x="420" y="26" text-anchor="middle" fill="#f7b955" font-size="11" font-weight="700">机器人钱包</text> | |
| 471 | - | <text x="420" y="44" text-anchor="middle" fill="#f7b955" font-size="10" font-weight="700">+ $400K USDC</text> | |
| 487 | + | <p>整笔交易完成后,stale 池子的 USDC 余额从 <strong>$1,412,213 → $716,018</strong>,单笔被搬走 49%。</p> | |
| 488 | + | ||
| 489 | + | <div class="panel"> | |
| 490 | + | <strong>4 条指令,1 笔 atomic tx:</strong> | |
| 491 | + | <pre style="margin:8px 0 0; color:var(--text-dim); font-size:13px; font-family:ui-monospace,monospace; overflow-x:auto;"> | |
| 492 | + | #1 ComputeBudget: SetComputeUnitLimit | |
| 493 | + | #2 Meteora DAMM v2: swap2 ← USDC → ANX | |
| 494 | + | #3 Meteora DAMM v2: swap2 ← ANX → ANB | |
| 495 | + | #4 Meteora DLMM: swap2 ← ANB → USDC(stale 池) | |
| 496 | + | #5 System Program: transfer ← Jito tip 2.3 SOL | |
| 497 | + | </pre> | |
| 498 | + | <p style="margin:10px 0 0; color:var(--text-dim); font-size:13px;">使用了 3 个 Address Lookup Tables 压缩账户引用,否则 33 个账户塞不进 1232 字节的 tx 大小限制。</p> | |
| 499 | + | </div> | |
| 472 | 500 | ||
| 473 | - | <text x="540" y="38" fill="#8b949e" font-size="11">所有指令打包进 1 笔 tx,</text> | |
| 474 | - | <text x="540" y="54" fill="#8b949e" font-size="11">失败回滚 → 永远不会亏</text> | |
| 475 | - | </g> | |
| 476 | - | </svg> | |
| 477 | - | <figcaption>套利的整个动作:低价吃光 → 市价卖出 → 同一笔交易原子完成。</figcaption> | |
| 478 | - | </figure> | |
| 501 | + | <h2>5. 三种不同 bot 的策略对比</h2> | |
| 502 | + | <p>3 笔交易、3 个独立钱包、3 套差异显著的策略——这说明它们是 3 个独立团队同时盯到了这个池子:</p> | |
| 479 | 503 | ||
| 480 | - | <h3>事件时间线</h3> | |
| 481 | 504 | <table> | |
| 482 | 505 | <thead> | |
| 483 | - | <tr><th>时刻</th><th>角色</th><th>动作</th><th>结果</th></tr> | |
| 506 | + | <tr> | |
| 507 | + | <th></th> | |
| 508 | + | <th>Bot 1(ESuvjv…)</th> | |
| 509 | + | <th>Bot 2(2QfBNK…)</th> | |
| 510 | + | <th>Bot 3(MRiYA4…)</th> | |
| 511 | + | </tr> | |
| 484 | 512 | </thead> | |
| 485 | 513 | <tbody> | |
| 486 | - | <tr><td>T+0s</td><td>鲸鱼</td><td>大额 swap,第一次"打开"这个被遗忘的池子</td><td>active bin 开始移动</td></tr> | |
| 487 | - | <tr><td>T+0.4s</td><td>Bot 1</td><td>监听器触发,发起反向套利</td><td>$0.16 成本 → $403K 盈利</td></tr> | |
| 488 | - | <tr><td>T+1.2s</td><td>Bot 2</td><td>下一个 block 抢落地</td><td>$0.23 成本 → $696K 盈利</td></tr> | |
| 489 | - | <tr><td>T+0~150s</td><td>Bot 3-6</td><td>剩余 bin 慢慢被扫</td><td>累计接近 $3M</td></tr> | |
| 490 | - | <tr><td>T+150s</td><td>—</td><td>active bin 已逼近 Raydium 市价</td><td>套利窗口关闭</td></tr> | |
| 514 | + | <tr><th>抢落地手段</th><td>Jito bundle + tip</td><td>纯 priority fee</td><td>Jito bundle + tip + nonce</td></tr> | |
| 515 | + | <tr><th>路径长度</th><td>3 跳(绕 ANX)</td><td>2 跳</td><td>2 跳</td></tr> | |
| 516 | + | <tr><th>程序结构</th><td>直接调 Meteora 程序</td><td>自定义 on-chain arb 程序<br/><span class="addr">sattC…</span></td><td>自定义 on-chain arb 程序<br/><span class="addr">AN225k…</span></td></tr> | |
| 517 | + | <tr><th>付的"过路费"</th><td>$205 → Jito 验证者</td><td>$45 → 当 leader</td><td>$447 → Jito 验证者</td></tr> | |
| 518 | + | <tr><th>本金 USDC</th><td>$0.227</td><td>$0.156</td><td>$0.127</td></tr> | |
| 519 | + | <tr><th>毛利</th><td>$696,194</td><td>$403,294</td><td>$282,761</td></tr> | |
| 520 | + | <tr><th>"过路费 / 毛利"</th><td>0.029%</td><td>0.011%</td><td>0.158%</td></tr> | |
| 491 | 521 | </tbody> | |
| 492 | 522 | </table> | |
| 493 | 523 | ||
| 494 | - | <h2>5. 技术实现骨架(如果你想做)</h2> | |
| 524 | + | <div class="callout"> | |
| 525 | + | <strong>有意思的是 Bot 3 的 tip 反而最高($447)但抢到的利润最少。</strong>原因可能是:池子被前两笔搬空了 696K + 403K = 1.1M,留给 Bot 3 的 USDC 只剩 ~580K,所以即便它愿意付更多 tip,可吃的肉本身已经少了。 | |
| 526 | + | </div> | |
| 495 | 527 | ||
| 496 | - | <ol class="steps"> | |
| 497 | - | <li><strong>扫描全网 Meteora DLMM 池找"stale"标的。</strong>拉所有 DLMM 池的 PDA 账户,用 SDK 读 active bin 价格,跟 Jupiter / Birdeye 拿到的市价对比。差 5-10% 以上的进候选池。这一步可以离线一天扫一次。</li> | |
| 498 | - | <li><strong>实时盯盘候选池。</strong>用 Helius / Triton 的 Geyser gRPC 或 <code>accountSubscribe</code> WebSocket 订阅这些池子账户,状态一变就 push 给你(延迟 50-200ms)。</li> | |
| 499 | - | <li><strong>盈亏模拟。</strong>调用 <code>@meteora-ag/dlmm</code> 模拟从这个池子买 X、再到 Raydium 卖的总收益。扣掉两边手续费、Solana 优先费、Jito tip 后还赚才发交易。</li> | |
| 500 | - | <li><strong>原子 transaction。</strong>把"Meteora 买 + Raydium 卖"两条 swap 指令打到同一笔 tx 里,每个指令都设 <code>min_out_amount</code>,价格滑了整笔回滚。账户多塞不下时用 Address Lookup Table (LUT) 压缩。</li> | |
| 501 | - | <li><strong>抢落地。</strong>普通 RPC 抢不过别人。主流做法:Jito bundle(带 tip)+ Helius Sender / Triton Cascade 同时发出去,哪个先 land 算哪个。tip 大小是 bot 之间最常调的旋钮。</li> | |
| 502 | - | </ol> | |
| 528 | + | <h2>6. Stale 池余额的"清算曲线"</h2> | |
| 529 | + | <figure> | |
| 530 | + | <svg viewBox="0 0 760 280" xmlns="http://www.w3.org/2000/svg"> | |
| 531 | + | <rect width="760" height="280" fill="url(#bg1)" rx="10"/> | |
| 532 | + | <!-- Axes --> | |
| 533 | + | <line x1="80" y1="40" x2="80" y2="220" stroke="#30363d" stroke-width="1"/> | |
| 534 | + | <line x1="80" y1="220" x2="700" y2="220" stroke="#30363d" stroke-width="1"/> | |
| 535 | + | ||
| 536 | + | <!-- Y labels --> | |
| 537 | + | <text x="74" y="48" text-anchor="end" fill="#8b949e" font-size="10">$1.4M</text> | |
| 538 | + | <text x="74" y="98" text-anchor="end" fill="#8b949e" font-size="10">$1.0M</text> | |
| 539 | + | <text x="74" y="148" text-anchor="end" fill="#8b949e" font-size="10">$600K</text> | |
| 540 | + | <text x="74" y="198" text-anchor="end" fill="#8b949e" font-size="10">$200K</text> | |
| 541 | + | <text x="74" y="220" text-anchor="end" fill="#8b949e" font-size="10">$0</text> | |
| 542 | + | ||
| 543 | + | <!-- X labels --> | |
| 544 | + | <text x="160" y="240" text-anchor="middle" fill="#8b949e" font-size="11">slot 416936447</text> | |
| 545 | + | <text x="380" y="240" text-anchor="middle" fill="#8b949e" font-size="11">slot 416936448</text> | |
| 546 | + | <text x="600" y="240" text-anchor="middle" fill="#8b949e" font-size="11">slot 416936449</text> | |
| 547 | + | ||
| 548 | + | <!-- Bars showing pool USDC drain --> | |
| 549 | + | <!-- Pre tx2: 2.18M --> | |
| 550 | + | <rect x="100" y="40" width="120" height="180" fill="#3fb950" opacity="0.5"/> | |
| 551 | + | <text x="160" y="58" text-anchor="middle" fill="#fff" font-size="11" font-weight="700">$2.18M</text> | |
| 552 | + | <text x="160" y="32" text-anchor="middle" fill="#3fb950" font-size="10">事件前</text> | |
| 553 | + | ||
| 554 | + | <!-- Post tx2: 1.77M (lost 403K) --> | |
| 555 | + | <rect x="320" y="92" width="120" height="128" fill="#f7b955" opacity="0.6"/> | |
| 556 | + | <text x="380" y="110" text-anchor="middle" fill="#fff" font-size="11" font-weight="700">$1.41M</text> | |
| 557 | + | <text x="380" y="32" text-anchor="middle" fill="#f7b955" font-size="10">tx#2 后 (-$403K)</text> | |
| 558 | + | ||
| 559 | + | <!-- Post tx1: 716K (lost 696K) --> | |
| 560 | + | <rect x="540" y="170" width="60" height="50" fill="#f85149" opacity="0.7"/> | |
| 561 | + | <text x="570" y="166" text-anchor="middle" fill="#fff" font-size="11" font-weight="700">$716K</text> | |
| 562 | + | <text x="570" y="32" text-anchor="middle" fill="#f85149" font-size="10">tx#1 后 (-$696K)</text> | |
| 563 | + | ||
| 564 | + | <!-- Post tx3: 298K (lost 282K) --> | |
| 565 | + | <rect x="620" y="200" width="60" height="20" fill="#f85149" opacity="0.9"/> | |
| 566 | + | <text x="650" y="195" text-anchor="middle" fill="#fff" font-size="11" font-weight="700">$298K</text> | |
| 567 | + | <text x="650" y="32" text-anchor="middle" fill="#f85149" font-size="10">tx#3 后 (-$282K)</text> | |
| 568 | + | ||
| 569 | + | <text x="380" y="266" text-anchor="middle" fill="#8b949e" font-size="11">Stale 池 USDC 余额(仅显示 3 笔最大 tx 的影响)</text> | |
| 570 | + | </svg> | |
| 571 | + | <figcaption>3 个连续 slot 内,USDC 从 $2.18M 跌到 $298K,跌幅 86%。剩余的 $298K 在后续 6 笔小 tx 里被分掉。</figcaption> | |
| 572 | + | </figure> | |
| 503 | 573 | ||
| 504 | - | <div class="callout"> | |
| 505 | - | <strong>提示:</strong>这种机会真正的瓶颈不在策略本身,而在<strong>抢速度</strong>和<strong>风险控制</strong>。一旦池子被发现,每个 block 都有 5-20 个机器人在抢同一笔利润。原子 + Jito + 充足的 priority fee 是最低门槛。 | |
| 574 | + | <h2>7. 修正后的核心结论</h2> | |
| 575 | + | ||
| 576 | + | <div class="callout update"> | |
| 577 | + | <strong>方向修正:</strong>过期池套利可以走两个方向: | |
| 578 | + | <ol style="margin:8px 0 0; padding-left:22px;"> | |
| 579 | + | <li>代币涨了,但 LP 把 X 代币挂在低价 bins 等卖 → bot 用 USDC 把廉价代币<strong>买光</strong>转手到市场。</li> | |
| 580 | + | <li><strong>代币跌了,但 LP 把 USDC 挂在高价 bins 等买 → bot 用近乎为零成本的代币把高价 USDC <strong>赎光</strong>。</strong>(本次事件)</li> | |
| 581 | + | </ol> | |
| 582 | + | 两种方向本质一致:DLMM 的 active bin 必须靠交易才能移动,没人交易就漂移成"过期"。 | |
| 506 | 583 | </div> | |
| 507 | 584 | ||
| 508 | - | <h2>6. 一句话总结</h2> | |
| 585 | + | <h3>对 LP 的启示</h3> | |
| 586 | + | <p>提供 DLMM 集中流动性的人,必须明白挂出去的 bin 等价于<strong>限价订单簿</strong>。如果你挂在 active bin 下方放 USDC,等价于"愿意按这些价位买代币"——代币涨了你赚,代币归零你亏。如果代币只是冷门、流动性低,更没人会来推动 active bin。所以 LP 必须:</p> | |
| 587 | + | <ol style="padding-left:22px;"> | |
| 588 | + | <li>给 bins 设一个"我能接受的最低价格"和"最高价格"区间,超出就会暴露。</li> | |
| 589 | + | <li>对低市值 / 高波动代币,至少每周检查一次,必要时用 SDK 调用 <code>removeLiquidity</code> 收回。</li> | |
| 590 | + | <li>不要假设"价格往哪个方向走,DLMM 都能自适应"——它不会。</li> | |
| 591 | + | </ol> | |
| 592 | + | ||
| 593 | + | <h3>对套利者的启示</h3> | |
| 594 | + | <p>这种"反向 stale 池"在 Solana 链上数量比想象中多。扫描方法和 v1 报告里描述的一致:拉所有 DLMM 池 → 算出每个池子的 active bin 隐含价格 → 跟 Jupiter 聚合市价对比 → 价差超过阈值就放进监听清单。<strong>关键是阈值要双向:</strong></p> | |
| 595 | + | <ul style="padding-left:22px;"> | |
| 596 | + | <li>active bin 价 >> 市价:池子里 USDC 太贵,可以把代币塞进去赎 USDC(本次事件)</li> | |
| 597 | + | <li>active bin 价 << 市价:池子里代币太便宜,可以付 USDC 把代币买光(v1 描述的方向)</li> | |
| 598 | + | </ul> | |
| 599 | + | ||
| 600 | + | <h2>8. 一句话最终总结</h2> | |
| 509 | 601 | <div class="quote"> | |
| 510 | - | <strong>Bin 不会自动更新价格</strong>,DLMM 池子只在被交易时才移动 active bin。LP 创建池子后 10 个月不维护,外部市场暴涨 1000 倍——池子里那些"高于原始 active bin 但远低于市场价"的 bins 就成了静悄悄挂着的「便宜代币堆」,等着第一个发现它的套利机器人一口气全吃光。 | |
| 602 | + | 这次事件不是机器人"截胡了某个大额 swap",而是机器人发现了一个 LP 留下的"<strong>10 个月没人维护的限价单簿</strong>",用近乎为零的成本(几毛钱本金 + 几百美金 Jito tip)把这个限价单簿里的 USDC 一次性结清。鲸鱼不是 swap 用户,鲸鱼就是当初那个 LP——他亲手把钱挂在过期价位上 10 个月,等到第一个发现的人来收。 | |
| 511 | 603 | </div> | |
| 512 | 604 | ||
| 513 | - | <p>这就是 stale pool / stale LP arbitrage。错不在 Meteora 协议,而在 LP 自己。这种漏洞跟 Uniswap v3 在以太坊上遇到的"untracked LP"问题完全一样,只是 Solana 上池子多、LP 散、被发现的速度极快——这次连 1 秒都没撑住。</p> | |
| 514 | - | ||
| 515 | 605 | <footer> | |
| 516 | - | <p>资料来源: | |
| 606 | + | <p>资料来源 · | |
| 517 | 607 | <a href="https://x.com/anshu_code/status/2051888998671581324" target="_blank">@anshu_code 主推</a> · | |
| 518 | - | <a href="https://x.com/anshu_code/status/2051392982327468463" target="_blank">前一条引用</a> · | |
| 519 | - | Meteora DLMM 文档 · Jupiter / Helius 公开技术资料 | |
| 608 | + | <a href="https://x.com/anshu_code/status/2051889010621219025" target="_blank">9 笔交易清单</a> · | |
| 609 | + | Solscan: | |
| 610 | + | <a href="https://solscan.io/tx/J8TY8VkjZpAAm78GwbnEE1xkBwGdheQ4C1VsZA7Cwcv1AyDw3PxTQJ3eWh9YZmZyLQnLD3fuHBsihXbX4sTATi8" target="_blank">$696K tx</a> · | |
| 611 | + | <a href="https://solscan.io/tx/3pb5512ttABHr8mKCM8MTfqTHqbQYxuFMQu8vrof6j24fdRz3LSp4LiLoNhbjtNec43UjFivQGTjjDEKaJ5AYhtx" target="_blank">$403K tx</a> · | |
| 612 | + | <a href="https://solscan.io/tx/5Z1zXUMKKrxmDfreMAFWTp11mwMxVqusbVSfbokUFURZ2xkYfUuXNzNuYMh2vn55eFDhGgHRkQEHRtoSr4i2sTah" target="_blank">$282K tx</a> | |
| 520 | 613 | </p> | |
| 521 | - | <p>本文为根据公开链上数据和推文内容做的技术拆解,不构成投资建议;过期池套利涉及极高的速度竞争和资金风险,复刻前请自行评估。</p> | |
| 614 | + | <p>本文为根据公开链上数据和推文做的技术拆解,不构成投资建议;过期池套利涉及极高的速度竞争与资金风险,复刻前请自行评估。</p> | |
| 522 | 615 | </footer> | |
| 523 | 616 | ||
| 524 | 617 | </div> | |
geekmind revised this gist 1 month ago. Go to revision
1 file changed, 526 insertions
meteora_stale_pool_arb.html(file created)
| @@ -0,0 +1,526 @@ | |||
| 1 | + | <!DOCTYPE html> | |
| 2 | + | <html lang="zh-CN"> | |
| 3 | + | <head> | |
| 4 | + | <meta charset="UTF-8" /> | |
| 5 | + | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
| 6 | + | <title>Solana Meteora 过期池套利拆解:299 万美金消失的 150 秒</title> | |
| 7 | + | <style> | |
| 8 | + | :root { | |
| 9 | + | --bg: #0d1117; | |
| 10 | + | --panel: #161b22; | |
| 11 | + | --panel2: #1c2330; | |
| 12 | + | --border: #30363d; | |
| 13 | + | --text: #e6edf3; | |
| 14 | + | --text-dim: #8b949e; | |
| 15 | + | --accent: #f7b955; | |
| 16 | + | --accent2: #58a6ff; | |
| 17 | + | --green: #3fb950; | |
| 18 | + | --red: #f85149; | |
| 19 | + | --purple: #bc8cff; | |
| 20 | + | } | |
| 21 | + | * { box-sizing: border-box; } | |
| 22 | + | html, body { | |
| 23 | + | margin: 0; padding: 0; | |
| 24 | + | background: var(--bg); | |
| 25 | + | color: var(--text); | |
| 26 | + | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", | |
| 27 | + | "Hiragino Sans GB", "Microsoft YaHei", sans-serif; | |
| 28 | + | line-height: 1.7; | |
| 29 | + | } | |
| 30 | + | .wrap { | |
| 31 | + | max-width: 920px; | |
| 32 | + | margin: 0 auto; | |
| 33 | + | padding: 48px 28px 96px; | |
| 34 | + | } | |
| 35 | + | header { | |
| 36 | + | border-bottom: 1px solid var(--border); | |
| 37 | + | padding-bottom: 28px; | |
| 38 | + | margin-bottom: 36px; | |
| 39 | + | } | |
| 40 | + | .tag { | |
| 41 | + | display: inline-block; | |
| 42 | + | background: rgba(247, 185, 85, 0.12); | |
| 43 | + | color: var(--accent); | |
| 44 | + | padding: 4px 12px; | |
| 45 | + | border-radius: 999px; | |
| 46 | + | font-size: 12px; | |
| 47 | + | letter-spacing: 0.04em; | |
| 48 | + | text-transform: uppercase; | |
| 49 | + | margin-bottom: 16px; | |
| 50 | + | border: 1px solid rgba(247, 185, 85, 0.3); | |
| 51 | + | } | |
| 52 | + | h1 { | |
| 53 | + | font-size: 34px; | |
| 54 | + | line-height: 1.25; | |
| 55 | + | margin: 0 0 12px; | |
| 56 | + | font-weight: 700; | |
| 57 | + | letter-spacing: -0.01em; | |
| 58 | + | } | |
| 59 | + | .subtitle { | |
| 60 | + | color: var(--text-dim); | |
| 61 | + | font-size: 16px; | |
| 62 | + | margin: 0; | |
| 63 | + | } | |
| 64 | + | h2 { | |
| 65 | + | font-size: 22px; | |
| 66 | + | margin: 56px 0 14px; | |
| 67 | + | padding-left: 12px; | |
| 68 | + | border-left: 4px solid var(--accent); | |
| 69 | + | } | |
| 70 | + | h3 { | |
| 71 | + | font-size: 17px; | |
| 72 | + | margin: 28px 0 10px; | |
| 73 | + | color: var(--accent2); | |
| 74 | + | } | |
| 75 | + | p { margin: 12px 0; } | |
| 76 | + | code { | |
| 77 | + | background: var(--panel2); | |
| 78 | + | border: 1px solid var(--border); | |
| 79 | + | padding: 1px 6px; | |
| 80 | + | border-radius: 4px; | |
| 81 | + | font-size: 13.5px; | |
| 82 | + | color: var(--accent); | |
| 83 | + | font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; | |
| 84 | + | } | |
| 85 | + | .stats { | |
| 86 | + | display: grid; | |
| 87 | + | grid-template-columns: repeat(4, 1fr); | |
| 88 | + | gap: 12px; | |
| 89 | + | margin: 28px 0; | |
| 90 | + | } | |
| 91 | + | .stat { | |
| 92 | + | background: var(--panel); | |
| 93 | + | border: 1px solid var(--border); | |
| 94 | + | border-radius: 10px; | |
| 95 | + | padding: 18px 16px; | |
| 96 | + | text-align: center; | |
| 97 | + | } | |
| 98 | + | .stat .num { | |
| 99 | + | font-size: 26px; | |
| 100 | + | font-weight: 700; | |
| 101 | + | color: var(--accent); | |
| 102 | + | margin-bottom: 4px; | |
| 103 | + | font-variant-numeric: tabular-nums; | |
| 104 | + | } | |
| 105 | + | .stat .lbl { | |
| 106 | + | color: var(--text-dim); | |
| 107 | + | font-size: 12.5px; | |
| 108 | + | } | |
| 109 | + | .quote { | |
| 110 | + | background: var(--panel); | |
| 111 | + | border-left: 3px solid var(--accent2); | |
| 112 | + | padding: 16px 20px; | |
| 113 | + | border-radius: 0 8px 8px 0; | |
| 114 | + | color: var(--text); | |
| 115 | + | font-size: 15px; | |
| 116 | + | margin: 18px 0; | |
| 117 | + | } | |
| 118 | + | .quote .src { | |
| 119 | + | display: block; | |
| 120 | + | margin-top: 8px; | |
| 121 | + | color: var(--text-dim); | |
| 122 | + | font-size: 12.5px; | |
| 123 | + | } | |
| 124 | + | .panel { | |
| 125 | + | background: var(--panel); | |
| 126 | + | border: 1px solid var(--border); | |
| 127 | + | border-radius: 12px; | |
| 128 | + | padding: 22px 24px; | |
| 129 | + | margin: 22px 0; | |
| 130 | + | } | |
| 131 | + | figure { | |
| 132 | + | margin: 22px 0; | |
| 133 | + | background: var(--panel); | |
| 134 | + | border: 1px solid var(--border); | |
| 135 | + | border-radius: 12px; | |
| 136 | + | padding: 22px 18px 14px; | |
| 137 | + | } | |
| 138 | + | figcaption { | |
| 139 | + | color: var(--text-dim); | |
| 140 | + | font-size: 13px; | |
| 141 | + | text-align: center; | |
| 142 | + | margin-top: 10px; | |
| 143 | + | } | |
| 144 | + | svg { display: block; max-width: 100%; height: auto; margin: 0 auto; } | |
| 145 | + | ||
| 146 | + | table { | |
| 147 | + | width: 100%; | |
| 148 | + | border-collapse: collapse; | |
| 149 | + | margin: 18px 0; | |
| 150 | + | font-size: 14px; | |
| 151 | + | } | |
| 152 | + | th, td { | |
| 153 | + | padding: 10px 12px; | |
| 154 | + | border-bottom: 1px solid var(--border); | |
| 155 | + | text-align: left; | |
| 156 | + | } | |
| 157 | + | th { | |
| 158 | + | background: var(--panel2); | |
| 159 | + | color: var(--text-dim); | |
| 160 | + | font-weight: 600; | |
| 161 | + | font-size: 13px; | |
| 162 | + | text-transform: uppercase; | |
| 163 | + | letter-spacing: 0.03em; | |
| 164 | + | } | |
| 165 | + | ol.steps { | |
| 166 | + | counter-reset: s; | |
| 167 | + | list-style: none; | |
| 168 | + | padding: 0; | |
| 169 | + | } | |
| 170 | + | ol.steps > li { | |
| 171 | + | counter-increment: s; | |
| 172 | + | position: relative; | |
| 173 | + | padding: 14px 18px 14px 56px; | |
| 174 | + | margin: 10px 0; | |
| 175 | + | background: var(--panel); | |
| 176 | + | border: 1px solid var(--border); | |
| 177 | + | border-radius: 10px; | |
| 178 | + | } | |
| 179 | + | ol.steps > li::before { | |
| 180 | + | content: counter(s); | |
| 181 | + | position: absolute; | |
| 182 | + | left: 16px; | |
| 183 | + | top: 14px; | |
| 184 | + | width: 28px; | |
| 185 | + | height: 28px; | |
| 186 | + | border-radius: 50%; | |
| 187 | + | background: var(--accent); | |
| 188 | + | color: #1d1300; | |
| 189 | + | font-weight: 700; | |
| 190 | + | text-align: center; | |
| 191 | + | line-height: 28px; | |
| 192 | + | font-size: 14px; | |
| 193 | + | } | |
| 194 | + | .callout { | |
| 195 | + | background: rgba(88, 166, 255, 0.08); | |
| 196 | + | border: 1px solid rgba(88, 166, 255, 0.3); | |
| 197 | + | border-radius: 10px; | |
| 198 | + | padding: 14px 18px; | |
| 199 | + | margin: 18px 0; | |
| 200 | + | color: var(--text); | |
| 201 | + | font-size: 14.5px; | |
| 202 | + | } | |
| 203 | + | .callout.warn { | |
| 204 | + | background: rgba(248, 81, 73, 0.08); | |
| 205 | + | border-color: rgba(248, 81, 73, 0.3); | |
| 206 | + | } | |
| 207 | + | .callout strong { color: var(--accent2); } | |
| 208 | + | .callout.warn strong { color: var(--red); } | |
| 209 | + | footer { | |
| 210 | + | margin-top: 64px; | |
| 211 | + | padding-top: 24px; | |
| 212 | + | border-top: 1px solid var(--border); | |
| 213 | + | color: var(--text-dim); | |
| 214 | + | font-size: 13px; | |
| 215 | + | } | |
| 216 | + | footer a { color: var(--accent2); text-decoration: none; } | |
| 217 | + | footer a:hover { text-decoration: underline; } | |
| 218 | + | ||
| 219 | + | @media (max-width: 640px) { | |
| 220 | + | .wrap { padding: 28px 16px 64px; } | |
| 221 | + | h1 { font-size: 26px; } | |
| 222 | + | .stats { grid-template-columns: repeat(2, 1fr); } | |
| 223 | + | } | |
| 224 | + | </style> | |
| 225 | + | </head> | |
| 226 | + | <body> | |
| 227 | + | <div class="wrap"> | |
| 228 | + | ||
| 229 | + | <header> | |
| 230 | + | <span class="tag">Solana · MEV · DEX 套利</span> | |
| 231 | + | <h1>299 万美金,150 秒蒸发<br/>—— Meteora 过期池套利完整拆解</h1> | |
| 232 | + | <p class="subtitle">用图解搞懂:DLMM 的 bin 是什么,为什么旧 LP 池会变成"白送代币的提款机",以及套利机器人是怎么把它们一口气吞掉的。</p> | |
| 233 | + | </header> | |
| 234 | + | ||
| 235 | + | <section> | |
| 236 | + | <div class="stats"> | |
| 237 | + | <div class="stat"><div class="num">$2.99M</div><div class="lbl">被抽走金额</div></div> | |
| 238 | + | <div class="stat"><div class="num">150s</div><div class="lbl">总耗时</div></div> | |
| 239 | + | <div class="stat"><div class="num">6 + 1</div><div class="lbl">机器人 + 鲸鱼</div></div> | |
| 240 | + | <div class="stat"><div class="num">10 个月</div><div class="lbl">池子无人维护</div></div> | |
| 241 | + | </div> | |
| 242 | + | ||
| 243 | + | <div class="quote"> | |
| 244 | + | "$2,993,502 drained from a single Solana pool in 150 seconds. 1 whale. 6 bots. 9 transactions. 1 misconfigured Meteora pool that sat for 10 months." | |
| 245 | + | <span class="src">—— @anshu_code, X / 2026-05-06</span> | |
| 246 | + | </div> | |
| 247 | + | ||
| 248 | + | <p>这条推文讲的,是 Solana 链上一个被忽略了 10 个月的 <strong>Meteora DLMM 流动性池</strong>,在 150 秒内被 6 个套利机器人和一个大户合力"洗"了一遍,搬走 299 万美金。本文用图把它拆开讲清楚。</p> | |
| 249 | + | </section> | |
| 250 | + | ||
| 251 | + | <h2>1. 它属于哪一类套利?</h2> | |
| 252 | + | <p>这种玩法的术语叫 <strong>Stale Pool Arbitrage(过期池套利)</strong>。靶子是那些 <em>LP 挂上去就不再维护</em> 的集中流动性池——挂的还是几个月前的"老价格",外部市场早已涨飞,池子却毫无觉察。</p> | |
| 253 | + | ||
| 254 | + | <figure> | |
| 255 | + | <svg viewBox="0 0 760 280" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="过期池套利示意"> | |
| 256 | + | <defs> | |
| 257 | + | <linearGradient id="bg1" x1="0" x2="0" y1="0" y2="1"> | |
| 258 | + | <stop offset="0" stop-color="#1c2330"/> | |
| 259 | + | <stop offset="1" stop-color="#161b22"/> | |
| 260 | + | </linearGradient> | |
| 261 | + | <marker id="arrow" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto"> | |
| 262 | + | <path d="M0,0 L8,3 L0,6 z" fill="#f7b955"/> | |
| 263 | + | </marker> | |
| 264 | + | </defs> | |
| 265 | + | <rect width="760" height="280" fill="url(#bg1)" rx="10"/> | |
| 266 | + | ||
| 267 | + | <!-- Raydium box --> | |
| 268 | + | <rect x="40" y="60" width="240" height="160" fill="#0d1117" stroke="#3fb950" stroke-width="1.5" rx="10"/> | |
| 269 | + | <text x="160" y="90" text-anchor="middle" fill="#3fb950" font-size="15" font-weight="700">Raydium / 真实市场</text> | |
| 270 | + | <text x="160" y="135" text-anchor="middle" fill="#e6edf3" font-size="13">代币 X 已涨到</text> | |
| 271 | + | <text x="160" y="170" text-anchor="middle" fill="#3fb950" font-size="32" font-weight="700">$1.00</text> | |
| 272 | + | <text x="160" y="195" text-anchor="middle" fill="#8b949e" font-size="11">活跃交易 · 价格随市场实时更新</text> | |
| 273 | + | ||
| 274 | + | <!-- Meteora box --> | |
| 275 | + | <rect x="480" y="60" width="240" height="160" fill="#0d1117" stroke="#f85149" stroke-width="1.5" rx="10"/> | |
| 276 | + | <text x="600" y="90" text-anchor="middle" fill="#f85149" font-size="15" font-weight="700">Meteora 旧池子</text> | |
| 277 | + | <text x="600" y="135" text-anchor="middle" fill="#e6edf3" font-size="13">10 个月没人交易</text> | |
| 278 | + | <text x="600" y="170" text-anchor="middle" fill="#f85149" font-size="32" font-weight="700">$0.001</text> | |
| 279 | + | <text x="600" y="195" text-anchor="middle" fill="#8b949e" font-size="11">价格停在 LP 创建时的水平</text> | |
| 280 | + | ||
| 281 | + | <!-- Bridge / arrow --> | |
| 282 | + | <text x="380" y="130" text-anchor="middle" fill="#f7b955" font-size="13" font-weight="700">价差 1000×</text> | |
| 283 | + | <line x1="290" y1="150" x2="470" y2="150" stroke="#f7b955" stroke-width="2" marker-end="url(#arrow)"/> | |
| 284 | + | <text x="380" y="180" text-anchor="middle" fill="#8b949e" font-size="11">套利机器人在这里下手</text> | |
| 285 | + | </svg> | |
| 286 | + | <figcaption>同一种代币,两个池子,价格差 1000 倍。差距在 LP 不维护时会一直存在。</figcaption> | |
| 287 | + | </figure> | |
| 288 | + | ||
| 289 | + | <h2>2. 先理解 DLMM:什么是 bin?</h2> | |
| 290 | + | <p>Meteora DLMM(Dynamic Liquidity Market Maker)跟 Uniswap v3 思路一样:把价格切成一格一格的"档位",每一档叫 <strong>bin</strong>。LP 不是在一条曲线上放钱,而是把代币塞进具体某几个 bin 里。</p> | |
| 291 | + | ||
| 292 | + | <figure> | |
| 293 | + | <svg viewBox="0 0 760 320" xmlns="http://www.w3.org/2000/svg"> | |
| 294 | + | <rect width="760" height="320" fill="url(#bg1)" rx="10"/> | |
| 295 | + | ||
| 296 | + | <!-- Active bin marker --> | |
| 297 | + | <line x1="380" y1="40" x2="380" y2="280" stroke="#f7b955" stroke-width="1" stroke-dasharray="4 4"/> | |
| 298 | + | <text x="380" y="32" text-anchor="middle" fill="#f7b955" font-size="13" font-weight="700">↓ Active Bin(当前价)</text> | |
| 299 | + | ||
| 300 | + | <!-- Bins --> | |
| 301 | + | <g font-family="ui-monospace, monospace" font-size="11"> | |
| 302 | + | <!-- Y bins (left, USDC) --> | |
| 303 | + | <g> | |
| 304 | + | <rect x="60" y="180" width="48" height="100" fill="#3fb950" opacity="0.85" rx="3"/> | |
| 305 | + | <rect x="115" y="160" width="48" height="120" fill="#3fb950" opacity="0.85" rx="3"/> | |
| 306 | + | <rect x="170" y="140" width="48" height="140" fill="#3fb950" opacity="0.85" rx="3"/> | |
| 307 | + | <rect x="225" y="120" width="48" height="160" fill="#3fb950" opacity="0.85" rx="3"/> | |
| 308 | + | <rect x="280" y="105" width="48" height="175" fill="#3fb950" opacity="0.85" rx="3"/> | |
| 309 | + | <text x="84" y="298" text-anchor="middle" fill="#8b949e">$0.5</text> | |
| 310 | + | <text x="139" y="298" text-anchor="middle" fill="#8b949e">$0.6</text> | |
| 311 | + | <text x="194" y="298" text-anchor="middle" fill="#8b949e">$0.7</text> | |
| 312 | + | <text x="249" y="298" text-anchor="middle" fill="#8b949e">$0.8</text> | |
| 313 | + | <text x="304" y="298" text-anchor="middle" fill="#8b949e">$0.9</text> | |
| 314 | + | </g> | |
| 315 | + | <!-- Active --> | |
| 316 | + | <rect x="358" y="100" width="44" height="180" fill="#f7b955" opacity="0.9" rx="3"/> | |
| 317 | + | <text x="380" y="298" text-anchor="middle" fill="#f7b955" font-weight="700">$1.0</text> | |
| 318 | + | ||
| 319 | + | <!-- X bins (right, token) --> | |
| 320 | + | <g> | |
| 321 | + | <rect x="430" y="105" width="48" height="175" fill="#bc8cff" opacity="0.85" rx="3"/> | |
| 322 | + | <rect x="485" y="120" width="48" height="160" fill="#bc8cff" opacity="0.85" rx="3"/> | |
| 323 | + | <rect x="540" y="140" width="48" height="140" fill="#bc8cff" opacity="0.85" rx="3"/> | |
| 324 | + | <rect x="595" y="160" width="48" height="120" fill="#bc8cff" opacity="0.85" rx="3"/> | |
| 325 | + | <rect x="650" y="180" width="48" height="100" fill="#bc8cff" opacity="0.85" rx="3"/> | |
| 326 | + | <text x="454" y="298" text-anchor="middle" fill="#8b949e">$1.1</text> | |
| 327 | + | <text x="509" y="298" text-anchor="middle" fill="#8b949e">$1.2</text> | |
| 328 | + | <text x="564" y="298" text-anchor="middle" fill="#8b949e">$1.3</text> | |
| 329 | + | <text x="619" y="298" text-anchor="middle" fill="#8b949e">$1.4</text> | |
| 330 | + | <text x="674" y="298" text-anchor="middle" fill="#8b949e">$1.5</text> | |
| 331 | + | </g> | |
| 332 | + | </g> | |
| 333 | + | ||
| 334 | + | <!-- Labels --> | |
| 335 | + | <text x="194" y="80" text-anchor="middle" fill="#3fb950" font-size="13" font-weight="700">下方 bins</text> | |
| 336 | + | <text x="194" y="98" text-anchor="middle" fill="#3fb950" font-size="11">装 USDC(限价买单)</text> | |
| 337 | + | ||
| 338 | + | <text x="564" y="80" text-anchor="middle" fill="#bc8cff" font-size="13" font-weight="700">上方 bins</text> | |
| 339 | + | <text x="564" y="98" text-anchor="middle" fill="#bc8cff" font-size="11">装 代币 X(限价卖单)</text> | |
| 340 | + | </svg> | |
| 341 | + | <figcaption>DLMM 池子结构:active bin 把价格分成左右两半。左边的 bin 装 USDC,右边的装代币。</figcaption> | |
| 342 | + | </figure> | |
| 343 | + | ||
| 344 | + | <div class="callout"> | |
| 345 | + | <strong>关键三点:</strong> | |
| 346 | + | <ol style="margin:8px 0 0; padding-left: 20px;"> | |
| 347 | + | <li>每个 bin 对应一个<strong>固定</strong>的兑换价(创建时算好的常数)。</li> | |
| 348 | + | <li>active bin <strong>下方</strong>的 bins 装 Y(USDC),是"低价等买 X 的限价买单"。</li> | |
| 349 | + | <li>active bin <strong>上方</strong>的 bins 装 X(代币),是"高价等卖出的限价卖单"。</li> | |
| 350 | + | </ol> | |
| 351 | + | </div> | |
| 352 | + | ||
| 353 | + | <h2>3. 为什么 bin 会"老价格存在"?</h2> | |
| 354 | + | <p>这是这次事件最反直觉的地方。<strong>DLMM 池子的价格不会自动跟着外部市场走</strong>——它只在<em>有人在本池子做 swap</em>的时候才移动 active bin。</p> | |
| 355 | + | ||
| 356 | + | <figure> | |
| 357 | + | <svg viewBox="0 0 760 360" xmlns="http://www.w3.org/2000/svg"> | |
| 358 | + | <rect width="760" height="360" fill="url(#bg1)" rx="10"/> | |
| 359 | + | ||
| 360 | + | <!-- Time axis --> | |
| 361 | + | <line x1="60" y1="320" x2="700" y2="320" stroke="#30363d" stroke-width="1"/> | |
| 362 | + | <text x="60" y="345" fill="#8b949e" font-size="11">Day 0</text> | |
| 363 | + | <text x="380" y="345" fill="#8b949e" font-size="11">Day 1 ~ 300(无人交易)</text> | |
| 364 | + | <text x="700" y="345" text-anchor="end" fill="#8b949e" font-size="11">Day 300(被发现)</text> | |
| 365 | + | ||
| 366 | + | <!-- Raydium price line - rising --> | |
| 367 | + | <text x="60" y="48" fill="#3fb950" font-size="12" font-weight="700">Raydium 真实市价</text> | |
| 368 | + | <path d="M60,290 Q200,280 300,200 T700,80" stroke="#3fb950" stroke-width="2.5" fill="none"/> | |
| 369 | + | <circle cx="60" cy="290" r="4" fill="#3fb950"/> | |
| 370 | + | <circle cx="700" cy="80" r="5" fill="#3fb950"/> | |
| 371 | + | <text x="80" y="285" fill="#3fb950" font-size="11">$0.001</text> | |
| 372 | + | <text x="688" y="74" text-anchor="end" fill="#3fb950" font-size="11" font-weight="700">$1.00 ↑↑↑</text> | |
| 373 | + | ||
| 374 | + | <!-- Meteora price line - flat --> | |
| 375 | + | <text x="60" y="200" fill="#f85149" font-size="12" font-weight="700">Meteora 池子 active bin</text> | |
| 376 | + | <line x1="60" y1="290" x2="640" y2="290" stroke="#f85149" stroke-width="2.5" stroke-dasharray="6 4"/> | |
| 377 | + | <circle cx="60" cy="290" r="4" fill="#f85149"/> | |
| 378 | + | <circle cx="640" cy="290" r="4" fill="#f85149"/> | |
| 379 | + | <text x="380" y="282" text-anchor="middle" fill="#f85149" font-size="11">10 个月一动不动 · 一直停在 $0.001</text> | |
| 380 | + | ||
| 381 | + | <!-- Gap arrow --> | |
| 382 | + | <line x1="660" y1="80" x2="660" y2="280" stroke="#f7b955" stroke-width="1.5" stroke-dasharray="3 3"/> | |
| 383 | + | <line x1="650" y1="80" x2="670" y2="80" stroke="#f7b955" stroke-width="1.5"/> | |
| 384 | + | <line x1="650" y1="280" x2="670" y2="280" stroke="#f7b955" stroke-width="1.5"/> | |
| 385 | + | <text x="678" y="180" fill="#f7b955" font-size="13" font-weight="700">价差</text> | |
| 386 | + | <text x="678" y="198" fill="#f7b955" font-size="11">1000×</text> | |
| 387 | + | </svg> | |
| 388 | + | <figcaption>外部市场涨了 1000 倍,Meteora 池子的 active bin 却没移动半步——因为没人来这里 swap。</figcaption> | |
| 389 | + | </figure> | |
| 390 | + | ||
| 391 | + | <p>所以"代币涨了为什么 bin 还能低价存在"的答案是:</p> | |
| 392 | + | <div class="callout warn"> | |
| 393 | + | <strong>Solana 链上没有"全局市场价"。</strong>每个 DEX 池子都是独立的小宇宙。Raydium 的价格涨到 $1 跟 Meteora 这个池子毫无机械联系——除非有套利机器人主动来"对齐"它。在它被发现之前,那批挂在 $0.001、$0.0011、$0.005、$0.01 ... 的 X 代币就一直**安静地坐在那儿等买家**。 | |
| 394 | + | </div> | |
| 395 | + | ||
| 396 | + | <h2>4. 攻击是怎么发生的(图解)</h2> | |
| 397 | + | <p>为了讲清楚机器人具体在干什么,下面把那笔 transaction 拆成 4 个画面:</p> | |
| 398 | + | ||
| 399 | + | <figure> | |
| 400 | + | <svg viewBox="0 0 760 480" xmlns="http://www.w3.org/2000/svg"> | |
| 401 | + | <rect width="760" height="480" fill="url(#bg1)" rx="10"/> | |
| 402 | + | ||
| 403 | + | <!-- Frame 1 --> | |
| 404 | + | <text x="20" y="34" fill="#f7b955" font-size="13" font-weight="700">① 池子初始状态:active bin 在 $0.001,上方塞满便宜 X 代币</text> | |
| 405 | + | <g transform="translate(40, 50)"> | |
| 406 | + | <rect x="0" y="0" width="40" height="60" fill="#f7b955" rx="2"/> | |
| 407 | + | <rect x="48" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 408 | + | <rect x="96" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 409 | + | <rect x="144" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 410 | + | <rect x="192" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 411 | + | <rect x="240" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 412 | + | <rect x="288" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 413 | + | <rect x="336" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 414 | + | <text x="20" y="78" text-anchor="middle" fill="#f7b955" font-size="10">$0.001</text> | |
| 415 | + | <text x="68" y="78" text-anchor="middle" fill="#8b949e" font-size="10">$0.002</text> | |
| 416 | + | <text x="116" y="78" text-anchor="middle" fill="#8b949e" font-size="10">$0.005</text> | |
| 417 | + | <text x="164" y="78" text-anchor="middle" fill="#8b949e" font-size="10">$0.01</text> | |
| 418 | + | <text x="212" y="78" text-anchor="middle" fill="#8b949e" font-size="10">$0.05</text> | |
| 419 | + | <text x="260" y="78" text-anchor="middle" fill="#8b949e" font-size="10">$0.2</text> | |
| 420 | + | <text x="308" y="78" text-anchor="middle" fill="#8b949e" font-size="10">$0.5</text> | |
| 421 | + | <text x="356" y="78" text-anchor="middle" fill="#8b949e" font-size="10">$1.0</text> | |
| 422 | + | <text x="450" y="38" fill="#bc8cff" font-size="11">每个紫格里都有大量代币 X,标价远低于市价</text> | |
| 423 | + | </g> | |
| 424 | + | ||
| 425 | + | <!-- Frame 2 --> | |
| 426 | + | <text x="20" y="148" fill="#f7b955" font-size="13" font-weight="700">② 机器人灌入 USDC,吞掉第一格 bin(按 $0.001 买)</text> | |
| 427 | + | <g transform="translate(40, 164)"> | |
| 428 | + | <rect x="0" y="0" width="40" height="60" fill="#3fb950" opacity="0.5" stroke="#3fb950" stroke-width="2" rx="2"/> | |
| 429 | + | <rect x="48" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 430 | + | <rect x="96" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 431 | + | <rect x="144" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 432 | + | <rect x="192" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 433 | + | <rect x="240" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 434 | + | <rect x="288" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 435 | + | <rect x="336" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 436 | + | <text x="20" y="78" text-anchor="middle" fill="#3fb950" font-size="10" font-weight="700">已吃完</text> | |
| 437 | + | <text x="450" y="38" fill="#3fb950" font-size="11">代币 X 进入机器人钱包,bin #1 变成 USDC</text> | |
| 438 | + | </g> | |
| 439 | + | ||
| 440 | + | <!-- Frame 3 --> | |
| 441 | + | <text x="20" y="262" fill="#f7b955" font-size="13" font-weight="700">③ active bin 推到下一格,继续吃(按 $0.002, $0.005, $0.01... 一路买上去)</text> | |
| 442 | + | <g transform="translate(40, 278)"> | |
| 443 | + | <rect x="0" y="0" width="40" height="60" fill="#3fb950" opacity="0.5" stroke="#3fb950" stroke-width="1" rx="2"/> | |
| 444 | + | <rect x="48" y="0" width="40" height="60" fill="#3fb950" opacity="0.5" stroke="#3fb950" stroke-width="1" rx="2"/> | |
| 445 | + | <rect x="96" y="0" width="40" height="60" fill="#3fb950" opacity="0.5" stroke="#3fb950" stroke-width="1" rx="2"/> | |
| 446 | + | <rect x="144" y="0" width="40" height="60" fill="#3fb950" opacity="0.5" stroke="#3fb950" stroke-width="1" rx="2"/> | |
| 447 | + | <rect x="192" y="0" width="40" height="60" fill="#3fb950" opacity="0.5" stroke="#3fb950" stroke-width="1" rx="2"/> | |
| 448 | + | <rect x="240" y="0" width="40" height="60" fill="#f7b955" rx="2"/> | |
| 449 | + | <rect x="288" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 450 | + | <rect x="336" y="0" width="40" height="60" fill="#bc8cff" opacity="0.85" rx="2"/> | |
| 451 | + | <text x="450" y="38" fill="#f7b955" font-size="11">active bin 一格格往上推,直到逼近真实市价 $1.0</text> | |
| 452 | + | </g> | |
| 453 | + | ||
| 454 | + | <!-- Frame 4 --> | |
| 455 | + | <text x="20" y="378" fill="#f7b955" font-size="13" font-weight="700">④ 同一笔 transaction 里把吃到的 X 全部发到 Raydium 按 $1.0 卖出</text> | |
| 456 | + | <g transform="translate(40, 394)"> | |
| 457 | + | <rect x="0" y="0" width="80" height="60" fill="#161b22" stroke="#bc8cff" stroke-width="1.5" rx="6"/> | |
| 458 | + | <text x="40" y="26" text-anchor="middle" fill="#bc8cff" font-size="11" font-weight="700">Meteora</text> | |
| 459 | + | <text x="40" y="44" text-anchor="middle" fill="#8b949e" font-size="10">买 X · 极便宜</text> | |
| 460 | + | ||
| 461 | + | <text x="160" y="34" fill="#f7b955" font-size="20">→</text> | |
| 462 | + | ||
| 463 | + | <rect x="200" y="0" width="80" height="60" fill="#161b22" stroke="#3fb950" stroke-width="1.5" rx="6"/> | |
| 464 | + | <text x="240" y="26" text-anchor="middle" fill="#3fb950" font-size="11" font-weight="700">Raydium</text> | |
| 465 | + | <text x="240" y="44" text-anchor="middle" fill="#8b949e" font-size="10">卖 X · 市价</text> | |
| 466 | + | ||
| 467 | + | <text x="320" y="34" fill="#f7b955" font-size="20">→</text> | |
| 468 | + | ||
| 469 | + | <rect x="360" y="0" width="120" height="60" fill="#161b22" stroke="#f7b955" stroke-width="1.5" rx="6"/> | |
| 470 | + | <text x="420" y="26" text-anchor="middle" fill="#f7b955" font-size="11" font-weight="700">机器人钱包</text> | |
| 471 | + | <text x="420" y="44" text-anchor="middle" fill="#f7b955" font-size="10" font-weight="700">+ $400K USDC</text> | |
| 472 | + | ||
| 473 | + | <text x="540" y="38" fill="#8b949e" font-size="11">所有指令打包进 1 笔 tx,</text> | |
| 474 | + | <text x="540" y="54" fill="#8b949e" font-size="11">失败回滚 → 永远不会亏</text> | |
| 475 | + | </g> | |
| 476 | + | </svg> | |
| 477 | + | <figcaption>套利的整个动作:低价吃光 → 市价卖出 → 同一笔交易原子完成。</figcaption> | |
| 478 | + | </figure> | |
| 479 | + | ||
| 480 | + | <h3>事件时间线</h3> | |
| 481 | + | <table> | |
| 482 | + | <thead> | |
| 483 | + | <tr><th>时刻</th><th>角色</th><th>动作</th><th>结果</th></tr> | |
| 484 | + | </thead> | |
| 485 | + | <tbody> | |
| 486 | + | <tr><td>T+0s</td><td>鲸鱼</td><td>大额 swap,第一次"打开"这个被遗忘的池子</td><td>active bin 开始移动</td></tr> | |
| 487 | + | <tr><td>T+0.4s</td><td>Bot 1</td><td>监听器触发,发起反向套利</td><td>$0.16 成本 → $403K 盈利</td></tr> | |
| 488 | + | <tr><td>T+1.2s</td><td>Bot 2</td><td>下一个 block 抢落地</td><td>$0.23 成本 → $696K 盈利</td></tr> | |
| 489 | + | <tr><td>T+0~150s</td><td>Bot 3-6</td><td>剩余 bin 慢慢被扫</td><td>累计接近 $3M</td></tr> | |
| 490 | + | <tr><td>T+150s</td><td>—</td><td>active bin 已逼近 Raydium 市价</td><td>套利窗口关闭</td></tr> | |
| 491 | + | </tbody> | |
| 492 | + | </table> | |
| 493 | + | ||
| 494 | + | <h2>5. 技术实现骨架(如果你想做)</h2> | |
| 495 | + | ||
| 496 | + | <ol class="steps"> | |
| 497 | + | <li><strong>扫描全网 Meteora DLMM 池找"stale"标的。</strong>拉所有 DLMM 池的 PDA 账户,用 SDK 读 active bin 价格,跟 Jupiter / Birdeye 拿到的市价对比。差 5-10% 以上的进候选池。这一步可以离线一天扫一次。</li> | |
| 498 | + | <li><strong>实时盯盘候选池。</strong>用 Helius / Triton 的 Geyser gRPC 或 <code>accountSubscribe</code> WebSocket 订阅这些池子账户,状态一变就 push 给你(延迟 50-200ms)。</li> | |
| 499 | + | <li><strong>盈亏模拟。</strong>调用 <code>@meteora-ag/dlmm</code> 模拟从这个池子买 X、再到 Raydium 卖的总收益。扣掉两边手续费、Solana 优先费、Jito tip 后还赚才发交易。</li> | |
| 500 | + | <li><strong>原子 transaction。</strong>把"Meteora 买 + Raydium 卖"两条 swap 指令打到同一笔 tx 里,每个指令都设 <code>min_out_amount</code>,价格滑了整笔回滚。账户多塞不下时用 Address Lookup Table (LUT) 压缩。</li> | |
| 501 | + | <li><strong>抢落地。</strong>普通 RPC 抢不过别人。主流做法:Jito bundle(带 tip)+ Helius Sender / Triton Cascade 同时发出去,哪个先 land 算哪个。tip 大小是 bot 之间最常调的旋钮。</li> | |
| 502 | + | </ol> | |
| 503 | + | ||
| 504 | + | <div class="callout"> | |
| 505 | + | <strong>提示:</strong>这种机会真正的瓶颈不在策略本身,而在<strong>抢速度</strong>和<strong>风险控制</strong>。一旦池子被发现,每个 block 都有 5-20 个机器人在抢同一笔利润。原子 + Jito + 充足的 priority fee 是最低门槛。 | |
| 506 | + | </div> | |
| 507 | + | ||
| 508 | + | <h2>6. 一句话总结</h2> | |
| 509 | + | <div class="quote"> | |
| 510 | + | <strong>Bin 不会自动更新价格</strong>,DLMM 池子只在被交易时才移动 active bin。LP 创建池子后 10 个月不维护,外部市场暴涨 1000 倍——池子里那些"高于原始 active bin 但远低于市场价"的 bins 就成了静悄悄挂着的「便宜代币堆」,等着第一个发现它的套利机器人一口气全吃光。 | |
| 511 | + | </div> | |
| 512 | + | ||
| 513 | + | <p>这就是 stale pool / stale LP arbitrage。错不在 Meteora 协议,而在 LP 自己。这种漏洞跟 Uniswap v3 在以太坊上遇到的"untracked LP"问题完全一样,只是 Solana 上池子多、LP 散、被发现的速度极快——这次连 1 秒都没撑住。</p> | |
| 514 | + | ||
| 515 | + | <footer> | |
| 516 | + | <p>资料来源: | |
| 517 | + | <a href="https://x.com/anshu_code/status/2051888998671581324" target="_blank">@anshu_code 主推</a> · | |
| 518 | + | <a href="https://x.com/anshu_code/status/2051392982327468463" target="_blank">前一条引用</a> · | |
| 519 | + | Meteora DLMM 文档 · Jupiter / Helius 公开技术资料 | |
| 520 | + | </p> | |
| 521 | + | <p>本文为根据公开链上数据和推文内容做的技术拆解,不构成投资建议;过期池套利涉及极高的速度竞争和资金风险,复刻前请自行评估。</p> | |
| 522 | + | </footer> | |
| 523 | + | ||
| 524 | + | </div> | |
| 525 | + | </body> | |
| 526 | + | </html> | |