[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-debugging-bytecode-evm-trace-stack-dump-cast-run":3},{"article":4,"author":54},{"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":7,"meta_description":16,"focus_keyword":17,"og_image":18,"canonical_url":18,"robots_meta":19,"created_at":15,"updated_at":15,"tags":20,"category_name":34,"related_articles":35},"d2000000-0000-0000-0000-000000000118","a0000000-0000-0000-0000-000000000022","Debugging Bytecode EVM — Trace, Stack Dump, dan cast run","debugging-bytecode-evm-trace-stack-dump-cast-run","Teknik debugging bytecode EVM: membaca execution trace, menganalisis stack dump, menggunakan cast run untuk replay transaksi, dan mendekode revert reason.","## Tantangan Debugging EVM\n\nDebugging kontrak EVM — terutama yang ditulis di Huff atau Yul — berbeda fundamental dari debugging software tradisional. Tidak ada breakpoint, tidak ada variabel watch, tidak ada stack trace yang bermakna. Yang Anda miliki adalah:\n\n- Urutan opcode yang dieksekusi\n- State stack di setiap langkah\n- Perubahan memory dan storage\n- Gas yang dikonsumsi per opcode\n\nArtikel ini mengajarkan cara menggunakan alat-alat ini secara efektif.\n\n## Foundry Trace dengan Verbosity Tinggi\n\nFoundry menyediakan empat level verbosity:\n\n```bash\nforge test -v    # Level 1: pass\u002Ffail\nforge test -vv   # Level 2: + log output\nforge test -vvv  # Level 3: + execution trace\nforge test -vvvv # Level 4: + opcode trace\n```\n\nLevel 4 (`-vvvv`) menampilkan setiap opcode yang dieksekusi:\n\n```\n[CALL] 0x1234...::swap(uint256) [gas: 80000]\n  ├─ [SLOAD] slot 0x00 → 0x...reserve0\n  ├─ [SLOAD] slot 0x01 → 0x...reserve1\n  ├─ [MUL] 997 * amountIn → amountWithFee\n  ├─ [CALL] 0xtoken::transfer(pair, amount)\n  │   ├─ [SLOAD] balances[sender] → balance\n  │   ├─ [SUB] balance - amount → newBalance\n  │   ├─ [SSTORE] balances[sender] = newBalance\n  │   └─ [RETURN] true\n  └─ [RETURN] success\n```\n\n## cast run: Replay Transaksi\n\n`cast run` memungkinkan Anda me-replay transaksi mainnet apa pun dengan trace lengkap:\n\n```bash\n# Replay transaksi dengan trace\ncast run 0x1234...txhash --rpc-url $ETH_RPC -vvvv\n\n# Replay pada block tertentu\ncast run 0x1234...txhash --rpc-url $ETH_RPC --block 18000000\n```\n\nIni sangat berguna untuk:\n- Menganalisis mengapa transaksi MEV gagal\n- Mempelajari strategi pencari lain\n- Memahami interaksi kontrak yang kompleks\n\n## Membaca Execution Trace\n\nExecution trace menampilkan hierarki panggilan:\n\n```\nTransaction: 0xabc...\nFrom: 0x123...\nTo: 0x456...\nValue: 0\nGas: 150000\nGas Used: 85432\n\nTrace:\n[85432] 0x456::fallback()\n  ├─ [2100] SLOAD(0x00) → operator_bitfield\n  ├─ [3] CALLER → 0x123\n  ├─ [3] AND(operator_bitfield, mask) → 1 (authorized)\n  ├─ [3] CALLDATALOAD(0) → 0x01... (opcode)\n  ├─ [45000] 0xWETH::transfer(pair, 1000000000000000000)\n  │   ├─ [2100] SLOAD(balances[0x456]) → 5000000000000000000\n  │   ├─ [100] SSTORE(balances[0x456]) = 4000000000000000000\n  │   ├─ [20000] SSTORE(balances[pair]) += 1000000000000000000\n  │   └─ [0] RETURN(true)\n  ├─ [35000] 0xPair::swap(0, amountOut, recipient, \"\")\n  │   └─ [0] RETURN()\n  └─ [0] STOP\n```\n\n## Mendekode Revert Reason\n\nKetika transaksi revert, data revert sering berisi informasi berguna:\n\n```bash\n# Dekode revert data\ncast decode-error 0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000\n\n# Output: Error(string): \"Insufficient balance\"\n```\n\nUntuk custom error di Solidity 0.8+:\n```bash\ncast decode-error 0x...\"custom selector\"\n```\n\nUntuk kontrak Huff yang revert tanpa data (`revert(0, 0)`), Anda hanya mendapatkan empty revert — inilah mengapa trace sangat penting.\n\n## Debugging Stack Error\n\nKesalahan stack paling umum di Huff:\n\n### 1. Stack Underflow\nMengambil dari stack kosong. EVM revert tanpa pesan.\n\n**Diagnosa:** Trace menunjukkan REVERT setelah opcode yang mengkonsumsi (ADD, SUB, dll) ketika stack tidak memiliki cukup item.\n\n**Fix:** Tambahkan komentar stack di setiap baris dan verifikasi `takes()` annotation cocok.\n\n### 2. Wrong Value on Stack\nNilai yang salah di posisi stack yang salah — hasilnya benar tetapi data yang salah.\n\n**Diagnosa:** Gunakan `forge debug` untuk step-through:\n```bash\nforge debug --debug src\u002Ftest\u002FMyTest.t.sol::testSwap\n```\n\nInteractive debugger menampilkan stack di setiap langkah.\n\n### 3. Off-by-one DUP\u002FSWAP\n`dup3` ketika seharusnya `dup4` karena push tambahan sebelumnya.\n\n**Diagnosa:** Trace stack state di setiap opcode dan bandingkan dengan komentar.\n\n## Gas Profiling\n\n```bash\n# Gas report per fungsi\nforge test --gas-report\n\n# Output:\n| Function      | Min  | Avg   | Median | Max   |\n|---------------|------|-------|--------|-------|\n| swap()        | 65000| 72000 | 71000  | 85000 |\n| withdraw()    | 21000| 25000 | 24000  | 30000 |\n```\n\nUntuk profiling granular per opcode:\n```bash\nforge test -vvvv --match-test testSwap 2>&1 | grep \"gas:\"\n```\n\n## Alat Debugging Tambahan\n\n### Tenderly\nPlatform web yang menyediakan visual debugger untuk transaksi mainnet. Menampilkan state changes, event, dan execution trace dalam format visual.\n\n### evm-trace (Python)\n```python\nfrom evm_trace import TraceFrame\n# Parse dan analisis trace dari node debug_traceTransaction\n```\n\n### hevm\nSymbolic execution engine yang bisa membuktikan properti tentang bytecode EVM.\n\n## Best Practice Debugging\n\n1. **Tulis komentar stack** — Satu-satunya dokumentasi yang diperlukan di Huff\n2. **Test incrementally** — Bangun dan test makro satu per satu\n3. **Gunakan fork testing** — Bug sering muncul hanya dengan state nyata\n4. **Pin block number** — Untuk reprodusibilitas sempurna\n5. **Simpan trace gagal** — Untuk analisis root cause nanti\n6. **Bandingkan gas** — Regresi gas sering mengindikasikan bug logika\n\n## Kesimpulan\n\nDebugging bytecode EVM memerlukan mentalitas berbeda dari debugging tradisional. Execution trace menggantikan breakpoint, stack dump menggantikan variabel watch, dan gas profiling menggantikan performance profiler. Kuasai alat-alat ini dan debugging kontrak Huff menjadi sistematik alih-alih trial-and-error.","\u003Ch2 id=\"tantangan-debugging-evm\">Tantangan Debugging EVM\u003C\u002Fh2>\n\u003Cp>Debugging kontrak EVM — terutama yang ditulis di Huff atau Yul — berbeda fundamental dari debugging software tradisional. Tidak ada breakpoint, tidak ada variabel watch, tidak ada stack trace yang bermakna. Yang Anda miliki adalah:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Urutan opcode yang dieksekusi\u003C\u002Fli>\n\u003Cli>State stack di setiap langkah\u003C\u002Fli>\n\u003Cli>Perubahan memory dan storage\u003C\u002Fli>\n\u003Cli>Gas yang dikonsumsi per opcode\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Artikel ini mengajarkan cara menggunakan alat-alat ini secara efektif.\u003C\u002Fp>\n\u003Ch2 id=\"foundry-trace-dengan-verbosity-tinggi\">Foundry Trace dengan Verbosity Tinggi\u003C\u002Fh2>\n\u003Cp>Foundry menyediakan empat level verbosity:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">forge test -v    # Level 1: pass\u002Ffail\nforge test -vv   # Level 2: + log output\nforge test -vvv  # Level 3: + execution trace\nforge test -vvvv # Level 4: + opcode trace\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Level 4 (\u003Ccode>-vvvv\u003C\u002Fcode>) menampilkan setiap opcode yang dieksekusi:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>[CALL] 0x1234...::swap(uint256) [gas: 80000]\n  ├─ [SLOAD] slot 0x00 → 0x...reserve0\n  ├─ [SLOAD] slot 0x01 → 0x...reserve1\n  ├─ [MUL] 997 * amountIn → amountWithFee\n  ├─ [CALL] 0xtoken::transfer(pair, amount)\n  │   ├─ [SLOAD] balances[sender] → balance\n  │   ├─ [SUB] balance - amount → newBalance\n  │   ├─ [SSTORE] balances[sender] = newBalance\n  │   └─ [RETURN] true\n  └─ [RETURN] success\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"cast-run-replay-transaksi\">cast run: Replay Transaksi\u003C\u002Fh2>\n\u003Cp>\u003Ccode>cast run\u003C\u002Fcode> memungkinkan Anda me-replay transaksi mainnet apa pun dengan trace lengkap:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\"># Replay transaksi dengan trace\ncast run 0x1234...txhash --rpc-url $ETH_RPC -vvvv\n\n# Replay pada block tertentu\ncast run 0x1234...txhash --rpc-url $ETH_RPC --block 18000000\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Ini sangat berguna untuk:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Menganalisis mengapa transaksi MEV gagal\u003C\u002Fli>\n\u003Cli>Mempelajari strategi pencari lain\u003C\u002Fli>\n\u003Cli>Memahami interaksi kontrak yang kompleks\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 id=\"membaca-execution-trace\">Membaca Execution Trace\u003C\u002Fh2>\n\u003Cp>Execution trace menampilkan hierarki panggilan:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>Transaction: 0xabc...\nFrom: 0x123...\nTo: 0x456...\nValue: 0\nGas: 150000\nGas Used: 85432\n\nTrace:\n[85432] 0x456::fallback()\n  ├─ [2100] SLOAD(0x00) → operator_bitfield\n  ├─ [3] CALLER → 0x123\n  ├─ [3] AND(operator_bitfield, mask) → 1 (authorized)\n  ├─ [3] CALLDATALOAD(0) → 0x01... (opcode)\n  ├─ [45000] 0xWETH::transfer(pair, 1000000000000000000)\n  │   ├─ [2100] SLOAD(balances[0x456]) → 5000000000000000000\n  │   ├─ [100] SSTORE(balances[0x456]) = 4000000000000000000\n  │   ├─ [20000] SSTORE(balances[pair]) += 1000000000000000000\n  │   └─ [0] RETURN(true)\n  ├─ [35000] 0xPair::swap(0, amountOut, recipient, \"\")\n  │   └─ [0] RETURN()\n  └─ [0] STOP\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"mendekode-revert-reason\">Mendekode Revert Reason\u003C\u002Fh2>\n\u003Cp>Ketika transaksi revert, data revert sering berisi informasi berguna:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\"># Dekode revert data\ncast decode-error 0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000\n\n# Output: Error(string): \"Insufficient balance\"\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Untuk custom error di Solidity 0.8+:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">cast decode-error 0x...\"custom selector\"\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Untuk kontrak Huff yang revert tanpa data (\u003Ccode>revert(0, 0)\u003C\u002Fcode>), Anda hanya mendapatkan empty revert — inilah mengapa trace sangat penting.\u003C\u002Fp>\n\u003Ch2 id=\"debugging-stack-error\">Debugging Stack Error\u003C\u002Fh2>\n\u003Cp>Kesalahan stack paling umum di Huff:\u003C\u002Fp>\n\u003Ch3>1. Stack Underflow\u003C\u002Fh3>\n\u003Cp>Mengambil dari stack kosong. EVM revert tanpa pesan.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Diagnosa:\u003C\u002Fstrong> Trace menunjukkan REVERT setelah opcode yang mengkonsumsi (ADD, SUB, dll) ketika stack tidak memiliki cukup item.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Fix:\u003C\u002Fstrong> Tambahkan komentar stack di setiap baris dan verifikasi \u003Ccode>takes()\u003C\u002Fcode> annotation cocok.\u003C\u002Fp>\n\u003Ch3>2. Wrong Value on Stack\u003C\u002Fh3>\n\u003Cp>Nilai yang salah di posisi stack yang salah — hasilnya benar tetapi data yang salah.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Diagnosa:\u003C\u002Fstrong> Gunakan \u003Ccode>forge debug\u003C\u002Fcode> untuk step-through:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">forge debug --debug src\u002Ftest\u002FMyTest.t.sol::testSwap\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Interactive debugger menampilkan stack di setiap langkah.\u003C\u002Fp>\n\u003Ch3>3. Off-by-one DUP\u002FSWAP\u003C\u002Fh3>\n\u003Cp>\u003Ccode>dup3\u003C\u002Fcode> ketika seharusnya \u003Ccode>dup4\u003C\u002Fcode> karena push tambahan sebelumnya.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Diagnosa:\u003C\u002Fstrong> Trace stack state di setiap opcode dan bandingkan dengan komentar.\u003C\u002Fp>\n\u003Ch2 id=\"gas-profiling\">Gas Profiling\u003C\u002Fh2>\n\u003Cpre>\u003Ccode class=\"language-bash\"># Gas report per fungsi\nforge test --gas-report\n\n# Output:\n| Function      | Min  | Avg   | Median | Max   |\n|---------------|------|-------|--------|-------|\n| swap()        | 65000| 72000 | 71000  | 85000 |\n| withdraw()    | 21000| 25000 | 24000  | 30000 |\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Untuk profiling granular per opcode:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">forge test -vvvv --match-test testSwap 2&gt;&amp;1 | grep \"gas:\"\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"alat-debugging-tambahan\">Alat Debugging Tambahan\u003C\u002Fh2>\n\u003Ch3>Tenderly\u003C\u002Fh3>\n\u003Cp>Platform web yang menyediakan visual debugger untuk transaksi mainnet. Menampilkan state changes, event, dan execution trace dalam format visual.\u003C\u002Fp>\n\u003Ch3>evm-trace (Python)\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-python\">from evm_trace import TraceFrame\n# Parse dan analisis trace dari node debug_traceTransaction\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>hevm\u003C\u002Fh3>\n\u003Cp>Symbolic execution engine yang bisa membuktikan properti tentang bytecode EVM.\u003C\u002Fp>\n\u003Ch2 id=\"best-practice-debugging\">Best Practice Debugging\u003C\u002Fh2>\n\u003Col>\n\u003Cli>\u003Cstrong>Tulis komentar stack\u003C\u002Fstrong> — Satu-satunya dokumentasi yang diperlukan di Huff\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Test incrementally\u003C\u002Fstrong> — Bangun dan test makro satu per satu\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Gunakan fork testing\u003C\u002Fstrong> — Bug sering muncul hanya dengan state nyata\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Pin block number\u003C\u002Fstrong> — Untuk reprodusibilitas sempurna\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Simpan trace gagal\u003C\u002Fstrong> — Untuk analisis root cause nanti\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Bandingkan gas\u003C\u002Fstrong> — Regresi gas sering mengindikasikan bug logika\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch2 id=\"kesimpulan\">Kesimpulan\u003C\u002Fh2>\n\u003Cp>Debugging bytecode EVM memerlukan mentalitas berbeda dari debugging tradisional. Execution trace menggantikan breakpoint, stack dump menggantikan variabel watch, dan gas profiling menggantikan performance profiler. Kuasai alat-alat ini dan debugging kontrak Huff menjadi sistematik alih-alih trial-and-error.\u003C\u002Fp>\n","id","b0000000-0000-0000-0000-000000000001",true,"2026-03-28T10:44:25.108117Z","Teknik debugging bytecode EVM: execution trace, stack dump, cast run, gas profiling, dan best practice untuk kontrak Huff.","debugging EVM bytecode",null,"index, follow",[21,26,30],{"id":22,"name":23,"slug":24,"created_at":25},"c0000000-0000-0000-0000-000000000016","EVM","evm","2026-03-28T10:44:21.513630Z",{"id":27,"name":28,"slug":29,"created_at":25},"c0000000-0000-0000-0000-000000000021","Foundry","foundry",{"id":31,"name":32,"slug":33,"created_at":25},"c0000000-0000-0000-0000-000000000017","Huff","huff","Blockchain",[36,42,48],{"id":37,"title":38,"slug":39,"excerpt":40,"locale":12,"category_name":34,"published_at":41},"d0000000-0000-0000-0000-000000000596","Lapisan Interoperabilitas Ethereum: Bagaimana 55+ L2 Menjadi Satu Chain","lapisan-interoperabilitas-ethereum-bagaimana-55-l2-menjadi-satu-chain","Ethereum memiliki 55+ rollup Layer 2, memecah likuiditas dan pengalaman pengguna. Lapisan Interoperabilitas Ethereum — menggabungkan pesan lintas-rollup, shared sequencer, dan based rollup — bertujuan menyatukan mereka menjadi satu jaringan yang dapat dikomposisi.","2026-03-28T10:44:44.364342Z",{"id":43,"title":44,"slug":45,"excerpt":46,"locale":12,"category_name":34,"published_at":47},"d0000000-0000-0000-0000-000000000595","ZK Proofs Melampaui Rollups: Inferensi AI Terverifikasi di Ethereum","zk-proofs-melampaui-rollups-inferensi-ai-terverifikasi-ethereum","Zero-knowledge proofs bukan lagi sekadar alat penskalaan. Pada 2026, zkML memungkinkan inferensi AI terverifikasi on-chain, ZK coprocessor memindahkan komputasi berat off-chain dengan verifikasi on-chain, dan sistem pembuktian baru seperti SP1 dan Jolt menjadikannya praktis.","2026-03-28T10:44:44.358370Z",{"id":49,"title":50,"slug":51,"excerpt":52,"locale":12,"category_name":34,"published_at":53},"d0000000-0000-0000-0000-000000000572","EIP-7702 dalam Praktik: Membangun Alur Akun Pintar Setelah Pectra","eip-7702-dalam-praktik-membangun-alur-akun-pintar-setelah-pectra","EIP-7702 memungkinkan EOA Ethereum mana pun untuk sementara bertindak sebagai kontrak pintar dalam satu transaksi. Berikut cara mengimplementasikan transaksi batch, sponsorship gas, dan social recovery menggunakan primitif account abstraction baru.","2026-03-28T10:44:42.816894Z",{"id":13,"name":55,"slug":56,"bio":57,"photo_url":18,"linkedin":18,"role":58,"created_at":59,"updated_at":59},"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"]