[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-deep-evm-6-manajemen-memory-yul-mstore-mload":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-000000000106","a0000000-0000-0000-0000-000000000022","Deep EVM #6: Manajemen Memory Yul — mstore, mload, dan Free Memory Pointer","deep-evm-6-manajemen-memory-yul-mstore-mload","Menguasai manajemen memory di Yul: cara kerja mstore\u002Fmload, free memory pointer Solidity, scratch space, dan teknik layout memory untuk efisiensi gas maksimal.","## Memory di EVM: Model Fundamental\n\nMemory EVM adalah array byte linear yang dimulai dari nol dan tumbuh sesuai kebutuhan. Tidak seperti storage yang persisten, memory hanya ada selama panggilan fungsi saat ini — ia dibersihkan sepenuhnya ketika eksekusi selesai atau sub-panggilan dimulai.\n\nDua opcode fundamental untuk memory:\n- **MSTORE(offset, value)** — Menulis 32 byte di offset yang diberikan\n- **MLOAD(offset)** — Membaca 32 byte dari offset yang diberikan\n\n```solidity\nassembly {\n    mstore(0x00, 0x42)   \u002F\u002F Tulis 0x42 di memory[0x00..0x1f]\n    let val := mload(0x00) \u002F\u002F Baca 32 byte dari memory[0x00]\n    \u002F\u002F val = 0x42\n}\n```\n\n### MSTORE8: Menulis Satu Byte\n```solidity\nassembly {\n    mstore8(0x00, 0xff)  \u002F\u002F Tulis 1 byte: memory[0x00] = 0xff\n    \u002F\u002F Byte lain di word ini tidak terpengaruh\n}\n```\n\n## Free Memory Pointer Solidity\n\nSolidity menyimpan pointer ke memory bebas di offset 0x40. Setiap alokasi memory memperbarui pointer ini:\n\n```solidity\nassembly {\n    let fmp := mload(0x40)  \u002F\u002F Baca pointer saat ini\n    \n    \u002F\u002F Alokasi 64 byte\n    let ptr := fmp\n    mstore(0x40, add(fmp, 0x40))  \u002F\u002F Update pointer\n    \n    \u002F\u002F Gunakan ptr..ptr+64\n    mstore(ptr, 0x01)       \u002F\u002F Tulis di blok yang dialokasi\n    mstore(add(ptr, 0x20), 0x02)\n}\n```\n\nPENTING: Jika Anda menggunakan inline assembly dan mengabaikan free memory pointer, Anda bisa menimpa data yang dialokasi oleh Solidity. Ini menyebabkan bug yang sangat sulit di-debug.\n\n## Tata Letak Memory Solidity\n\n```\nOffset     Ukuran   Tujuan\n0x00-0x1f  32 byte  Scratch space 1 (untuk hashing)\n0x20-0x3f  32 byte  Scratch space 2 (untuk hashing)\n0x40-0x5f  32 byte  Free memory pointer\n0x60-0x7f  32 byte  Slot zero (selalu 0)\n0x80+      dinamis  Area alokasi\n```\n\nScratch space (0x00-0x3f) aman untuk digunakan dalam assembly karena Solidity hanya menggunakannya sementara untuk operasi keccak256.\n\n## Pola Memory Umum\n\n### Pola 1: Hashing Dua Nilai\n```solidity\nassembly {\n    \u002F\u002F keccak256(abi.encodePacked(a, b))\n    mstore(0x00, a)\n    mstore(0x20, b)\n    let hash := keccak256(0x00, 0x40)  \u002F\u002F Hash 64 byte\n}\n```\n\nIni adalah cara paling efisien untuk hashing — menggunakan scratch space tanpa alokasi memory.\n\n### Pola 2: Encoding ABI Manual\n```solidity\nassembly {\n    let ptr := mload(0x40)  \u002F\u002F Alokasi dari free memory pointer\n    \n    \u002F\u002F Encode: transfer(address,uint256)\n    mstore(ptr, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)\n    mstore(add(ptr, 0x04), to)      \u002F\u002F address (padded ke 32 byte)\n    mstore(add(ptr, 0x24), amount)  \u002F\u002F uint256\n    \n    \u002F\u002F Call\n    let ok := call(gas(), token, 0, ptr, 0x44, 0x00, 0x20)\n}\n```\n\n### Pola 3: Membaca Return Data\n```solidity\nassembly {\n    \u002F\u002F Setelah call, baca return data\n    let size := returndatasize()\n    let ptr := mload(0x40)\n    returndatacopy(ptr, 0, size)  \u002F\u002F Salin return data ke memory\n    \n    \u002F\u002F Parse hasil\n    let success := mload(ptr)  \u002F\u002F Asumsi: mengembalikan bool\n}\n```\n\n## Biaya Ekspansi Memory\n\nMemory tidak gratis — biayanya tumbuh secara kuadratik:\n\n```\nbiaya(ukuran_word) = 3 * ukuran_word + floor(ukuran_word^2 \u002F 512)\n```\n\n| Memory Digunakan | Biaya Total | Biaya Marginal |\n|-----------------|-------------|----------------|\n| 32 byte (1 word) | 3 gas | 3 gas |\n| 1 KB (32 words) | 98 gas | 3 gas\u002Fword |\n| 10 KB (320 words) | 1160 gas | 4+ gas\u002Fword |\n| 100 KB (3200 words) | 29600 gas | 16+ gas\u002Fword |\n| 1 MB (32000 words) | 2048000+ gas | mahal |\n\nBiaya kuadratik ini berarti Anda harus sangat berhati-hati dengan penggunaan memory. Jangan pernah mengalokasi lebih dari yang diperlukan.\n\n## Teknik Optimasi Memory\n\n### 1. Gunakan Kembali Memory\nDaripada terus mengalokasi, tulis ulang area memory yang sama:\n\n```solidity\nassembly {\n    \u002F\u002F Daripada alokasi baru untuk setiap operasi:\n    let scratch := 0x00  \u002F\u002F Gunakan scratch space\n    \n    \u002F\u002F Operasi 1\n    mstore(scratch, data1)\n    let hash1 := keccak256(scratch, 0x20)\n    \n    \u002F\u002F Operasi 2 — tulis ulang area yang sama\n    mstore(scratch, data2)\n    let hash2 := keccak256(scratch, 0x20)\n}\n```\n\n### 2. Hindari Free Memory Pointer untuk Operasi Sementara\n```solidity\nassembly {\n    \u002F\u002F Buruk: alokasi melalui FMP untuk data sementara\n    let ptr := mload(0x40)\n    mstore(0x40, add(ptr, 0x20))\n    mstore(ptr, someValue)\n    \u002F\u002F Memory ini tidak pernah dibebaskan\n    \n    \u002F\u002F Baik: gunakan scratch space\n    mstore(0x00, someValue)\n    \u002F\u002F Tidak ada alokasi permanen\n}\n```\n\n### 3. Batch Memory Write\n```solidity\nassembly {\n    \u002F\u002F Tulis beberapa nilai secara berurutan\n    let base := mload(0x40)\n    mstore(base, val1)\n    mstore(add(base, 0x20), val2)\n    mstore(add(base, 0x40), val3)\n    mstore(add(base, 0x60), val4)\n    \u002F\u002F Satu update FMP\n    mstore(0x40, add(base, 0x80))\n}\n```\n\n## MCOPY (EIP-5656)\n\nDiperkenalkan di upgrade Cancun (2024), MCOPY menyalin byte dalam memory:\n\n```solidity\nassembly {\n    mcopy(dst, src, length)\n}\n```\n\nBiaya: 3 gas + 3 gas per word yang disalin + biaya ekspansi. Ini lebih murah daripada loop MLOAD\u002FMSTORE manual untuk blok data besar.\n\n## Memory dalam Konteks Sub-panggilan\n\nKetika kontrak memanggil kontrak lain (CALL, STATICCALL, DELEGATECALL), kontrak yang dipanggil mendapatkan memory baru yang kosong. Memory pemanggil dipertahankan tetapi tidak bisa diakses oleh yang dipanggil.\n\nData dikomunikasikan antara pemanggil dan yang dipanggil melalui:\n- **Calldata** (input): Pemanggil menulis ke memory, meneruskan via parameter offset\u002Flength ke CALL\n- **Return data** (output): Yang dipanggil menulis ke memory-nya, pemanggil membaca via RETURNDATACOPY\n\n## Kesimpulan\n\nManajemen memory yang efisien adalah keterampilan kritis untuk pengembang Yul. Pahami tata letak memory Solidity, gunakan scratch space untuk operasi sementara, waspadai biaya ekspansi kuadratik, dan selalu pertahankan konsistensi free memory pointer saat mencampur Solidity dan inline assembly.","\u003Ch2 id=\"memory-di-evm-model-fundamental\">Memory di EVM: Model Fundamental\u003C\u002Fh2>\n\u003Cp>Memory EVM adalah array byte linear yang dimulai dari nol dan tumbuh sesuai kebutuhan. Tidak seperti storage yang persisten, memory hanya ada selama panggilan fungsi saat ini — ia dibersihkan sepenuhnya ketika eksekusi selesai atau sub-panggilan dimulai.\u003C\u002Fp>\n\u003Cp>Dua opcode fundamental untuk memory:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>MSTORE(offset, value)\u003C\u002Fstrong> — Menulis 32 byte di offset yang diberikan\u003C\u002Fli>\n\u003Cli>\u003Cstrong>MLOAD(offset)\u003C\u002Fstrong> — Membaca 32 byte dari offset yang diberikan\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cpre>\u003Ccode class=\"language-solidity\">assembly {\n    mstore(0x00, 0x42)   \u002F\u002F Tulis 0x42 di memory[0x00..0x1f]\n    let val := mload(0x00) \u002F\u002F Baca 32 byte dari memory[0x00]\n    \u002F\u002F val = 0x42\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>MSTORE8: Menulis Satu Byte\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-solidity\">assembly {\n    mstore8(0x00, 0xff)  \u002F\u002F Tulis 1 byte: memory[0x00] = 0xff\n    \u002F\u002F Byte lain di word ini tidak terpengaruh\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"free-memory-pointer-solidity\">Free Memory Pointer Solidity\u003C\u002Fh2>\n\u003Cp>Solidity menyimpan pointer ke memory bebas di offset 0x40. Setiap alokasi memory memperbarui pointer ini:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-solidity\">assembly {\n    let fmp := mload(0x40)  \u002F\u002F Baca pointer saat ini\n    \n    \u002F\u002F Alokasi 64 byte\n    let ptr := fmp\n    mstore(0x40, add(fmp, 0x40))  \u002F\u002F Update pointer\n    \n    \u002F\u002F Gunakan ptr..ptr+64\n    mstore(ptr, 0x01)       \u002F\u002F Tulis di blok yang dialokasi\n    mstore(add(ptr, 0x20), 0x02)\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>PENTING: Jika Anda menggunakan inline assembly dan mengabaikan free memory pointer, Anda bisa menimpa data yang dialokasi oleh Solidity. Ini menyebabkan bug yang sangat sulit di-debug.\u003C\u002Fp>\n\u003Ch2 id=\"tata-letak-memory-solidity\">Tata Letak Memory Solidity\u003C\u002Fh2>\n\u003Cpre>\u003Ccode>Offset     Ukuran   Tujuan\n0x00-0x1f  32 byte  Scratch space 1 (untuk hashing)\n0x20-0x3f  32 byte  Scratch space 2 (untuk hashing)\n0x40-0x5f  32 byte  Free memory pointer\n0x60-0x7f  32 byte  Slot zero (selalu 0)\n0x80+      dinamis  Area alokasi\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Scratch space (0x00-0x3f) aman untuk digunakan dalam assembly karena Solidity hanya menggunakannya sementara untuk operasi keccak256.\u003C\u002Fp>\n\u003Ch2 id=\"pola-memory-umum\">Pola Memory Umum\u003C\u002Fh2>\n\u003Ch3>Pola 1: Hashing Dua Nilai\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-solidity\">assembly {\n    \u002F\u002F keccak256(abi.encodePacked(a, b))\n    mstore(0x00, a)\n    mstore(0x20, b)\n    let hash := keccak256(0x00, 0x40)  \u002F\u002F Hash 64 byte\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Ini adalah cara paling efisien untuk hashing — menggunakan scratch space tanpa alokasi memory.\u003C\u002Fp>\n\u003Ch3>Pola 2: Encoding ABI Manual\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-solidity\">assembly {\n    let ptr := mload(0x40)  \u002F\u002F Alokasi dari free memory pointer\n    \n    \u002F\u002F Encode: transfer(address,uint256)\n    mstore(ptr, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)\n    mstore(add(ptr, 0x04), to)      \u002F\u002F address (padded ke 32 byte)\n    mstore(add(ptr, 0x24), amount)  \u002F\u002F uint256\n    \n    \u002F\u002F Call\n    let ok := call(gas(), token, 0, ptr, 0x44, 0x00, 0x20)\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>Pola 3: Membaca Return Data\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-solidity\">assembly {\n    \u002F\u002F Setelah call, baca return data\n    let size := returndatasize()\n    let ptr := mload(0x40)\n    returndatacopy(ptr, 0, size)  \u002F\u002F Salin return data ke memory\n    \n    \u002F\u002F Parse hasil\n    let success := mload(ptr)  \u002F\u002F Asumsi: mengembalikan bool\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"biaya-ekspansi-memory\">Biaya Ekspansi Memory\u003C\u002Fh2>\n\u003Cp>Memory tidak gratis — biayanya tumbuh secara kuadratik:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>biaya(ukuran_word) = 3 * ukuran_word + floor(ukuran_word^2 \u002F 512)\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ctable>\u003Cthead>\u003Ctr>\u003Cth>Memory Digunakan\u003C\u002Fth>\u003Cth>Biaya Total\u003C\u002Fth>\u003Cth>Biaya Marginal\u003C\u002Fth>\u003C\u002Ftr>\u003C\u002Fthead>\u003Ctbody>\n\u003Ctr>\u003Ctd>32 byte (1 word)\u003C\u002Ftd>\u003Ctd>3 gas\u003C\u002Ftd>\u003Ctd>3 gas\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>1 KB (32 words)\u003C\u002Ftd>\u003Ctd>98 gas\u003C\u002Ftd>\u003Ctd>3 gas\u002Fword\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>10 KB (320 words)\u003C\u002Ftd>\u003Ctd>1160 gas\u003C\u002Ftd>\u003Ctd>4+ gas\u002Fword\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>100 KB (3200 words)\u003C\u002Ftd>\u003Ctd>29600 gas\u003C\u002Ftd>\u003Ctd>16+ gas\u002Fword\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>1 MB (32000 words)\u003C\u002Ftd>\u003Ctd>2048000+ gas\u003C\u002Ftd>\u003Ctd>mahal\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\n\u003Cp>Biaya kuadratik ini berarti Anda harus sangat berhati-hati dengan penggunaan memory. Jangan pernah mengalokasi lebih dari yang diperlukan.\u003C\u002Fp>\n\u003Ch2 id=\"teknik-optimasi-memory\">Teknik Optimasi Memory\u003C\u002Fh2>\n\u003Ch3>1. Gunakan Kembali Memory\u003C\u002Fh3>\n\u003Cp>Daripada terus mengalokasi, tulis ulang area memory yang sama:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-solidity\">assembly {\n    \u002F\u002F Daripada alokasi baru untuk setiap operasi:\n    let scratch := 0x00  \u002F\u002F Gunakan scratch space\n    \n    \u002F\u002F Operasi 1\n    mstore(scratch, data1)\n    let hash1 := keccak256(scratch, 0x20)\n    \n    \u002F\u002F Operasi 2 — tulis ulang area yang sama\n    mstore(scratch, data2)\n    let hash2 := keccak256(scratch, 0x20)\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>2. Hindari Free Memory Pointer untuk Operasi Sementara\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-solidity\">assembly {\n    \u002F\u002F Buruk: alokasi melalui FMP untuk data sementara\n    let ptr := mload(0x40)\n    mstore(0x40, add(ptr, 0x20))\n    mstore(ptr, someValue)\n    \u002F\u002F Memory ini tidak pernah dibebaskan\n    \n    \u002F\u002F Baik: gunakan scratch space\n    mstore(0x00, someValue)\n    \u002F\u002F Tidak ada alokasi permanen\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>3. Batch Memory Write\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-solidity\">assembly {\n    \u002F\u002F Tulis beberapa nilai secara berurutan\n    let base := mload(0x40)\n    mstore(base, val1)\n    mstore(add(base, 0x20), val2)\n    mstore(add(base, 0x40), val3)\n    mstore(add(base, 0x60), val4)\n    \u002F\u002F Satu update FMP\n    mstore(0x40, add(base, 0x80))\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"mcopy-eip-5656\">MCOPY (EIP-5656)\u003C\u002Fh2>\n\u003Cp>Diperkenalkan di upgrade Cancun (2024), MCOPY menyalin byte dalam memory:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-solidity\">assembly {\n    mcopy(dst, src, length)\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Biaya: 3 gas + 3 gas per word yang disalin + biaya ekspansi. Ini lebih murah daripada loop MLOAD\u002FMSTORE manual untuk blok data besar.\u003C\u002Fp>\n\u003Ch2 id=\"memory-dalam-konteks-sub-panggilan\">Memory dalam Konteks Sub-panggilan\u003C\u002Fh2>\n\u003Cp>Ketika kontrak memanggil kontrak lain (CALL, STATICCALL, DELEGATECALL), kontrak yang dipanggil mendapatkan memory baru yang kosong. Memory pemanggil dipertahankan tetapi tidak bisa diakses oleh yang dipanggil.\u003C\u002Fp>\n\u003Cp>Data dikomunikasikan antara pemanggil dan yang dipanggil melalui:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>Calldata\u003C\u002Fstrong> (input): Pemanggil menulis ke memory, meneruskan via parameter offset\u002Flength ke CALL\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Return data\u003C\u002Fstrong> (output): Yang dipanggil menulis ke memory-nya, pemanggil membaca via RETURNDATACOPY\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 id=\"kesimpulan\">Kesimpulan\u003C\u002Fh2>\n\u003Cp>Manajemen memory yang efisien adalah keterampilan kritis untuk pengembang Yul. Pahami tata letak memory Solidity, gunakan scratch space untuk operasi sementara, waspadai biaya ekspansi kuadratik, dan selalu pertahankan konsistensi free memory pointer saat mencampur Solidity dan inline assembly.\u003C\u002Fp>\n","id","b0000000-0000-0000-0000-000000000001",true,"2026-03-28T10:44:24.639128Z","Menguasai memory EVM di Yul: mstore, mload, free memory pointer, tata letak memory Solidity, dan teknik optimasi.","Yul memory management",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-000000000020","Gas Optimization","gas-optimization",{"id":31,"name":32,"slug":33,"created_at":25},"c0000000-0000-0000-0000-000000000018","Yul","yul","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"]