[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-deep-evm-16-beondeulinggwa-chungdol-haegyeol-teulaenjaeksyeon-paeking":3},{"article":4,"author":59},{"id":5,"category_id":6,"title":7,"slug":8,"excerpt":9,"content_md":10,"content_html":11,"locale":12,"author_id":13,"published":14,"published_at":15,"meta_title":16,"meta_description":17,"focus_keyword":18,"og_image":19,"canonical_url":19,"robots_meta":20,"created_at":15,"updated_at":15,"tags":21,"category_name":39,"related_articles":40},"d5000000-0000-0000-0000-000000000116","a0000000-0000-0000-0000-000000000056","Deep EVM #16: 번들링과 충돌 해결 — 수익성 있는 트랜잭션 패킹","deep-evm-16-beondeulinggwa-chungdol-haegyeol-teulaenjaeksyeon-paeking","여러 차익거래 트랜잭션을 충돌 없는 번들로 패킹합니다. 비트마스크 충돌 감지, 계층화 배칭 전략을 사용하고 Flashbots, MEV-Share, 직접 빌더 API를 통해 제출합니다.","## 번들링이 중요한 이유\n\n단일 차익거래 트랜잭션은 간단합니다: 시뮬레이션하고, 제출하고, 이익을 얻습니다. 그러나 프로덕션 MEV 봇은 블록당 수십 개의 수익성 있는 사이클을 찾습니다. 각 사이클은 하나의 트랜잭션을 생산합니다. 개별적으로 제출하면 낭비적이고 위험합니다:\n\n1. **가스 오버헤드:** 각 트랜잭션은 21,000 기본 가스 비용을 지불합니다. N개의 스왑을 하나의 트랜잭션으로 번들링하면 기본 비용을 한 번만 지불합니다.\n2. **원자성:** 트랜잭션 A와 B가 같은 풀을 건드리면, A의 실행이 B가 의존하는 상태를 변경합니다. 별도로 제출하면 B가 되돌릴 수 있습니다. 함께 번들링하면 올바르게 순서를 정할 수 있습니다.\n3. **빌더 선호:** 블록 빌더는 더 많은 총 MEV를 지불하는 더 큰 번들을 선호합니다 — 번들은 다른 서처의 번들과 포함을 위해 경쟁합니다.\n\n## 충돌 감지: 비트마스크 접근법\n\n두 차익거래 사이클이 풀을 공유하면 충돌합니다. 사이클 A가 풀 X를 통해 스왑하면 풀 X의 준비금이 변경됩니다. 풀 X도 사용하는 사이클 B는 이전 준비금에 대해 시뮬레이션되었으므로 다른(아마도 더 나쁜) 결과를 생산합니다.\n\n비트마스크를 사용하여 충돌을 감지합니다. 각 풀에 인덱스(0 ~ N-1)를 할당합니다. 각 사이클은 어떤 풀을 건드리는지를 나타내는 비트마스크를 받습니다:\n\n```rust\nuse bitvec::prelude::*;\n\n#[derive(Clone)]\npub struct CycleWithMask {\n    pub cycle: ProfitableCycle,\n    pub pool_mask: BitVec,\n}\n\npub fn build_pool_masks(\n    cycles: &[ProfitableCycle],\n    pool_index: &HashMap\u003CAddress, usize>,\n    total_pools: usize,\n) -> Vec\u003CCycleWithMask> {\n    cycles\n        .iter()\n        .map(|c| {\n            let mut mask = bitvec![0; total_pools];\n            for pool in &c.cycle.pools {\n                if let Some(&idx) = pool_index.get(&pool.address) {\n                    mask.set(idx, true);\n                }\n            }\n            CycleWithMask {\n                cycle: c.clone(),\n                pool_mask: mask,\n            }\n        })\n        .collect()\n}\n```\n\n두 사이클의 비트마스크에 공통 비트가 있으면 충돌합니다:\n\n```rust\nfn conflicts(a: &BitVec, b: &BitVec) -> bool {\n    a.iter()\n        .zip(b.iter())\n        .any(|(x, y)| *x && *y)\n}\n```\n\n비교당 O(N\u002F64)입니다 — 각 64비트 워드가 단일 AND 명령으로 검사됩니다. 80,000개 풀의 경우 비트마스크는 10KB입니다. 두 마스크를 비교하는 데 약 150 AND 연산이 걸립니다. 풀 주소 목록을 순회하는 것보다 몇 배나 빠릅니다.\n\n## 그리디 번들 패킹\n\n수익성 있는 사이클 집합이 주어지면, 최대 이익 충돌 없는 부분 집합을 찾습니다. 이것은 충돌 그래프에서의 가중 최대 독립 집합 문제입니다 — 일반적으로 NP-난해합니다. 그리디 근사를 사용합니다:\n\n```rust\npub fn pack_bundle(\n    candidates: &mut Vec\u003CCycleWithMask>,\n) -> Vec\u003CCycleWithMask> {\n    \u002F\u002F 이익 내림차순 정렬\n    candidates.sort_by(|a, b| {\n        b.cycle.expected_profit.cmp(&a.cycle.expected_profit)\n    });\n\n    let total_pools = candidates\n        .first()\n        .map(|c| c.pool_mask.len())\n        .unwrap_or(0);\n\n    let mut bundle: Vec\u003CCycleWithMask> = Vec::new();\n    let mut used_pools = bitvec![0; total_pools];\n\n    for candidate in candidates.iter() {\n        \u002F\u002F 이미 선택된 사이클과 충돌하는지 확인\n        if conflicts(&candidate.pool_mask, &used_pools) {\n            continue;\n        }\n\n        \u002F\u002F 충돌 없음 — 번들에 추가\n        used_pools |= &candidate.pool_mask;\n        bundle.push(candidate.clone());\n    }\n\n    bundle\n}\n```\n\n그리디 접근법은 가장 수익성 높은 사이클을 먼저 선택하고, 해당 풀을 사용됨으로 표시한 다음, 다음으로 수익성 높은 비충돌 사이클을 선택하는 식으로 진행합니다. 전역 최적은 아니지만 O(N * P\u002F64) 시간에 실행됩니다. 실무에서 그리디 해는 최적의 5-10% 이내입니다.\n\n## 패킹 후 재시뮬레이션\n\n번들을 선택한 후, 순서대로 전체 시퀀스를 재시뮬레이션합니다. 첫 번째 사이클은 현재 상태에 대해 실행됩니다. 두 번째 사이클은 첫 번째 사이클 실행 *후*의 상태에 대해 시뮬레이션되어야 합니다:\n\n```rust\npub fn validate_bundle(\n    simulator: &mut Simulator,\n    bundle: &[CycleWithMask],\n) -> Vec\u003CValidatedTx> {\n    let mut validated = Vec::new();\n\n    let snapshot = simulator.snapshot();\n\n    for entry in bundle {\n        let calldata = build_execution_calldata(\n            &entry.cycle,\n            entry.cycle.optimal_input,\n        );\n\n        let result = simulator.simulate_swap(\n            bot_address(),\n            bot_contract(),\n            calldata.clone(),\n            U256::ZERO,\n        );\n\n        match result {\n            Ok(sim) if sim.success => {\n                validated.push(ValidatedTx {\n                    calldata,\n                    gas_used: sim.gas_used,\n                    expected_profit: entry.cycle.expected_profit,\n                });\n            }\n            _ => {\n                tracing::debug!(\n                    \"사이클 {:?}이 번들 검증 중 실패\",\n                    entry.cycle.cycle.id\n                );\n            }\n        }\n    }\n\n    simulator.restore(snapshot);\n\n    validated\n}\n```\n\n개별적으로 수익성이 있던 사이클이 번들 검증 중 실패할 수 있습니다. 번들의 이전 사이클이 의존하는 풀 상태를 변경했기 때문입니다.\n\n## 번들 제출\n\n### Flashbots 번들\n\n표준 제출 경로입니다. 번들은 Flashbots 호환 빌더에 제출되는 서명된 트랜잭션의 정렬된 목록입니다:\n\n```rust\nuse ethers_flashbots::{FlashbotsMiddleware, BundleRequest};\n\npub async fn submit_flashbots_bundle(\n    client: &FlashbotsMiddleware\u003CProvider\u003CHttp>, LocalWallet>,\n    transactions: Vec\u003CBytes>,\n    target_block: u64,\n) -> Result\u003CBundleHash> {\n    let mut bundle = BundleRequest::new();\n\n    for tx in transactions {\n        bundle = bundle.push_transaction(tx);\n    }\n\n    bundle = bundle\n        .set_block(target_block)\n        .set_simulation_block(target_block - 1)\n        .set_simulation_timestamp(0);\n\n    let result = client\n        .send_bundle(&bundle)\n        .await?;\n\n    Ok(result.bundle_hash)\n}\n```\n\nFlashbots 번들은 핵심 속성을 가집니다: **전부 또는 전무 실행**. 번들의 모든 트랜잭션이 성공하거나, 아무것도 포함되지 않습니다. 첫 번째 스왑은 성공하지만 두 번째가 되돌리는 부분 실행을 방지하여, 원치 않는 중간 토큰을 남기는 것을 막습니다.\n\n### MEV-Share\n\nMEV-Share는 MEV를 사용자에게 재분배하는 Flashbots의 프로토콜입니다. 사용자가 Flashbots Protect를 통해 트랜잭션을 제출하면, 서처가 백런에 입찰할 수 있습니다. 사용자는 MEV의 일부를 받습니다.\n\n### 직접 빌더 API\n\n일부 빌더는 Flashbots를 우회하여 번들을 직접 수락합니다:\n\n- **Titan Builder:** `https:\u002F\u002Frpc.titanbuilder.xyz`\n- **BeaverBuild:** `https:\u002F\u002Frpc.beaverbuild.org`\n- **Rsync Builder:** `https:\u002F\u002Frsync-builder.xyz`\n\n```rust\npub async fn submit_to_builders(\n    bundles: &[SignedBundle],\n    builders: &[BuilderEndpoint],\n) {\n    \u002F\u002F 모든 빌더에 동시 제출\n    let futures: Vec\u003C_> = builders\n        .iter()\n        .map(|builder| {\n            submit_bundle_to_builder(builder, bundles)\n        })\n        .collect();\n\n    let results = futures::future::join_all(futures).await;\n\n    for (builder, result) in builders.iter().zip(results) {\n        match result {\n            Ok(_) => tracing::info!(\"{}에 제출됨\", builder.name),\n            Err(e) => tracing::warn!(\"{} 실패: {}\", builder.name, e),\n        }\n    }\n}\n```\n\n항상 여러 빌더에 제출하세요. 블록 포함을 위해 경쟁하고 있습니다 — 더 많은 빌더가 번들을 볼수록 포함 확률이 높습니다.\n\n## Coinbase 전송: 빌더에 지불\n\nMEV 번들은 가스 가격으로 포함 비용을 지불하지 않습니다. 대신 번들의 마지막 트랜잭션이 `block.coinbase`(빌더의 수수료 수신자)에 직접 ETH 전송을 보냅니다:\n\n```huff\n#define macro PAY_COINBASE() = takes(1) returns(0) {\n    \u002F\u002F takes: [payment_amount]\n    0x00 0x00 0x00 0x00     \u002F\u002F retSize, retOff, argSize, argOff\n    swap4                   \u002F\u002F [amount, 0, 0, 0, 0]\n    coinbase                \u002F\u002F [coinbase, amount, 0, 0, 0, 0]\n    gas call                \u002F\u002F [success]\n    pop\n}\n```\n\n지불 금액은 일반적으로 예상 이익의 90-99%입니다. 서처는 1-10%를 마진으로 유지합니다. 더 높은 지불은 포함 확률을 높이지만 이익을 줄입니다. 이것은 끊임없는 게임 이론적 균형입니다.\n\n## 엔드투엔드 흐름\n\n모든 것을 종합하면, 프로덕션 MEV 봇의 블록당 흐름입니다:\n\n```\n1. 새 블록 도착 (t=0)\n2. 이벤트에서 풀 준비금 업데이트 (t=0-500ms)\n3. 사이클 인덱스를 통해 영향 받은 사이클 식별 (t=500ms-1s)\n4. 영향 받은 사이클 + 순환 배치 시뮬레이션 (t=1-4s)\n   - 최적 입력 이진 검색\n   - 마감 시간 인식: 가장 높은 이익 먼저\n5. 비트마스크 구축, 충돌 없는 번들 패킹 (t=4-5s)\n6. 순서대로 번들 재시뮬레이션 (t=5-6s)\n7. 트랜잭션 서명, coinbase 지불 계산 (t=6-7s)\n8. Flashbots + 직접 빌더에 제출 (t=7-8s)\n9. 포함 대기 (t=8-12s)\n10. 결과 기록, 이익 추적 업데이트 (t=12s)\n```\n\n전체 파이프라인이 12초 블록 시간 내에 실행됩니다. 모든 밀리초가 중요합니다.\n\n## 모니터링과 관찰 가능성\n\n프로덕션 MEV 봇에는 포괄적인 모니터링이 필요합니다:\n\n```rust\n#[derive(Default)]\npub struct BlockMetrics {\n    pub cycles_evaluated: u64,\n    pub cycles_profitable: u64,\n    pub bundles_submitted: u64,\n    pub bundles_included: u64,\n    pub total_profit_wei: U256,\n    pub total_gas_cost_wei: U256,\n    pub simulation_time_ms: u64,\n    pub deadline_expired: bool,\n}\n```\n\n포함률(bundles_included \u002F bundles_submitted), 포함된 번들당 평균 이익, 마감 시간 미스를 추적합니다. 건강한 봇은 20% 이상의 포함률과 5% 미만의 마감 시간 미스를 가집니다.\n\n## 요약\n\n번들링은 개별 차익거래 트랜잭션을 블록당 이익을 최대화하는 최적화된 충돌 없는 패키지로 변환합니다. 비트마스크 충돌 감지는 마이크로초 내에 실행됩니다. 그리디 패킹은 거의 최적의 번들을 찾습니다. 재시뮬레이션은 현실적인 상태에 대해 번들을 검증합니다. 다중 빌더 제출은 포함 확률을 최대화합니다. 이것으로 Deep EVM 시리즈를 마무리합니다 — Huff의 원시 옵코드부터 프로덕션 MEV 인프라까지. 스택: 온체인 실행을 위한 Huff 컨트랙트, 오프체인 시뮬레이션 및 번들링을 위한 Rust, 공정한 블록 포함을 위한 Flashbots 생태계.","\u003Ch2 id=\"\">번들링이 중요한 이유\u003C\u002Fh2>\n\u003Cp>단일 차익거래 트랜잭션은 간단합니다: 시뮬레이션하고, 제출하고, 이익을 얻습니다. 그러나 프로덕션 MEV 봇은 블록당 수십 개의 수익성 있는 사이클을 찾습니다. 각 사이클은 하나의 트랜잭션을 생산합니다. 개별적으로 제출하면 낭비적이고 위험합니다:\u003C\u002Fp>\n\u003Col>\n\u003Cli>\u003Cstrong>가스 오버헤드:\u003C\u002Fstrong> 각 트랜잭션은 21,000 기본 가스 비용을 지불합니다. N개의 스왑을 하나의 트랜잭션으로 번들링하면 기본 비용을 한 번만 지불합니다.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>원자성:\u003C\u002Fstrong> 트랜잭션 A와 B가 같은 풀을 건드리면, A의 실행이 B가 의존하는 상태를 변경합니다. 별도로 제출하면 B가 되돌릴 수 있습니다. 함께 번들링하면 올바르게 순서를 정할 수 있습니다.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>빌더 선호:\u003C\u002Fstrong> 블록 빌더는 더 많은 총 MEV를 지불하는 더 큰 번들을 선호합니다 — 번들은 다른 서처의 번들과 포함을 위해 경쟁합니다.\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch2 id=\"\">충돌 감지: 비트마스크 접근법\u003C\u002Fh2>\n\u003Cp>두 차익거래 사이클이 풀을 공유하면 충돌합니다. 사이클 A가 풀 X를 통해 스왑하면 풀 X의 준비금이 변경됩니다. 풀 X도 사용하는 사이클 B는 이전 준비금에 대해 시뮬레이션되었으므로 다른(아마도 더 나쁜) 결과를 생산합니다.\u003C\u002Fp>\n\u003Cp>비트마스크를 사용하여 충돌을 감지합니다. 각 풀에 인덱스(0 ~ N-1)를 할당합니다. 각 사이클은 어떤 풀을 건드리는지를 나타내는 비트마스크를 받습니다:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-rust\">use bitvec::prelude::*;\n\n#[derive(Clone)]\npub struct CycleWithMask {\n    pub cycle: ProfitableCycle,\n    pub pool_mask: BitVec,\n}\n\npub fn build_pool_masks(\n    cycles: &amp;[ProfitableCycle],\n    pool_index: &amp;HashMap&lt;Address, usize&gt;,\n    total_pools: usize,\n) -&gt; Vec&lt;CycleWithMask&gt; {\n    cycles\n        .iter()\n        .map(|c| {\n            let mut mask = bitvec![0; total_pools];\n            for pool in &amp;c.cycle.pools {\n                if let Some(&amp;idx) = pool_index.get(&amp;pool.address) {\n                    mask.set(idx, true);\n                }\n            }\n            CycleWithMask {\n                cycle: c.clone(),\n                pool_mask: mask,\n            }\n        })\n        .collect()\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>두 사이클의 비트마스크에 공통 비트가 있으면 충돌합니다:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-rust\">fn conflicts(a: &amp;BitVec, b: &amp;BitVec) -&gt; bool {\n    a.iter()\n        .zip(b.iter())\n        .any(|(x, y)| *x &amp;&amp; *y)\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>비교당 O(N\u002F64)입니다 — 각 64비트 워드가 단일 AND 명령으로 검사됩니다. 80,000개 풀의 경우 비트마스크는 10KB입니다. 두 마스크를 비교하는 데 약 150 AND 연산이 걸립니다. 풀 주소 목록을 순회하는 것보다 몇 배나 빠릅니다.\u003C\u002Fp>\n\u003Ch2 id=\"\">그리디 번들 패킹\u003C\u002Fh2>\n\u003Cp>수익성 있는 사이클 집합이 주어지면, 최대 이익 충돌 없는 부분 집합을 찾습니다. 이것은 충돌 그래프에서의 가중 최대 독립 집합 문제입니다 — 일반적으로 NP-난해합니다. 그리디 근사를 사용합니다:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-rust\">pub fn pack_bundle(\n    candidates: &amp;mut Vec&lt;CycleWithMask&gt;,\n) -&gt; Vec&lt;CycleWithMask&gt; {\n    \u002F\u002F 이익 내림차순 정렬\n    candidates.sort_by(|a, b| {\n        b.cycle.expected_profit.cmp(&amp;a.cycle.expected_profit)\n    });\n\n    let total_pools = candidates\n        .first()\n        .map(|c| c.pool_mask.len())\n        .unwrap_or(0);\n\n    let mut bundle: Vec&lt;CycleWithMask&gt; = Vec::new();\n    let mut used_pools = bitvec![0; total_pools];\n\n    for candidate in candidates.iter() {\n        \u002F\u002F 이미 선택된 사이클과 충돌하는지 확인\n        if conflicts(&amp;candidate.pool_mask, &amp;used_pools) {\n            continue;\n        }\n\n        \u002F\u002F 충돌 없음 — 번들에 추가\n        used_pools |= &amp;candidate.pool_mask;\n        bundle.push(candidate.clone());\n    }\n\n    bundle\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>그리디 접근법은 가장 수익성 높은 사이클을 먼저 선택하고, 해당 풀을 사용됨으로 표시한 다음, 다음으로 수익성 높은 비충돌 사이클을 선택하는 식으로 진행합니다. 전역 최적은 아니지만 O(N * P\u002F64) 시간에 실행됩니다. 실무에서 그리디 해는 최적의 5-10% 이내입니다.\u003C\u002Fp>\n\u003Ch2 id=\"\">패킹 후 재시뮬레이션\u003C\u002Fh2>\n\u003Cp>번들을 선택한 후, 순서대로 전체 시퀀스를 재시뮬레이션합니다. 첫 번째 사이클은 현재 상태에 대해 실행됩니다. 두 번째 사이클은 첫 번째 사이클 실행 \u003Cem>후\u003C\u002Fem>의 상태에 대해 시뮬레이션되어야 합니다:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-rust\">pub fn validate_bundle(\n    simulator: &amp;mut Simulator,\n    bundle: &amp;[CycleWithMask],\n) -&gt; Vec&lt;ValidatedTx&gt; {\n    let mut validated = Vec::new();\n\n    let snapshot = simulator.snapshot();\n\n    for entry in bundle {\n        let calldata = build_execution_calldata(\n            &amp;entry.cycle,\n            entry.cycle.optimal_input,\n        );\n\n        let result = simulator.simulate_swap(\n            bot_address(),\n            bot_contract(),\n            calldata.clone(),\n            U256::ZERO,\n        );\n\n        match result {\n            Ok(sim) if sim.success =&gt; {\n                validated.push(ValidatedTx {\n                    calldata,\n                    gas_used: sim.gas_used,\n                    expected_profit: entry.cycle.expected_profit,\n                });\n            }\n            _ =&gt; {\n                tracing::debug!(\n                    \"사이클 {:?}이 번들 검증 중 실패\",\n                    entry.cycle.cycle.id\n                );\n            }\n        }\n    }\n\n    simulator.restore(snapshot);\n\n    validated\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>개별적으로 수익성이 있던 사이클이 번들 검증 중 실패할 수 있습니다. 번들의 이전 사이클이 의존하는 풀 상태를 변경했기 때문입니다.\u003C\u002Fp>\n\u003Ch2 id=\"\">번들 제출\u003C\u002Fh2>\n\u003Ch3>Flashbots 번들\u003C\u002Fh3>\n\u003Cp>표준 제출 경로입니다. 번들은 Flashbots 호환 빌더에 제출되는 서명된 트랜잭션의 정렬된 목록입니다:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-rust\">use ethers_flashbots::{FlashbotsMiddleware, BundleRequest};\n\npub async fn submit_flashbots_bundle(\n    client: &amp;FlashbotsMiddleware&lt;Provider&lt;Http&gt;, LocalWallet&gt;,\n    transactions: Vec&lt;Bytes&gt;,\n    target_block: u64,\n) -&gt; Result&lt;BundleHash&gt; {\n    let mut bundle = BundleRequest::new();\n\n    for tx in transactions {\n        bundle = bundle.push_transaction(tx);\n    }\n\n    bundle = bundle\n        .set_block(target_block)\n        .set_simulation_block(target_block - 1)\n        .set_simulation_timestamp(0);\n\n    let result = client\n        .send_bundle(&amp;bundle)\n        .await?;\n\n    Ok(result.bundle_hash)\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Flashbots 번들은 핵심 속성을 가집니다: \u003Cstrong>전부 또는 전무 실행\u003C\u002Fstrong>. 번들의 모든 트랜잭션이 성공하거나, 아무것도 포함되지 않습니다. 첫 번째 스왑은 성공하지만 두 번째가 되돌리는 부분 실행을 방지하여, 원치 않는 중간 토큰을 남기는 것을 막습니다.\u003C\u002Fp>\n\u003Ch3>MEV-Share\u003C\u002Fh3>\n\u003Cp>MEV-Share는 MEV를 사용자에게 재분배하는 Flashbots의 프로토콜입니다. 사용자가 Flashbots Protect를 통해 트랜잭션을 제출하면, 서처가 백런에 입찰할 수 있습니다. 사용자는 MEV의 일부를 받습니다.\u003C\u002Fp>\n\u003Ch3>직접 빌더 API\u003C\u002Fh3>\n\u003Cp>일부 빌더는 Flashbots를 우회하여 번들을 직접 수락합니다:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>Titan Builder:\u003C\u002Fstrong> \u003Ccode>https:\u002F\u002Frpc.titanbuilder.xyz\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>\u003Cstrong>BeaverBuild:\u003C\u002Fstrong> \u003Ccode>https:\u002F\u002Frpc.beaverbuild.org\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Rsync Builder:\u003C\u002Fstrong> \u003Ccode>https:\u002F\u002Frsync-builder.xyz\u003C\u002Fcode>\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cpre>\u003Ccode class=\"language-rust\">pub async fn submit_to_builders(\n    bundles: &amp;[SignedBundle],\n    builders: &amp;[BuilderEndpoint],\n) {\n    \u002F\u002F 모든 빌더에 동시 제출\n    let futures: Vec&lt;_&gt; = builders\n        .iter()\n        .map(|builder| {\n            submit_bundle_to_builder(builder, bundles)\n        })\n        .collect();\n\n    let results = futures::future::join_all(futures).await;\n\n    for (builder, result) in builders.iter().zip(results) {\n        match result {\n            Ok(_) =&gt; tracing::info!(\"{}에 제출됨\", builder.name),\n            Err(e) =&gt; tracing::warn!(\"{} 실패: {}\", builder.name, e),\n        }\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>항상 여러 빌더에 제출하세요. 블록 포함을 위해 경쟁하고 있습니다 — 더 많은 빌더가 번들을 볼수록 포함 확률이 높습니다.\u003C\u002Fp>\n\u003Ch2 id=\"coinbase\">Coinbase 전송: 빌더에 지불\u003C\u002Fh2>\n\u003Cp>MEV 번들은 가스 가격으로 포함 비용을 지불하지 않습니다. 대신 번들의 마지막 트랜잭션이 \u003Ccode>block.coinbase\u003C\u002Fcode>(빌더의 수수료 수신자)에 직접 ETH 전송을 보냅니다:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-huff\">#define macro PAY_COINBASE() = takes(1) returns(0) {\n    \u002F\u002F takes: [payment_amount]\n    0x00 0x00 0x00 0x00     \u002F\u002F retSize, retOff, argSize, argOff\n    swap4                   \u002F\u002F [amount, 0, 0, 0, 0]\n    coinbase                \u002F\u002F [coinbase, amount, 0, 0, 0, 0]\n    gas call                \u002F\u002F [success]\n    pop\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>지불 금액은 일반적으로 예상 이익의 90-99%입니다. 서처는 1-10%를 마진으로 유지합니다. 더 높은 지불은 포함 확률을 높이지만 이익을 줄입니다. 이것은 끊임없는 게임 이론적 균형입니다.\u003C\u002Fp>\n\u003Ch2 id=\"\">엔드투엔드 흐름\u003C\u002Fh2>\n\u003Cp>모든 것을 종합하면, 프로덕션 MEV 봇의 블록당 흐름입니다:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>1. 새 블록 도착 (t=0)\n2. 이벤트에서 풀 준비금 업데이트 (t=0-500ms)\n3. 사이클 인덱스를 통해 영향 받은 사이클 식별 (t=500ms-1s)\n4. 영향 받은 사이클 + 순환 배치 시뮬레이션 (t=1-4s)\n   - 최적 입력 이진 검색\n   - 마감 시간 인식: 가장 높은 이익 먼저\n5. 비트마스크 구축, 충돌 없는 번들 패킹 (t=4-5s)\n6. 순서대로 번들 재시뮬레이션 (t=5-6s)\n7. 트랜잭션 서명, coinbase 지불 계산 (t=6-7s)\n8. Flashbots + 직접 빌더에 제출 (t=7-8s)\n9. 포함 대기 (t=8-12s)\n10. 결과 기록, 이익 추적 업데이트 (t=12s)\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>전체 파이프라인이 12초 블록 시간 내에 실행됩니다. 모든 밀리초가 중요합니다.\u003C\u002Fp>\n\u003Ch2 id=\"\">모니터링과 관찰 가능성\u003C\u002Fh2>\n\u003Cp>프로덕션 MEV 봇에는 포괄적인 모니터링이 필요합니다:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-rust\">#[derive(Default)]\npub struct BlockMetrics {\n    pub cycles_evaluated: u64,\n    pub cycles_profitable: u64,\n    pub bundles_submitted: u64,\n    pub bundles_included: u64,\n    pub total_profit_wei: U256,\n    pub total_gas_cost_wei: U256,\n    pub simulation_time_ms: u64,\n    pub deadline_expired: bool,\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>포함률(bundles_included \u002F bundles_submitted), 포함된 번들당 평균 이익, 마감 시간 미스를 추적합니다. 건강한 봇은 20% 이상의 포함률과 5% 미만의 마감 시간 미스를 가집니다.\u003C\u002Fp>\n\u003Ch2 id=\"\">요약\u003C\u002Fh2>\n\u003Cp>번들링은 개별 차익거래 트랜잭션을 블록당 이익을 최대화하는 최적화된 충돌 없는 패키지로 변환합니다. 비트마스크 충돌 감지는 마이크로초 내에 실행됩니다. 그리디 패킹은 거의 최적의 번들을 찾습니다. 재시뮬레이션은 현실적인 상태에 대해 번들을 검증합니다. 다중 빌더 제출은 포함 확률을 최대화합니다. 이것으로 Deep EVM 시리즈를 마무리합니다 — Huff의 원시 옵코드부터 프로덕션 MEV 인프라까지. 스택: 온체인 실행을 위한 Huff 컨트랙트, 오프체인 시뮬레이션 및 번들링을 위한 Rust, 공정한 블록 포함을 위한 Flashbots 생태계.\u003C\u002Fp>\n","ko","b0000000-0000-0000-0000-000000000001",true,"2026-03-28T10:44:28.061959Z","Deep EVM #16: 번들링과 충돌 해결 — MEV 트랜잭션 패킹","비트마스크 감지, 그리디 패킹, Flashbots 및 직접 빌더 API를 통한 제출을 사용하여 여러 MEV 차익거래 트랜잭션을 충돌 없는 번들로 패킹.","mev 번들링 충돌 해결",null,"index, follow",[22,27,31,35],{"id":23,"name":24,"slug":25,"created_at":26},"c0000000-0000-0000-0000-000000000019","MEV","mev","2026-03-28T10:44:21.513630Z",{"id":28,"name":29,"slug":30,"created_at":26},"c0000000-0000-0000-0000-000000000001","Rust","rust",{"id":32,"name":33,"slug":34,"created_at":26},"c0000000-0000-0000-0000-000000000013","Security","security",{"id":36,"name":37,"slug":38,"created_at":26},"c0000000-0000-0000-0000-000000000009","Web3","web3","엔지니어링",[41,47,53],{"id":42,"title":43,"slug":44,"excerpt":45,"locale":12,"category_name":39,"published_at":46},"d0000000-0000-0000-0000-000000000674","2026년, Bali가 동남아시아의 임팩트 테크 허브가 되고 있는 이유","bali-2026-dongnamasia-impaekteu-tekeu-heobeu-iyu","Bali는 동남아시아 스타트업 생태계에서 16위를 차지하고 있습니다. Web3 빌더, AI 지속가능성 스타트업, 에코 여행 테크 기업이 집중되면서, 이 섬은 지역 임팩트 테크의 수도로 자리매김하고 있습니다.","2026-03-28T10:44:49.294484Z",{"id":48,"title":49,"slug":50,"excerpt":51,"locale":12,"category_name":39,"published_at":52},"d0000000-0000-0000-0000-000000000673","ASEAN 데이터 보호 패치워크: 개발자를 위한 컴플라이언스 체크리스트","asean-deiteo-boho-paechiwokeu-gaebaljaleul-wihan-keompeullaieonseuchekeuriseuteu","7개 ASEAN 국가가 포괄적인 데이터 보호법을 시행하고 있으며, 각각 다른 동의 모델, 현지화 요건, 벌칙 구조를 가지고 있습니다. 다중 국가 애플리케이션을 구축하는 개발자를 위한 실용적인 컴플라이언스 체크리스트입니다.","2026-03-28T10:44:49.286400Z",{"id":54,"title":55,"slug":56,"excerpt":57,"locale":12,"category_name":39,"published_at":58},"d0000000-0000-0000-0000-000000000672","Indonesia 290억 달러 디지털 전환: 소프트웨어 기업을 위한 기회","indonesia-290eok-dallleo-dijiteol-jeonhwan-sopeuteuweo-gieopui-gihoe","Indonesia IT 서비스 시장은 2026년 290.3억 달러에 달할 것으로 예상되며, 이는 2025년 243.7억 달러에서 증가한 수치입니다. 클라우드 인프라, AI, 전자상거래, 데이터센터가 동남아시아에서 가장 빠른 성장을 주도하고 있습니다.","2026-03-28T10:44:49.265609Z",{"id":13,"name":60,"slug":61,"bio":62,"photo_url":19,"linkedin":19,"role":63,"created_at":64,"updated_at":64},"Open Soft Team","open-soft-team","The engineering team at Open Soft, building premium software solutions from Bali, Indonesia.","Engineering Team","2026-03-28T08:31:22.226811Z"]