[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-deep-evm-10-manajemen-stack-huff-dup-swap":3},{"article":4,"author":55},{"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":35,"related_articles":36},"d2000000-0000-0000-0000-000000000110","a0000000-0000-0000-0000-000000000022","Deep EVM #10: Manajemen Stack Huff — takes(), returns(), dan Seni dup\u002Fswap","deep-evm-10-manajemen-stack-huff-dup-swap","Kuasai mesin stack EVM: visualisasikan state stack, gunakan dup1-16 dan swap1-16 secara efektif, dan bangun pola untuk menyimpan nilai, merotasi, dan membersihkan.","## Model Mental Mesin Stack\n\nEVM adalah mesin stack. Tidak ada register, tidak ada variabel bernama — hanya stack last-in-first-out dari word 32-byte, 1024 slot dalamnya. Setiap opcode mendorong, mengambil, atau mengatur ulang item di stack ini. Jika Anda tidak bisa memegang state stack saat ini di kepala Anda, Anda akan menghasilkan bytecode yang bermasalah. Artikel ini tentang membangun model mental itu.\n\n### Konvensi Notasi\n\nDi seluruh artikel ini (dan dalam komentar Huff), kami merepresentasikan state stack dengan tanda kurung di mana item paling kiri adalah atas stack:\n\n```\n\u002F\u002F [atas, kedua, ketiga, ..., bawah]\n0x01  \u002F\u002F [1]\n0x02  \u002F\u002F [2, 1]\nadd   \u002F\u002F [3]\n```\n\nSetiap makro Huff harus memiliki komentar stack setelah setiap opcode. Ini bukan opsional — ini satu-satunya cara untuk mengaudit kebenaran.\n\n## DUP: Menduplikasi Item Stack\n\nEVM menyediakan `DUP1` hingga `DUP16`. `DUPn` menyalin item ke-n dari atas dan mendorongnya ke stack. Stack tumbuh sebanyak 1.\n\n```huff\n\u002F\u002F Stack: [a, b, c, d]\ndup1   \u002F\u002F [a, a, b, c, d]       — salin atas\ndup3   \u002F\u002F [c, a, a, b, c, d]    — salin ke-3 dari atas\n```\n\nBiaya gas: 3 gas untuk DUPn manapun. Ini adalah salah satu operasi termurah di EVM.\n\n### Kapan Menggunakan DUP\n\nDUP adalah alat Anda untuk **pembacaan non-destruktif**. Banyak opcode mengkonsumsi argumennya (ADD mengambil dua, mendorong satu), jadi jika Anda memerlukan nilai lagi nanti, DUP sebelum menyerahkannya ke opcode yang mengkonsumsi.\n\n```huff\n#define macro SAFE_SUB() = takes(2) returns(1) {\n    \u002F\u002F takes: [a, b] — hitung a - b, revert jika b > a\n    dup2 dup2       \u002F\u002F [a, b, a, b]\n    lt              \u002F\u002F [a \u003C b?, a, b]\n    revert_underflow jumpi  \u002F\u002F [a, b]\n    sub             \u002F\u002F [a - b]\n    done jump\n    revert_underflow:\n        0x00 0x00 revert\n    done:\n}\n```\n\nPerhatikan `dup2 dup2` — kita menduplikasi baik `a` maupun `b` karena `lt` akan mengkonsumsinya, tetapi kita masih memerlukan aslinya untuk `sub`.\n\n## SWAP: Mengatur Ulang Stack\n\nEVM menyediakan `SWAP1` hingga `SWAP16`. `SWAPn` menukar item teratas dengan item ke-(n+1). Ukuran stack tetap sama.\n\n```huff\n\u002F\u002F Stack: [a, b, c, d]\nswap1  \u002F\u002F [b, a, c, d]          — tukar atas dengan ke-2\nswap3  \u002F\u002F [d, a, c, b]          — tukar atas dengan ke-4\n```\n\nBiaya gas: 3 gas untuk SWAPn manapun.\n\n### Kapan Menggunakan SWAP\n\nSWAP mengurutkan ulang argumen untuk opcode yang mengharapkan urutan tertentu. Misalnya, `SUB` menghitung `stack[0] - stack[1]`. Jika nilai Anda dalam urutan yang salah:\n\n```huff\n\u002F\u002F Stack: [b, a]  — tetapi kita ingin a - b\nswap1   \u002F\u002F [a, b]\nsub     \u002F\u002F [a - b]\n```\n\n## Batasan Kedalaman-16\n\nDUP dan SWAP hanya menjangkau 16 level. Jika sebuah nilai ada di posisi 17 atau lebih dalam, Anda tidak bisa mengaksesnya dengan satu opcode. Ini adalah kendala keras EVM.\n\n**Strategi untuk stack dalam:**\n\n1. **Restrukturisasi logika Anda** untuk menjaga nilai yang dibutuhkan dekat atas. Ini pendekatan terbaik.\n2. **Gunakan memory sebagai scratch space.** Simpan nilai dengan `MSTORE`, ambil nanti dengan `MLOAD`. Biaya 3+3=6 gas vs 3 gas untuk DUP, tetapi menembus batasan kedalaman.\n3. **Pecah makro menjadi makro yang lebih kecil** yang masing-masing beroperasi pada item stack yang lebih sedikit.\n\n```huff\n#define macro STASH_TO_MEMORY() = takes(1) returns(0) {\n    \u002F\u002F takes: [value]\n    0x80 mstore     \u002F\u002F []  — simpan di 0x80 (scratch space)\n}\n\n#define macro RECALL_FROM_MEMORY() = takes(0) returns(1) {\n    0x80 mload      \u002F\u002F [value]\n}\n```\n\nDalam kontrak MEV kita sering memesan `0x80..0xc0` sebagai area scratch untuk nilai yang sebaliknya akan mendorong stack melewati 16.\n\n## Pola Umum\n\n### Pola 1: Menyimpan Nilai Melalui Operasi yang Mengkonsumsi\n\nAnda memiliki `[x]` dan perlu memanggil opcode yang mengkonsumsi `x` tetapi Anda masih memerlukan `x` setelahnya.\n\n```huff\n\u002F\u002F Ingin: hitung hash dari x, tetapi pertahankan x\n\u002F\u002F Stack: [x]\ndup1        \u002F\u002F [x, x]\n0x00 mstore \u002F\u002F [x]  — memory[0] = x\n0x20 0x00   \u002F\u002F [0, 32, x]\nkeccak256   \u002F\u002F [hash, x]\n```\n\n### Pola 2: Merotasi Tiga Item\n\nAnda memiliki `[a, b, c]` dan memerlukan `[c, a, b]`:\n\n```huff\nswap2       \u002F\u002F [c, b, a]\nswap1       \u002F\u002F [c, a, b]\n```\n\n2 opcode, 6 gas. Tidak ada rotasi opcode tunggal di EVM.\n\nAnda memiliki `[a, b, c]` dan memerlukan `[b, c, a]`:\n\n```huff\nswap1       \u002F\u002F [b, a, c]\nswap2       \u002F\u002F [b, c, a]\n```\n\n### Pola 3: Membersihkan Item Stack yang Tidak Diinginkan\n\nSetelah komputasi Anda mungkin memiliki item ekstra. Gunakan `pop` (2 gas) untuk membuang:\n\n```huff\n\u002F\u002F Stack: [result, sampah1, sampah2]\nswap1 pop   \u002F\u002F [result, sampah2]\nswap1 pop   \u002F\u002F [result]\n```\n\n### Pola 4: Menduplikasi Sepasang\n\nAnda perlu menyalin dua item teratas:\n\n```huff\n\u002F\u002F Stack: [a, b]\ndup2        \u002F\u002F [b, a, b]\ndup2        \u002F\u002F [a, b, a, b]\n```\n\nPerhatikan Anda DUP dalam urutan terbalik. `dup2` pertama menyalin `b` (yang ada di posisi 2), kemudian `dup2` menyalin `a` (sekarang di posisi 2 karena kita menumbuhkan stack). Pola ini muncul terus-menerus dalam kode perbandingan-sebelum-aritmatika.\n\n## Disiplin Visualisasi Stack\n\nKetika menulis Huff, adopsi disiplin ini:\n\n1. **Komentari setiap baris** dengan state stack setelah eksekusi.\n2. **Verifikasi takes\u002Freturns** — hitung item stack di masuk dan keluar.\n3. **Telusuri setiap cabang** — di setiap JUMPI, baik jalur yang diambil maupun tidak diambil harus meninggalkan stack dalam state yang valid.\n4. **Awasi drift stack** — jika badan loop tidak menyeimbangkan push dan pop secara sempurna, stack akan tumbuh atau menyusut di setiap iterasi.\n\n```huff\n#define macro TRANSFER() = takes(3) returns(0) {\n    \u002F\u002F takes: [amount, from, to]\n\n    \u002F\u002F Muat saldo pengirim\n    dup2                    \u002F\u002F [from, amount, from, to]\n    sload                   \u002F\u002F [bal_from, amount, from, to]\n\n    \u002F\u002F Periksa saldo cukup\n    dup1 dup3               \u002F\u002F [amount, bal_from, bal_from, amount, from, to]\n    gt                      \u002F\u002F [amount > bal_from?, bal_from, amount, from, to]\n    insufficient jumpi      \u002F\u002F [bal_from, amount, from, to]\n\n    \u002F\u002F Kurangi dari pengirim\n    dup2                    \u002F\u002F [amount, bal_from, amount, from, to]\n    swap1 sub               \u002F\u002F [bal_from - amount, amount, from, to]\n    dup3                    \u002F\u002F [from, new_bal, amount, from, to]\n    sstore                  \u002F\u002F [amount, from, to]\n\n    \u002F\u002F Tambahkan ke penerima\n    dup3                    \u002F\u002F [to, amount, from, to]\n    sload                   \u002F\u002F [bal_to, amount, from, to]\n    add                     \u002F\u002F [new_bal_to, from, to]\n    swap2                   \u002F\u002F [to, from, new_bal_to]\n    sstore                  \u002F\u002F [from]\n    pop                     \u002F\u002F []\n    done jump\n\n    insufficient:\n        0x00 0x00 revert\n    done:\n}\n```\n\nSetiap baris memiliki komentar stack. Setiap cabang berakhir dengan bersih. Ini satu-satunya cara untuk menulis Huff yang benar.\n\n## Debugging Error Stack\n\nBug paling umum di Huff:\n\n1. **Stack underflow** — Mengambil dari stack kosong. EVM revert saat runtime. Penyebab: salah menghitung `takes` atau lupa DUP.\n2. **Ketidakseimbangan stack di JUMP** — JUMPDEST yang dicapai dari dua jalur berbeda mengharapkan state stack yang berbeda. Compiler tidak akan menangkap ini.\n3. **Off-by-one di DUP\u002FSWAP** — `dup3` vs `dup4` ketika Anda menambahkan push ekstra sebelumnya. Inilah mengapa komentar stack wajib.\n\n`huffc` memiliki flag `--stack-check` yang melakukan analisis stack dasar:\n\n```bash\nhuffc src\u002FContract.huff -r --stack-check\n```\n\nIa menangkap underflow yang jelas tetapi tidak bisa menelusuri semua jalur jump dinamis. Untuk kontrak kompleks, telusuri eksekusi secara manual dengan `forge debug` atau `evm-trace`.\n\n## Lanjutan: Stack sebagai Register File\n\nPengembang Huff berpengalaman memikirkan ~8 posisi stack teratas sebagai register file:\n\n```\nPosisi 1 (atas):    Register kerja — komputasi saat ini\nPosisi 2-3:        Register argumen — input ke operasi berikutnya\nPosisi 4-6:        Register variabel lokal — nilai yang segera dibutuhkan\nPosisi 7-8:        Register konteks — counter loop, base pointer\nPosisi 9+:         Area spill — jarang diakses, pertimbangkan memory\n```\n\nModel mental ini membantu Anda memutuskan kapan SWAP nilai ke atas vs kapan DUP, dan kapan spill ke memory.\n\n## Ringkasan\n\nManajemen stack adalah keterampilan inti untuk pengembangan Huff. DUP untuk pembacaan non-destruktif, SWAP untuk pengurutan ulang, dan memory untuk nilai melewati kedalaman 16. Komentari setiap baris dengan state stack. Verifikasi setiap cabang. Di artikel berikutnya, kita akan menggunakan keterampilan ini untuk membangun dispatcher fungsi O(1) dengan jump table yang dipadatkan — di mana manajemen stack yang tepat langsung diterjemahkan menjadi penghematan gas.","\u003Ch2 id=\"model-mental-mesin-stack\">Model Mental Mesin Stack\u003C\u002Fh2>\n\u003Cp>EVM adalah mesin stack. Tidak ada register, tidak ada variabel bernama — hanya stack last-in-first-out dari word 32-byte, 1024 slot dalamnya. Setiap opcode mendorong, mengambil, atau mengatur ulang item di stack ini. Jika Anda tidak bisa memegang state stack saat ini di kepala Anda, Anda akan menghasilkan bytecode yang bermasalah. Artikel ini tentang membangun model mental itu.\u003C\u002Fp>\n\u003Ch3>Konvensi Notasi\u003C\u002Fh3>\n\u003Cp>Di seluruh artikel ini (dan dalam komentar Huff), kami merepresentasikan state stack dengan tanda kurung di mana item paling kiri adalah atas stack:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>\u002F\u002F [atas, kedua, ketiga, ..., bawah]\n0x01  \u002F\u002F [1]\n0x02  \u002F\u002F [2, 1]\nadd   \u002F\u002F [3]\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Setiap makro Huff harus memiliki komentar stack setelah setiap opcode. Ini bukan opsional — ini satu-satunya cara untuk mengaudit kebenaran.\u003C\u002Fp>\n\u003Ch2 id=\"dup-menduplikasi-item-stack\">DUP: Menduplikasi Item Stack\u003C\u002Fh2>\n\u003Cp>EVM menyediakan \u003Ccode>DUP1\u003C\u002Fcode> hingga \u003Ccode>DUP16\u003C\u002Fcode>. \u003Ccode>DUPn\u003C\u002Fcode> menyalin item ke-n dari atas dan mendorongnya ke stack. Stack tumbuh sebanyak 1.\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-huff\">\u002F\u002F Stack: [a, b, c, d]\ndup1   \u002F\u002F [a, a, b, c, d]       — salin atas\ndup3   \u002F\u002F [c, a, a, b, c, d]    — salin ke-3 dari atas\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Biaya gas: 3 gas untuk DUPn manapun. Ini adalah salah satu operasi termurah di EVM.\u003C\u002Fp>\n\u003Ch3>Kapan Menggunakan DUP\u003C\u002Fh3>\n\u003Cp>DUP adalah alat Anda untuk \u003Cstrong>pembacaan non-destruktif\u003C\u002Fstrong>. Banyak opcode mengkonsumsi argumennya (ADD mengambil dua, mendorong satu), jadi jika Anda memerlukan nilai lagi nanti, DUP sebelum menyerahkannya ke opcode yang mengkonsumsi.\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-huff\">#define macro SAFE_SUB() = takes(2) returns(1) {\n    \u002F\u002F takes: [a, b] — hitung a - b, revert jika b &gt; a\n    dup2 dup2       \u002F\u002F [a, b, a, b]\n    lt              \u002F\u002F [a &lt; b?, a, b]\n    revert_underflow jumpi  \u002F\u002F [a, b]\n    sub             \u002F\u002F [a - b]\n    done jump\n    revert_underflow:\n        0x00 0x00 revert\n    done:\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Perhatikan \u003Ccode>dup2 dup2\u003C\u002Fcode> — kita menduplikasi baik \u003Ccode>a\u003C\u002Fcode> maupun \u003Ccode>b\u003C\u002Fcode> karena \u003Ccode>lt\u003C\u002Fcode> akan mengkonsumsinya, tetapi kita masih memerlukan aslinya untuk \u003Ccode>sub\u003C\u002Fcode>.\u003C\u002Fp>\n\u003Ch2 id=\"swap-mengatur-ulang-stack\">SWAP: Mengatur Ulang Stack\u003C\u002Fh2>\n\u003Cp>EVM menyediakan \u003Ccode>SWAP1\u003C\u002Fcode> hingga \u003Ccode>SWAP16\u003C\u002Fcode>. \u003Ccode>SWAPn\u003C\u002Fcode> menukar item teratas dengan item ke-(n+1). Ukuran stack tetap sama.\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-huff\">\u002F\u002F Stack: [a, b, c, d]\nswap1  \u002F\u002F [b, a, c, d]          — tukar atas dengan ke-2\nswap3  \u002F\u002F [d, a, c, b]          — tukar atas dengan ke-4\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Biaya gas: 3 gas untuk SWAPn manapun.\u003C\u002Fp>\n\u003Ch3>Kapan Menggunakan SWAP\u003C\u002Fh3>\n\u003Cp>SWAP mengurutkan ulang argumen untuk opcode yang mengharapkan urutan tertentu. Misalnya, \u003Ccode>SUB\u003C\u002Fcode> menghitung \u003Ccode>stack[0] - stack[1]\u003C\u002Fcode>. Jika nilai Anda dalam urutan yang salah:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-huff\">\u002F\u002F Stack: [b, a]  — tetapi kita ingin a - b\nswap1   \u002F\u002F [a, b]\nsub     \u002F\u002F [a - b]\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"batasan-kedalaman-16\">Batasan Kedalaman-16\u003C\u002Fh2>\n\u003Cp>DUP dan SWAP hanya menjangkau 16 level. Jika sebuah nilai ada di posisi 17 atau lebih dalam, Anda tidak bisa mengaksesnya dengan satu opcode. Ini adalah kendala keras EVM.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Strategi untuk stack dalam:\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Col>\n\u003Cli>\u003Cstrong>Restrukturisasi logika Anda\u003C\u002Fstrong> untuk menjaga nilai yang dibutuhkan dekat atas. Ini pendekatan terbaik.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Gunakan memory sebagai scratch space.\u003C\u002Fstrong> Simpan nilai dengan \u003Ccode>MSTORE\u003C\u002Fcode>, ambil nanti dengan \u003Ccode>MLOAD\u003C\u002Fcode>. Biaya 3+3=6 gas vs 3 gas untuk DUP, tetapi menembus batasan kedalaman.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Pecah makro menjadi makro yang lebih kecil\u003C\u002Fstrong> yang masing-masing beroperasi pada item stack yang lebih sedikit.\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cpre>\u003Ccode class=\"language-huff\">#define macro STASH_TO_MEMORY() = takes(1) returns(0) {\n    \u002F\u002F takes: [value]\n    0x80 mstore     \u002F\u002F []  — simpan di 0x80 (scratch space)\n}\n\n#define macro RECALL_FROM_MEMORY() = takes(0) returns(1) {\n    0x80 mload      \u002F\u002F [value]\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Dalam kontrak MEV kita sering memesan \u003Ccode>0x80..0xc0\u003C\u002Fcode> sebagai area scratch untuk nilai yang sebaliknya akan mendorong stack melewati 16.\u003C\u002Fp>\n\u003Ch2 id=\"pola-umum\">Pola Umum\u003C\u002Fh2>\n\u003Ch3>Pola 1: Menyimpan Nilai Melalui Operasi yang Mengkonsumsi\u003C\u002Fh3>\n\u003Cp>Anda memiliki \u003Ccode>[x]\u003C\u002Fcode> dan perlu memanggil opcode yang mengkonsumsi \u003Ccode>x\u003C\u002Fcode> tetapi Anda masih memerlukan \u003Ccode>x\u003C\u002Fcode> setelahnya.\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-huff\">\u002F\u002F Ingin: hitung hash dari x, tetapi pertahankan x\n\u002F\u002F Stack: [x]\ndup1        \u002F\u002F [x, x]\n0x00 mstore \u002F\u002F [x]  — memory[0] = x\n0x20 0x00   \u002F\u002F [0, 32, x]\nkeccak256   \u002F\u002F [hash, x]\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>Pola 2: Merotasi Tiga Item\u003C\u002Fh3>\n\u003Cp>Anda memiliki \u003Ccode>[a, b, c]\u003C\u002Fcode> dan memerlukan \u003Ccode>[c, a, b]\u003C\u002Fcode>:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-huff\">swap2       \u002F\u002F [c, b, a]\nswap1       \u002F\u002F [c, a, b]\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>2 opcode, 6 gas. Tidak ada rotasi opcode tunggal di EVM.\u003C\u002Fp>\n\u003Cp>Anda memiliki \u003Ccode>[a, b, c]\u003C\u002Fcode> dan memerlukan \u003Ccode>[b, c, a]\u003C\u002Fcode>:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-huff\">swap1       \u002F\u002F [b, a, c]\nswap2       \u002F\u002F [b, c, a]\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>Pola 3: Membersihkan Item Stack yang Tidak Diinginkan\u003C\u002Fh3>\n\u003Cp>Setelah komputasi Anda mungkin memiliki item ekstra. Gunakan \u003Ccode>pop\u003C\u002Fcode> (2 gas) untuk membuang:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-huff\">\u002F\u002F Stack: [result, sampah1, sampah2]\nswap1 pop   \u002F\u002F [result, sampah2]\nswap1 pop   \u002F\u002F [result]\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>Pola 4: Menduplikasi Sepasang\u003C\u002Fh3>\n\u003Cp>Anda perlu menyalin dua item teratas:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-huff\">\u002F\u002F Stack: [a, b]\ndup2        \u002F\u002F [b, a, b]\ndup2        \u002F\u002F [a, b, a, b]\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Perhatikan Anda DUP dalam urutan terbalik. \u003Ccode>dup2\u003C\u002Fcode> pertama menyalin \u003Ccode>b\u003C\u002Fcode> (yang ada di posisi 2), kemudian \u003Ccode>dup2\u003C\u002Fcode> menyalin \u003Ccode>a\u003C\u002Fcode> (sekarang di posisi 2 karena kita menumbuhkan stack). Pola ini muncul terus-menerus dalam kode perbandingan-sebelum-aritmatika.\u003C\u002Fp>\n\u003Ch2 id=\"disiplin-visualisasi-stack\">Disiplin Visualisasi Stack\u003C\u002Fh2>\n\u003Cp>Ketika menulis Huff, adopsi disiplin ini:\u003C\u002Fp>\n\u003Col>\n\u003Cli>\u003Cstrong>Komentari setiap baris\u003C\u002Fstrong> dengan state stack setelah eksekusi.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Verifikasi takes\u002Freturns\u003C\u002Fstrong> — hitung item stack di masuk dan keluar.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Telusuri setiap cabang\u003C\u002Fstrong> — di setiap JUMPI, baik jalur yang diambil maupun tidak diambil harus meninggalkan stack dalam state yang valid.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Awasi drift stack\u003C\u002Fstrong> — jika badan loop tidak menyeimbangkan push dan pop secara sempurna, stack akan tumbuh atau menyusut di setiap iterasi.\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cpre>\u003Ccode class=\"language-huff\">#define macro TRANSFER() = takes(3) returns(0) {\n    \u002F\u002F takes: [amount, from, to]\n\n    \u002F\u002F Muat saldo pengirim\n    dup2                    \u002F\u002F [from, amount, from, to]\n    sload                   \u002F\u002F [bal_from, amount, from, to]\n\n    \u002F\u002F Periksa saldo cukup\n    dup1 dup3               \u002F\u002F [amount, bal_from, bal_from, amount, from, to]\n    gt                      \u002F\u002F [amount &gt; bal_from?, bal_from, amount, from, to]\n    insufficient jumpi      \u002F\u002F [bal_from, amount, from, to]\n\n    \u002F\u002F Kurangi dari pengirim\n    dup2                    \u002F\u002F [amount, bal_from, amount, from, to]\n    swap1 sub               \u002F\u002F [bal_from - amount, amount, from, to]\n    dup3                    \u002F\u002F [from, new_bal, amount, from, to]\n    sstore                  \u002F\u002F [amount, from, to]\n\n    \u002F\u002F Tambahkan ke penerima\n    dup3                    \u002F\u002F [to, amount, from, to]\n    sload                   \u002F\u002F [bal_to, amount, from, to]\n    add                     \u002F\u002F [new_bal_to, from, to]\n    swap2                   \u002F\u002F [to, from, new_bal_to]\n    sstore                  \u002F\u002F [from]\n    pop                     \u002F\u002F []\n    done jump\n\n    insufficient:\n        0x00 0x00 revert\n    done:\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Setiap baris memiliki komentar stack. Setiap cabang berakhir dengan bersih. Ini satu-satunya cara untuk menulis Huff yang benar.\u003C\u002Fp>\n\u003Ch2 id=\"debugging-error-stack\">Debugging Error Stack\u003C\u002Fh2>\n\u003Cp>Bug paling umum di Huff:\u003C\u002Fp>\n\u003Col>\n\u003Cli>\u003Cstrong>Stack underflow\u003C\u002Fstrong> — Mengambil dari stack kosong. EVM revert saat runtime. Penyebab: salah menghitung \u003Ccode>takes\u003C\u002Fcode> atau lupa DUP.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Ketidakseimbangan stack di JUMP\u003C\u002Fstrong> — JUMPDEST yang dicapai dari dua jalur berbeda mengharapkan state stack yang berbeda. Compiler tidak akan menangkap ini.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Off-by-one di DUP\u002FSWAP\u003C\u002Fstrong> — \u003Ccode>dup3\u003C\u002Fcode> vs \u003Ccode>dup4\u003C\u002Fcode> ketika Anda menambahkan push ekstra sebelumnya. Inilah mengapa komentar stack wajib.\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>\u003Ccode>huffc\u003C\u002Fcode> memiliki flag \u003Ccode>--stack-check\u003C\u002Fcode> yang melakukan analisis stack dasar:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">huffc src\u002FContract.huff -r --stack-check\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Ia menangkap underflow yang jelas tetapi tidak bisa menelusuri semua jalur jump dinamis. Untuk kontrak kompleks, telusuri eksekusi secara manual dengan \u003Ccode>forge debug\u003C\u002Fcode> atau \u003Ccode>evm-trace\u003C\u002Fcode>.\u003C\u002Fp>\n\u003Ch2 id=\"lanjutan-stack-sebagai-register-file\">Lanjutan: Stack sebagai Register File\u003C\u002Fh2>\n\u003Cp>Pengembang Huff berpengalaman memikirkan ~8 posisi stack teratas sebagai register file:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>Posisi 1 (atas):    Register kerja — komputasi saat ini\nPosisi 2-3:        Register argumen — input ke operasi berikutnya\nPosisi 4-6:        Register variabel lokal — nilai yang segera dibutuhkan\nPosisi 7-8:        Register konteks — counter loop, base pointer\nPosisi 9+:         Area spill — jarang diakses, pertimbangkan memory\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Model mental ini membantu Anda memutuskan kapan SWAP nilai ke atas vs kapan DUP, dan kapan spill ke memory.\u003C\u002Fp>\n\u003Ch2 id=\"ringkasan\">Ringkasan\u003C\u002Fh2>\n\u003Cp>Manajemen stack adalah keterampilan inti untuk pengembangan Huff. DUP untuk pembacaan non-destruktif, SWAP untuk pengurutan ulang, dan memory untuk nilai melewati kedalaman 16. Komentari setiap baris dengan state stack. Verifikasi setiap cabang. Di artikel berikutnya, kita akan menggunakan keterampilan ini untuk membangun dispatcher fungsi O(1) dengan jump table yang dipadatkan — di mana manajemen stack yang tepat langsung diterjemahkan menjadi penghematan gas.\u003C\u002Fp>\n","id","b0000000-0000-0000-0000-000000000001",true,"2026-03-28T10:44:24.872808Z","Deep EVM #10: Manajemen Stack Huff — dup, swap, dan Disiplin Stack","Kuasai manajemen stack EVM di Huff: dup1-16, swap1-16, batasan kedalaman-16, pola umum, dan debugging error stack.","manajemen stack Huff EVM",null,"index, follow",[22,27,31],{"id":23,"name":24,"slug":25,"created_at":26},"c0000000-0000-0000-0000-000000000016","EVM","evm","2026-03-28T10:44:21.513630Z",{"id":28,"name":29,"slug":30,"created_at":26},"c0000000-0000-0000-0000-000000000020","Gas Optimization","gas-optimization",{"id":32,"name":33,"slug":34,"created_at":26},"c0000000-0000-0000-0000-000000000017","Huff","huff","Blockchain",[37,43,49],{"id":38,"title":39,"slug":40,"excerpt":41,"locale":12,"category_name":35,"published_at":42},"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":44,"title":45,"slug":46,"excerpt":47,"locale":12,"category_name":35,"published_at":48},"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":50,"title":51,"slug":52,"excerpt":53,"locale":12,"category_name":35,"published_at":54},"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":56,"slug":57,"bio":58,"photo_url":19,"linkedin":19,"role":59,"created_at":60,"updated_at":60},"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"]