[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-deep-evm-7-loop-kondisional-efisien-gas-yul":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-000000000107","a0000000-0000-0000-0000-000000000022","Deep EVM #7: Loop dan Kondisional Efisien Gas di Yul","deep-evm-7-loop-kondisional-efisien-gas-yul","Teknik loop dan kondisional di Yul yang menghemat gas: for loop teroptimasi, trik short-circuit, loop unrolling, dan perbandingan biaya gas dengan Solidity.","## Loop di Yul vs Solidity\n\nSolidity mengkompilasi loop for menjadi serangkaian opcode yang menyertakan pemeriksaan overflow, penanganan revert, dan boilerplate lainnya. Yul memungkinkan Anda menulis loop yang lebih ringkas dan efisien.\n\n### Solidity For Loop (Default)\n```solidity\nfor (uint256 i = 0; i \u003C length; i++) {\n    \u002F\u002F badan loop\n}\n```\n\nDikompilasi menjadi: inisialisasi + pemeriksaan overflow pada i++ + perbandingan + JUMPI + badan + increment + JUMP kembali.\n\n### Yul For Loop (Teroptimasi)\n```solidity\nassembly {\n    for { let i := 0 } lt(i, length) { i := add(i, 1) } {\n        \u002F\u002F badan loop\n    }\n}\n```\n\nPerbedaan kunci: Yul tidak menyisipkan pemeriksaan overflow pada `add(i, 1)`. Untuk counter loop yang tidak mungkin overflow (karena length \u003C 2^256), ini menghemat ~30 gas per iterasi.\n\n## Teknik Optimasi Loop\n\n### 1. Cache Batas Loop\n```solidity\n\u002F\u002F Buruk: membaca length dari storage setiap iterasi\nassembly {\n    for { let i := 0 } lt(i, sload(lengthSlot)) { i := add(i, 1) } {\n        \u002F\u002F SLOAD setiap iterasi = 100 gas warm per iterasi!\n    }\n}\n\n\u002F\u002F Baik: cache length di stack\nassembly {\n    let len := sload(lengthSlot)  \u002F\u002F Satu SLOAD\n    for { let i := 0 } lt(i, len) { i := add(i, 1) } {\n        \u002F\u002F len dari stack = 3 gas (DUP)\n    }\n}\n```\n\nPenghematan: (100 - 3) * jumlah_iterasi gas.\n\n### 2. Hitung Mundur\n```solidity\nassembly {\n    \u002F\u002F Menghitung mundur menghemat gas karena perbandingan dengan 0 (ISZERO)\n    \u002F\u002F lebih murah daripada perbandingan dengan nilai non-zero (LT)\n    let i := length\n    for { } gt(i, 0) { i := sub(i, 1) } {\n        let index := sub(i, 1)  \u002F\u002F index 0-based\n        \u002F\u002F ... gunakan index\n    }\n}\n```\n\nPenghematan: kecil (1-2 gas per iterasi) tetapi bertambah untuk loop panjang.\n\n### 3. Loop Unrolling\nUntuk loop dengan jumlah iterasi yang diketahui, unrolling menghilangkan overhead JUMP:\n\n```solidity\nassembly {\n    \u002F\u002F Daripada loop 4 iterasi:\n    \u002F\u002F for { let i := 0 } lt(i, 4) { i := add(i, 1) } { ... }\n    \n    \u002F\u002F Unroll:\n    let s0 := sload(0)\n    let s1 := sload(1)\n    let s2 := sload(2)\n    let s3 := sload(3)\n    let total := add(add(s0, s1), add(s2, s3))\n}\n```\n\nMenghemat: ~15 gas per iterasi yang di-unroll (JUMP + JUMPDEST + perbandingan + increment).\n\n### 4. Batch Processing\n```solidity\nassembly {\n    \u002F\u002F Proses 32 byte sekaligus daripada 1 byte\n    let words := div(dataLength, 32)\n    for { let i := 0 } lt(i, words) { i := add(i, 1) } {\n        let word := mload(add(dataPtr, mul(i, 32)))\n        \u002F\u002F Proses seluruh word 32-byte\n    }\n    \u002F\u002F Handle sisa byte\n    let remaining := mod(dataLength, 32)\n    if remaining {\n        let lastWord := mload(add(dataPtr, mul(words, 32)))\n        \u002F\u002F Mask byte yang relevan\n    }\n}\n```\n\n## Kondisional di Yul\n\n### If Statement\n```solidity\nassembly {\n    if condition {\n        \u002F\u002F dieksekusi jika condition != 0\n    }\n    \u002F\u002F Yul TIDAK memiliki else!\n}\n```\n\nYul tidak memiliki `else`. Untuk logika if-else, gunakan `switch`:\n\n### Switch Statement\n```solidity\nassembly {\n    switch condition\n    case 0 {\n        \u002F\u002F false branch\n    }\n    default {\n        \u002F\u002F true branch (non-zero)\n    }\n}\n```\n\n### Multi-Way Switch\n```solidity\nassembly {\n    \u002F\u002F Dispatch berdasarkan function selector\n    let selector := shr(224, calldataload(0))\n    \n    switch selector\n    case 0xa9059cbb { \u002F\u002F transfer(address,uint256)\n        \u002F\u002F handle transfer\n    }\n    case 0x70a08231 { \u002F\u002F balanceOf(address)\n        \u002F\u002F handle balanceOf\n    }\n    case 0x095ea7b3 { \u002F\u002F approve(address,uint256)\n        \u002F\u002F handle approve\n    }\n    default {\n        revert(0, 0)  \u002F\u002F fungsi tidak dikenali\n    }\n}\n```\n\n## Short-Circuit Evaluation\n\nSolidity mengkompilasi `&&` dan `||` dengan branching terpisah. Di Yul, Anda bisa menggunakan operasi bitwise untuk evaluasi tanpa branching:\n\n```solidity\nassembly {\n    \u002F\u002F Solidity: require(a > 0 && b > 0 && c > 0)\n    \u002F\u002F Menghasilkan 3 JUMPI\n    \n    \u002F\u002F Yul: satu pemeriksaan gabungan\n    if iszero(and(and(gt(a, 0), gt(b, 0)), gt(c, 0))) {\n        revert(0, 0)\n    }\n    \u002F\u002F Hanya 1 JUMPI!\n}\n```\n\nPenghematan: ~20 gas per kondisi tambahan yang digabungkan.\n\n## Perbandingan Gas: Yul vs Solidity\n\n| Operasi | Solidity | Yul | Penghematan |\n|---------|----------|-----|-------------|\n| Loop increment (i++) | ~35 gas | ~6 gas | ~29 gas |\n| Pemeriksaan 3 kondisi | ~45 gas | ~25 gas | ~20 gas |\n| Array sum (10 elemen) | ~800 gas | ~550 gas | ~250 gas |\n| Storage cache + loop | bervariasi | -30% | signifikan |\n\n## Pola Tingkat Lanjut\n\n### Early Exit dari Loop\n```solidity\nassembly {\n    let found := 0\n    for { let i := 0 } lt(i, length) { i := add(i, 1) } {\n        let val := sload(add(baseSlot, i))\n        if eq(val, target) {\n            found := 1\n            i := length  \u002F\u002F Paksa keluar dari loop\n        }\n    }\n}\n```\n\n### Loop dengan Akumulasi Memory\n```solidity\nassembly {\n    let ptr := mload(0x40)  \u002F\u002F Alokasi output\n    let outPtr := ptr\n    \n    for { let i := 0 } lt(i, count) { i := add(i, 1) } {\n        let val := sload(add(baseSlot, i))\n        if gt(val, threshold) {\n            mstore(outPtr, val)\n            outPtr := add(outPtr, 0x20)\n        }\n    }\n    \n    \u002F\u002F Update FMP\n    mstore(0x40, outPtr)\n    \u002F\u002F Jumlah hasil = (outPtr - ptr) \u002F 32\n}\n```\n\n## Perangkap Umum\n\n1. **Infinite loop** — Tanpa batas gas, loop Yul yang salah menghabiskan semua gas. Selalu pastikan kondisi terminasi.\n2. **Off-by-one** — Tanpa pemeriksaan batas otomatis, sangat mudah membaca melewati akhir array.\n3. **Stack depth** — Loop kompleks bisa mendorong stack mendekati batas 16 variabel lokal. Pindahkan data ke memory jika diperlukan.\n\n## Kesimpulan\n\nLoop dan kondisional di Yul memberikan kontrol penuh atas biaya gas. Cache batas loop, gabungkan kondisi, gunakan loop unrolling untuk iterasi yang diketahui, dan proses data dalam batch word 32-byte. Teknik-teknik ini secara konsisten menghasilkan penghematan 20-40% dibanding Solidity murni.","\u003Ch2 id=\"loop-di-yul-vs-solidity\">Loop di Yul vs Solidity\u003C\u002Fh2>\n\u003Cp>Solidity mengkompilasi loop for menjadi serangkaian opcode yang menyertakan pemeriksaan overflow, penanganan revert, dan boilerplate lainnya. Yul memungkinkan Anda menulis loop yang lebih ringkas dan efisien.\u003C\u002Fp>\n\u003Ch3>Solidity For Loop (Default)\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-solidity\">for (uint256 i = 0; i &lt; length; i++) {\n    \u002F\u002F badan loop\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Dikompilasi menjadi: inisialisasi + pemeriksaan overflow pada i++ + perbandingan + JUMPI + badan + increment + JUMP kembali.\u003C\u002Fp>\n\u003Ch3>Yul For Loop (Teroptimasi)\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-solidity\">assembly {\n    for { let i := 0 } lt(i, length) { i := add(i, 1) } {\n        \u002F\u002F badan loop\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Perbedaan kunci: Yul tidak menyisipkan pemeriksaan overflow pada \u003Ccode>add(i, 1)\u003C\u002Fcode>. Untuk counter loop yang tidak mungkin overflow (karena length &lt; 2^256), ini menghemat ~30 gas per iterasi.\u003C\u002Fp>\n\u003Ch2 id=\"teknik-optimasi-loop\">Teknik Optimasi Loop\u003C\u002Fh2>\n\u003Ch3>1. Cache Batas Loop\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-solidity\">\u002F\u002F Buruk: membaca length dari storage setiap iterasi\nassembly {\n    for { let i := 0 } lt(i, sload(lengthSlot)) { i := add(i, 1) } {\n        \u002F\u002F SLOAD setiap iterasi = 100 gas warm per iterasi!\n    }\n}\n\n\u002F\u002F Baik: cache length di stack\nassembly {\n    let len := sload(lengthSlot)  \u002F\u002F Satu SLOAD\n    for { let i := 0 } lt(i, len) { i := add(i, 1) } {\n        \u002F\u002F len dari stack = 3 gas (DUP)\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Penghematan: (100 - 3) * jumlah_iterasi gas.\u003C\u002Fp>\n\u003Ch3>2. Hitung Mundur\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-solidity\">assembly {\n    \u002F\u002F Menghitung mundur menghemat gas karena perbandingan dengan 0 (ISZERO)\n    \u002F\u002F lebih murah daripada perbandingan dengan nilai non-zero (LT)\n    let i := length\n    for { } gt(i, 0) { i := sub(i, 1) } {\n        let index := sub(i, 1)  \u002F\u002F index 0-based\n        \u002F\u002F ... gunakan index\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Penghematan: kecil (1-2 gas per iterasi) tetapi bertambah untuk loop panjang.\u003C\u002Fp>\n\u003Ch3>3. Loop Unrolling\u003C\u002Fh3>\n\u003Cp>Untuk loop dengan jumlah iterasi yang diketahui, unrolling menghilangkan overhead JUMP:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-solidity\">assembly {\n    \u002F\u002F Daripada loop 4 iterasi:\n    \u002F\u002F for { let i := 0 } lt(i, 4) { i := add(i, 1) } { ... }\n    \n    \u002F\u002F Unroll:\n    let s0 := sload(0)\n    let s1 := sload(1)\n    let s2 := sload(2)\n    let s3 := sload(3)\n    let total := add(add(s0, s1), add(s2, s3))\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Menghemat: ~15 gas per iterasi yang di-unroll (JUMP + JUMPDEST + perbandingan + increment).\u003C\u002Fp>\n\u003Ch3>4. Batch Processing\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-solidity\">assembly {\n    \u002F\u002F Proses 32 byte sekaligus daripada 1 byte\n    let words := div(dataLength, 32)\n    for { let i := 0 } lt(i, words) { i := add(i, 1) } {\n        let word := mload(add(dataPtr, mul(i, 32)))\n        \u002F\u002F Proses seluruh word 32-byte\n    }\n    \u002F\u002F Handle sisa byte\n    let remaining := mod(dataLength, 32)\n    if remaining {\n        let lastWord := mload(add(dataPtr, mul(words, 32)))\n        \u002F\u002F Mask byte yang relevan\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"kondisional-di-yul\">Kondisional di Yul\u003C\u002Fh2>\n\u003Ch3>If Statement\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-solidity\">assembly {\n    if condition {\n        \u002F\u002F dieksekusi jika condition != 0\n    }\n    \u002F\u002F Yul TIDAK memiliki else!\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Yul tidak memiliki \u003Ccode>else\u003C\u002Fcode>. Untuk logika if-else, gunakan \u003Ccode>switch\u003C\u002Fcode>:\u003C\u002Fp>\n\u003Ch3>Switch Statement\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-solidity\">assembly {\n    switch condition\n    case 0 {\n        \u002F\u002F false branch\n    }\n    default {\n        \u002F\u002F true branch (non-zero)\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>Multi-Way Switch\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-solidity\">assembly {\n    \u002F\u002F Dispatch berdasarkan function selector\n    let selector := shr(224, calldataload(0))\n    \n    switch selector\n    case 0xa9059cbb { \u002F\u002F transfer(address,uint256)\n        \u002F\u002F handle transfer\n    }\n    case 0x70a08231 { \u002F\u002F balanceOf(address)\n        \u002F\u002F handle balanceOf\n    }\n    case 0x095ea7b3 { \u002F\u002F approve(address,uint256)\n        \u002F\u002F handle approve\n    }\n    default {\n        revert(0, 0)  \u002F\u002F fungsi tidak dikenali\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"short-circuit-evaluation\">Short-Circuit Evaluation\u003C\u002Fh2>\n\u003Cp>Solidity mengkompilasi \u003Ccode>&amp;&amp;\u003C\u002Fcode> dan \u003Ccode>||\u003C\u002Fcode> dengan branching terpisah. Di Yul, Anda bisa menggunakan operasi bitwise untuk evaluasi tanpa branching:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-solidity\">assembly {\n    \u002F\u002F Solidity: require(a &gt; 0 &amp;&amp; b &gt; 0 &amp;&amp; c &gt; 0)\n    \u002F\u002F Menghasilkan 3 JUMPI\n    \n    \u002F\u002F Yul: satu pemeriksaan gabungan\n    if iszero(and(and(gt(a, 0), gt(b, 0)), gt(c, 0))) {\n        revert(0, 0)\n    }\n    \u002F\u002F Hanya 1 JUMPI!\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Penghematan: ~20 gas per kondisi tambahan yang digabungkan.\u003C\u002Fp>\n\u003Ch2 id=\"perbandingan-gas-yul-vs-solidity\">Perbandingan Gas: Yul vs Solidity\u003C\u002Fh2>\n\u003Ctable>\u003Cthead>\u003Ctr>\u003Cth>Operasi\u003C\u002Fth>\u003Cth>Solidity\u003C\u002Fth>\u003Cth>Yul\u003C\u002Fth>\u003Cth>Penghematan\u003C\u002Fth>\u003C\u002Ftr>\u003C\u002Fthead>\u003Ctbody>\n\u003Ctr>\u003Ctd>Loop increment (i++)\u003C\u002Ftd>\u003Ctd>~35 gas\u003C\u002Ftd>\u003Ctd>~6 gas\u003C\u002Ftd>\u003Ctd>~29 gas\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Pemeriksaan 3 kondisi\u003C\u002Ftd>\u003Ctd>~45 gas\u003C\u002Ftd>\u003Ctd>~25 gas\u003C\u002Ftd>\u003Ctd>~20 gas\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Array sum (10 elemen)\u003C\u002Ftd>\u003Ctd>~800 gas\u003C\u002Ftd>\u003Ctd>~550 gas\u003C\u002Ftd>\u003Ctd>~250 gas\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Storage cache + loop\u003C\u002Ftd>\u003Ctd>bervariasi\u003C\u002Ftd>\u003Ctd>-30%\u003C\u002Ftd>\u003Ctd>signifikan\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\n\u003Ch2 id=\"pola-tingkat-lanjut\">Pola Tingkat Lanjut\u003C\u002Fh2>\n\u003Ch3>Early Exit dari Loop\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-solidity\">assembly {\n    let found := 0\n    for { let i := 0 } lt(i, length) { i := add(i, 1) } {\n        let val := sload(add(baseSlot, i))\n        if eq(val, target) {\n            found := 1\n            i := length  \u002F\u002F Paksa keluar dari loop\n        }\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>Loop dengan Akumulasi Memory\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-solidity\">assembly {\n    let ptr := mload(0x40)  \u002F\u002F Alokasi output\n    let outPtr := ptr\n    \n    for { let i := 0 } lt(i, count) { i := add(i, 1) } {\n        let val := sload(add(baseSlot, i))\n        if gt(val, threshold) {\n            mstore(outPtr, val)\n            outPtr := add(outPtr, 0x20)\n        }\n    }\n    \n    \u002F\u002F Update FMP\n    mstore(0x40, outPtr)\n    \u002F\u002F Jumlah hasil = (outPtr - ptr) \u002F 32\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"perangkap-umum\">Perangkap Umum\u003C\u002Fh2>\n\u003Col>\n\u003Cli>\u003Cstrong>Infinite loop\u003C\u002Fstrong> — Tanpa batas gas, loop Yul yang salah menghabiskan semua gas. Selalu pastikan kondisi terminasi.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Off-by-one\u003C\u002Fstrong> — Tanpa pemeriksaan batas otomatis, sangat mudah membaca melewati akhir array.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Stack depth\u003C\u002Fstrong> — Loop kompleks bisa mendorong stack mendekati batas 16 variabel lokal. Pindahkan data ke memory jika diperlukan.\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch2 id=\"kesimpulan\">Kesimpulan\u003C\u002Fh2>\n\u003Cp>Loop dan kondisional di Yul memberikan kontrol penuh atas biaya gas. Cache batas loop, gabungkan kondisi, gunakan loop unrolling untuk iterasi yang diketahui, dan proses data dalam batch word 32-byte. Teknik-teknik ini secara konsisten menghasilkan penghematan 20-40% dibanding Solidity murni.\u003C\u002Fp>\n","id","b0000000-0000-0000-0000-000000000001",true,"2026-03-28T10:44:24.646371Z","Teknik loop dan kondisional di Yul: loop teroptimasi, short-circuit, unrolling, dan perbandingan biaya gas dengan Solidity.","Yul loop optimasi gas",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"]