[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-deep-evm-5-pengantar-yul-bahasa-assembly-solidity":3},{"article":4,"author":58},{"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":38,"related_articles":39},"d2000000-0000-0000-0000-000000000105","a0000000-0000-0000-0000-000000000022","Deep EVM #5: Pengantar Yul — Bahasa Assembly Rahasia Solidity","deep-evm-5-pengantar-yul-bahasa-assembly-solidity","Panduan praktis untuk Yul, bahasa assembly intermediate Solidity. Pelajari sintaks, tipe data, kontrol alur, dan kapan menggunakan inline assembly untuk optimasi gas.","## Apa Itu Yul?\n\nYul adalah bahasa assembly intermediate yang dirancang untuk EVM. Ia berada di antara Solidity tingkat tinggi dan opcode EVM mentah. Anda bisa menggunakan Yul dalam dua cara:\n\n1. **Inline assembly** — Blok `assembly { }` di dalam Solidity\n2. **Standalone Yul** — File `.yul` yang dikompilasi langsung ke bytecode\n\nYul memberikan kontrol langsung atas opcode EVM sambil mempertahankan sintaks yang dapat dibaca. Tidak seperti Huff yang benar-benar mentah, Yul memiliki variabel, fungsi, dan kontrol alur terstruktur.\n\n## Sintaks Dasar Yul\n\n```solidity\nassembly {\n    \u002F\u002F Variabel\n    let x := 42\n    let y := add(x, 1)  \u002F\u002F y = 43\n    \n    \u002F\u002F Memory\n    mstore(0x00, x)     \u002F\u002F Simpan x di memory[0x00]\n    let z := mload(0x00) \u002F\u002F Baca dari memory[0x00]\n    \n    \u002F\u002F Storage\n    sstore(0, x)        \u002F\u002F Simpan x di storage slot 0\n    let w := sload(0)   \u002F\u002F Baca dari storage slot 0\n    \n    \u002F\u002F Kontrol alur\n    if gt(x, 0) {\n        \u002F\u002F x > 0\n    }\n    \n    switch x\n    case 0 { \u002F* x == 0 *\u002F }\n    case 1 { \u002F* x == 1 *\u002F }\n    default { \u002F* lainnya *\u002F }\n    \n    \u002F\u002F Loop\n    for { let i := 0 } lt(i, 10) { i := add(i, 1) } {\n        \u002F\u002F badan loop\n    }\n}\n```\n\n## Variabel dan Tipe\n\nYul hanya memiliki satu tipe: `u256` (unsigned 256-bit integer). Semua nilai adalah 32-byte word. Tidak ada string, array, struct, atau tipe kompleks lainnya.\n\n```solidity\nassembly {\n    let a := 1          \u002F\u002F u256\n    let b := 0xff       \u002F\u002F u256\n    let c := true       \u002F\u002F 1 (u256)\n    let d := false      \u002F\u002F 0 (u256)\n    \u002F\u002F let s := \"hello\" \u002F\u002F TIDAK VALID di Yul EVM\n}\n```\n\nBoolean direpresentasikan sebagai 0 (false) dan non-zero (true). Alamat adalah u256 dengan 12 byte atas nol.\n\n## Mengakses Data Solidity dari Yul\n\nKetika menggunakan inline assembly di Solidity, Anda bisa mengakses variabel Solidity:\n\n```solidity\nfunction example(uint256 input) external pure returns (uint256) {\n    uint256 result;\n    assembly {\n        \u002F\u002F Akses parameter fungsi\n        result := add(input, 42)\n    }\n    return result;\n}\n```\n\nUntuk variabel state (storage), Anda mengakses slot-nya:\n\n```solidity\nuint256 public myValue;  \u002F\u002F slot 0\n\nfunction readValue() external view returns (uint256) {\n    uint256 val;\n    assembly {\n        val := sload(0)  \u002F\u002F Baca dari slot 0\n    }\n    return val;\n}\n```\n\nUntuk mapping, Anda harus menghitung slot secara manual:\n\n```solidity\nmapping(address => uint256) public balances;  \u002F\u002F slot 0\n\nfunction getBalance(address user) external view returns (uint256) {\n    uint256 bal;\n    assembly {\n        \u002F\u002F slot = keccak256(user . 0)\n        mstore(0x00, user)\n        mstore(0x20, 0)  \u002F\u002F slot dasar mapping\n        let slot := keccak256(0x00, 0x40)\n        bal := sload(slot)\n    }\n    return bal;\n}\n```\n\n## Fungsi Yul\n\n```solidity\nassembly {\n    function safeAdd(a, b) -> result {\n        result := add(a, b)\n        if lt(result, a) {\n            revert(0, 0)  \u002F\u002F overflow\n        }\n    }\n    \n    function max(a, b) -> m {\n        m := a\n        if gt(b, a) {\n            m := b\n        }\n    }\n    \n    let sum := safeAdd(100, 200)\n    let bigger := max(sum, 500)\n}\n```\n\nFungsi Yul dikompilasi menjadi JUMP\u002FJUMPDEST di bytecode — mirip dengan fungsi di Huff. Tidak ada overhead pemanggilan fungsi yang signifikan (8 gas untuk JUMP + 1 untuk JUMPDEST).\n\n## Kapan Menggunakan Inline Assembly\n\nInline assembly berguna ketika:\n\n1. **Optimasi gas kritis** — Hot path yang dipanggil jutaan kali\n2. **Operasi yang tidak tersedia di Solidity** — `RETURNDATASIZE`, `CHAINID`, `COINBASE`\n3. **Packing\u002Funpacking data** — Manipulasi bit yang lebih efisien\n4. **Komputasi hash kustom** — Keccak256 dengan layout memory manual\n5. **Interaksi tingkat rendah** — DELEGATECALL, CREATE2 dengan parameter spesifik\n\n### Contoh: Penghematan Gas Nyata\n\n```solidity\n\u002F\u002F Solidity murni: ~800 gas\nfunction transferSolidity(address to, uint256 amount) external {\n    require(balances[msg.sender] >= amount);\n    balances[msg.sender] -= amount;\n    balances[to] += amount;\n}\n\n\u002F\u002F Dengan assembly: ~600 gas\nfunction transferAssembly(address to, uint256 amount) external {\n    assembly {\n        \u002F\u002F Hitung slot pengirim\n        mstore(0x00, caller())\n        mstore(0x20, 0)  \u002F\u002F slot dasar balances\n        let senderSlot := keccak256(0x00, 0x40)\n        let senderBal := sload(senderSlot)\n        \n        \u002F\u002F Check\n        if lt(senderBal, amount) { revert(0, 0) }\n        \n        \u002F\u002F Update pengirim\n        sstore(senderSlot, sub(senderBal, amount))\n        \n        \u002F\u002F Hitung slot penerima\n        mstore(0x00, to)\n        let recipientSlot := keccak256(0x00, 0x40)\n        let recipientBal := sload(recipientSlot)\n        \n        \u002F\u002F Update penerima\n        sstore(recipientSlot, add(recipientBal, amount))\n    }\n}\n```\n\n## Keselamatan dan Risiko Assembly\n\nInline assembly melewati banyak pemeriksaan keselamatan Solidity:\n\n- **Tidak ada pemeriksaan overflow** — Anda harus menambahkan sendiri\n- **Tidak ada pemeriksaan tipe** — Semua 32-byte word\n- **Akses memory langsung** — Bisa menimpa free memory pointer\n- **Tidak ada reentrancy guard otomatis** — Harus ditangani manual\n\nAturan emas: gunakan assembly hanya ketika penghematan gas terbukti signifikan melalui benchmarking.\n\n## Debugging Yul\n\nFoundry mendukung debugging assembly:\n\n```bash\n# Trace eksekusi dengan opcode detail:\nforge test -vvvv --match-test testTransferAssembly\n\n# Gas snapshot:\nforge snapshot\n```\n\nAnda juga bisa menggunakan `forge debug` untuk stepping melalui opcode satu per satu.\n\n## Kesimpulan\n\nYul adalah jembatan antara Solidity dan opcode EVM mentah. Ia memberikan kontrol yang cukup untuk optimasi gas serius sambil mempertahankan readability yang lebih baik dari Huff. Untuk sebagian besar kasus penggunaan optimasi, inline assembly Yul adalah pilihan yang tepat — cukup dekat dengan metal untuk menghemat gas, cukup tinggi levelnya untuk tetap maintainable.","\u003Ch2 id=\"apa-itu-yul\">Apa Itu Yul?\u003C\u002Fh2>\n\u003Cp>Yul adalah bahasa assembly intermediate yang dirancang untuk EVM. Ia berada di antara Solidity tingkat tinggi dan opcode EVM mentah. Anda bisa menggunakan Yul dalam dua cara:\u003C\u002Fp>\n\u003Col>\n\u003Cli>\u003Cstrong>Inline assembly\u003C\u002Fstrong> — Blok \u003Ccode>assembly { }\u003C\u002Fcode> di dalam Solidity\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Standalone Yul\u003C\u002Fstrong> — File \u003Ccode>.yul\u003C\u002Fcode> yang dikompilasi langsung ke bytecode\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>Yul memberikan kontrol langsung atas opcode EVM sambil mempertahankan sintaks yang dapat dibaca. Tidak seperti Huff yang benar-benar mentah, Yul memiliki variabel, fungsi, dan kontrol alur terstruktur.\u003C\u002Fp>\n\u003Ch2 id=\"sintaks-dasar-yul\">Sintaks Dasar Yul\u003C\u002Fh2>\n\u003Cpre>\u003Ccode class=\"language-solidity\">assembly {\n    \u002F\u002F Variabel\n    let x := 42\n    let y := add(x, 1)  \u002F\u002F y = 43\n    \n    \u002F\u002F Memory\n    mstore(0x00, x)     \u002F\u002F Simpan x di memory[0x00]\n    let z := mload(0x00) \u002F\u002F Baca dari memory[0x00]\n    \n    \u002F\u002F Storage\n    sstore(0, x)        \u002F\u002F Simpan x di storage slot 0\n    let w := sload(0)   \u002F\u002F Baca dari storage slot 0\n    \n    \u002F\u002F Kontrol alur\n    if gt(x, 0) {\n        \u002F\u002F x &gt; 0\n    }\n    \n    switch x\n    case 0 { \u002F* x == 0 *\u002F }\n    case 1 { \u002F* x == 1 *\u002F }\n    default { \u002F* lainnya *\u002F }\n    \n    \u002F\u002F Loop\n    for { let i := 0 } lt(i, 10) { i := add(i, 1) } {\n        \u002F\u002F badan loop\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"variabel-dan-tipe\">Variabel dan Tipe\u003C\u002Fh2>\n\u003Cp>Yul hanya memiliki satu tipe: \u003Ccode>u256\u003C\u002Fcode> (unsigned 256-bit integer). Semua nilai adalah 32-byte word. Tidak ada string, array, struct, atau tipe kompleks lainnya.\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-solidity\">assembly {\n    let a := 1          \u002F\u002F u256\n    let b := 0xff       \u002F\u002F u256\n    let c := true       \u002F\u002F 1 (u256)\n    let d := false      \u002F\u002F 0 (u256)\n    \u002F\u002F let s := \"hello\" \u002F\u002F TIDAK VALID di Yul EVM\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Boolean direpresentasikan sebagai 0 (false) dan non-zero (true). Alamat adalah u256 dengan 12 byte atas nol.\u003C\u002Fp>\n\u003Ch2 id=\"mengakses-data-solidity-dari-yul\">Mengakses Data Solidity dari Yul\u003C\u002Fh2>\n\u003Cp>Ketika menggunakan inline assembly di Solidity, Anda bisa mengakses variabel Solidity:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-solidity\">function example(uint256 input) external pure returns (uint256) {\n    uint256 result;\n    assembly {\n        \u002F\u002F Akses parameter fungsi\n        result := add(input, 42)\n    }\n    return result;\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Untuk variabel state (storage), Anda mengakses slot-nya:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-solidity\">uint256 public myValue;  \u002F\u002F slot 0\n\nfunction readValue() external view returns (uint256) {\n    uint256 val;\n    assembly {\n        val := sload(0)  \u002F\u002F Baca dari slot 0\n    }\n    return val;\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Untuk mapping, Anda harus menghitung slot secara manual:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-solidity\">mapping(address =&gt; uint256) public balances;  \u002F\u002F slot 0\n\nfunction getBalance(address user) external view returns (uint256) {\n    uint256 bal;\n    assembly {\n        \u002F\u002F slot = keccak256(user . 0)\n        mstore(0x00, user)\n        mstore(0x20, 0)  \u002F\u002F slot dasar mapping\n        let slot := keccak256(0x00, 0x40)\n        bal := sload(slot)\n    }\n    return bal;\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"fungsi-yul\">Fungsi Yul\u003C\u002Fh2>\n\u003Cpre>\u003Ccode class=\"language-solidity\">assembly {\n    function safeAdd(a, b) -&gt; result {\n        result := add(a, b)\n        if lt(result, a) {\n            revert(0, 0)  \u002F\u002F overflow\n        }\n    }\n    \n    function max(a, b) -&gt; m {\n        m := a\n        if gt(b, a) {\n            m := b\n        }\n    }\n    \n    let sum := safeAdd(100, 200)\n    let bigger := max(sum, 500)\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Fungsi Yul dikompilasi menjadi JUMP\u002FJUMPDEST di bytecode — mirip dengan fungsi di Huff. Tidak ada overhead pemanggilan fungsi yang signifikan (8 gas untuk JUMP + 1 untuk JUMPDEST).\u003C\u002Fp>\n\u003Ch2 id=\"kapan-menggunakan-inline-assembly\">Kapan Menggunakan Inline Assembly\u003C\u002Fh2>\n\u003Cp>Inline assembly berguna ketika:\u003C\u002Fp>\n\u003Col>\n\u003Cli>\u003Cstrong>Optimasi gas kritis\u003C\u002Fstrong> — Hot path yang dipanggil jutaan kali\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Operasi yang tidak tersedia di Solidity\u003C\u002Fstrong> — \u003Ccode>RETURNDATASIZE\u003C\u002Fcode>, \u003Ccode>CHAINID\u003C\u002Fcode>, \u003Ccode>COINBASE\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Packing\u002Funpacking data\u003C\u002Fstrong> — Manipulasi bit yang lebih efisien\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Komputasi hash kustom\u003C\u002Fstrong> — Keccak256 dengan layout memory manual\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Interaksi tingkat rendah\u003C\u002Fstrong> — DELEGATECALL, CREATE2 dengan parameter spesifik\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch3>Contoh: Penghematan Gas Nyata\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-solidity\">\u002F\u002F Solidity murni: ~800 gas\nfunction transferSolidity(address to, uint256 amount) external {\n    require(balances[msg.sender] &gt;= amount);\n    balances[msg.sender] -= amount;\n    balances[to] += amount;\n}\n\n\u002F\u002F Dengan assembly: ~600 gas\nfunction transferAssembly(address to, uint256 amount) external {\n    assembly {\n        \u002F\u002F Hitung slot pengirim\n        mstore(0x00, caller())\n        mstore(0x20, 0)  \u002F\u002F slot dasar balances\n        let senderSlot := keccak256(0x00, 0x40)\n        let senderBal := sload(senderSlot)\n        \n        \u002F\u002F Check\n        if lt(senderBal, amount) { revert(0, 0) }\n        \n        \u002F\u002F Update pengirim\n        sstore(senderSlot, sub(senderBal, amount))\n        \n        \u002F\u002F Hitung slot penerima\n        mstore(0x00, to)\n        let recipientSlot := keccak256(0x00, 0x40)\n        let recipientBal := sload(recipientSlot)\n        \n        \u002F\u002F Update penerima\n        sstore(recipientSlot, add(recipientBal, amount))\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"keselamatan-dan-risiko-assembly\">Keselamatan dan Risiko Assembly\u003C\u002Fh2>\n\u003Cp>Inline assembly melewati banyak pemeriksaan keselamatan Solidity:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>Tidak ada pemeriksaan overflow\u003C\u002Fstrong> — Anda harus menambahkan sendiri\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Tidak ada pemeriksaan tipe\u003C\u002Fstrong> — Semua 32-byte word\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Akses memory langsung\u003C\u002Fstrong> — Bisa menimpa free memory pointer\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Tidak ada reentrancy guard otomatis\u003C\u002Fstrong> — Harus ditangani manual\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Aturan emas: gunakan assembly hanya ketika penghematan gas terbukti signifikan melalui benchmarking.\u003C\u002Fp>\n\u003Ch2 id=\"debugging-yul\">Debugging Yul\u003C\u002Fh2>\n\u003Cp>Foundry mendukung debugging assembly:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\"># Trace eksekusi dengan opcode detail:\nforge test -vvvv --match-test testTransferAssembly\n\n# Gas snapshot:\nforge snapshot\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Anda juga bisa menggunakan \u003Ccode>forge debug\u003C\u002Fcode> untuk stepping melalui opcode satu per satu.\u003C\u002Fp>\n\u003Ch2 id=\"kesimpulan\">Kesimpulan\u003C\u002Fh2>\n\u003Cp>Yul adalah jembatan antara Solidity dan opcode EVM mentah. Ia memberikan kontrol yang cukup untuk optimasi gas serius sambil mempertahankan readability yang lebih baik dari Huff. Untuk sebagian besar kasus penggunaan optimasi, inline assembly Yul adalah pilihan yang tepat — cukup dekat dengan metal untuk menghemat gas, cukup tinggi levelnya untuk tetap maintainable.\u003C\u002Fp>\n","id","b0000000-0000-0000-0000-000000000001",true,"2026-03-28T10:44:24.633784Z","Panduan praktis Yul: sintaks, variabel, fungsi, dan kapan menggunakan inline assembly untuk optimasi gas di smart contract.","Yul assembly EVM",null,"index, follow",[21,26,30,34],{"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-000000000014","Solidity","solidity",{"id":35,"name":36,"slug":37,"created_at":25},"c0000000-0000-0000-0000-000000000018","Yul","yul","Blockchain",[40,46,52],{"id":41,"title":42,"slug":43,"excerpt":44,"locale":12,"category_name":38,"published_at":45},"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":47,"title":48,"slug":49,"excerpt":50,"locale":12,"category_name":38,"published_at":51},"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":53,"title":54,"slug":55,"excerpt":56,"locale":12,"category_name":38,"published_at":57},"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":59,"slug":60,"bio":61,"photo_url":18,"linkedin":18,"role":62,"created_at":63,"updated_at":63},"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"]