Langsung ke konten utama
BlockchainMar 28, 2026

Deep EVM #12: Huff Lanjutan — Eksekusi Adaptif dan Komputasi On-Chain

OS
Open Soft Team

Engineering Team

Melampaui Dasar-Dasar

Di artikel sebelumnya kita membahas makro, label, manajemen stack, dan jump table. Sekarang kita menggabungkan semua keterampilan ini untuk membangun pola Huff lanjutan yang digunakan dalam kontrak produksi — terutama bot MEV dan kontrak DeFi yang dioptimasi.

Eksekusi Adaptif

Eksekusi adaptif berarti kontrak Anda mengubah perilakunya berdasarkan state on-chain saat runtime. Ini krusial untuk bot MEV yang perlu mengambil keputusan berdasarkan reserves pool, gas price, atau state kontrak lain.

Pola: Routing Berdasarkan State

#define macro ADAPTIVE_SWAP() = takes(0) returns(0) {
    // Baca reserves dari pool
    0x0902f1ac          // [getReserves_selector]
    0x00 mstore
    0x00 0x00 0x04 0x00 // [0, 4, 0, 0]
    [POOL] staticcall   // [success]
    pop
    
    0x00 mload          // [reserve0]
    0x20 mload          // [reserve1, reserve0]
    
    // Jika reserve0 > threshold, gunakan jalur A
    dup2                // [reserve0, reserve1, reserve0]
    [THRESHOLD] gt      // [reserve0>threshold?, reserve1, reserve0]
    path_a jumpi
    
    // Jalur B: reserves rendah, gunakan strategi berbeda
    PATH_B_SWAP()
    stop
    
    path_a:
    PATH_A_SWAP()
    stop
}

Pola ini memungkinkan satu kontrak menangani beberapa strategi swap tanpa redeploy.

Autentikasi Multi-Operator

Bot MEV sering memerlukan beberapa operator (alamat EOA yang berbeda) yang bisa menjalankan transaksi. Alih-alih mapping yang mahal, gunakan bitfield:

#define constant OPERATORS_SLOT = 0x00

#define macro IS_OPERATOR() = takes(0) returns(0) {
    caller              // [caller]
    [OPERATORS_SLOT]    // [slot, caller]
    sload               // [operators_bitfield, caller]
    
    // Hitung bit index dari address
    // Gunakan byte terakhir address sebagai index (0-255)
    swap1               // [caller, operators_bitfield]
    0xff and            // [index, operators_bitfield]
    
    // Buat bit mask: 1 << index
    0x01 swap1 shl      // [mask, operators_bitfield]
    
    // Periksa apakah bit diset
    and                 // [result]
    iszero              // [not_operator?]
    unauthorized jumpi  // []
    
    // Lanjutkan eksekusi...
    done jump
    
    unauthorized:
    0x00 0x00 revert
    done:
}

Satu slot storage menampung hingga 256 operator. Menambah/menghapus operator hanya memerlukan satu SSTORE.

Layout Memory Lanjutan

Untuk kontrak Huff yang kompleks, rencanakan layout memory di muka:

// Layout Memory Kontrak MEV:
// 0x00-0x1f:  Scratch space 1 (hashing, return data)
// 0x20-0x3f:  Scratch space 2 (hashing)
// 0x40-0x5f:  Calldata buffer - selector + param 1
// 0x60-0x7f:  Calldata buffer - param 2
// 0x80-0x9f:  Calldata buffer - param 3
// 0xa0-0xbf:  Calldata buffer - param 4
// 0xc0-0xdf:  Return data buffer
// 0xe0-0xff:  Stack spill area
// 0x100+:     Dynamic allocation (jarang digunakan)

Dengan layout yang direncanakan, Anda menghindari konflik memory dan bisa menggunakan kembali area yang sama untuk operasi yang tidak tumpang tindih.

Pola: Reuse Calldata Buffer

#define macro MULTI_CALL() = takes(0) returns(0) {
    // Panggilan 1: getReserves() pada pair
    0x0902f1ac 0x00 mstore
    0x60 0x00 0x04 0x00 [PAIR] staticcall pop
    
    // Simpan reserves
    0x00 mload      // [reserve0]
    0x20 mload      // [reserve1]
    
    // Panggilan 2: balanceOf() pada token — reuse buffer!
    0x70a08231 0x00 mstore
    address 0x04 mstore
    0x20 0x00 0x24 0x00 [TOKEN] staticcall pop
    
    // Balance sekarang di 0x00
    0x00 mload      // [balance, reserve1, reserve0]
}

Area memory 0x00-0x9f digunakan kembali untuk setiap external call, menghemat biaya ekspansi memory.

Komputasi On-Chain yang Dioptimasi

Kalkulasi Akar Kuadrat (Babylon Method)

Berguna untuk kalkulasi AMM (Uniswap V2 mint):

#define macro SQRT() = takes(1) returns(1) {
    // takes: [x]
    dup1            // [x, x]
    iszero          // [x==0?, x]
    is_zero jumpi   // [x]
    
    // Initial guess: x / 2 + 1
    dup1            // [x, x]
    0x01 shr        // [x/2, x]
    0x01 add        // [guess, x]
    
    // 7 iterasi Newton-Raphson (cukup untuk uint256)
    // guess = (guess + x/guess) / 2
    dup2 dup2 div   // [x/guess, guess, x]
    add             // [guess+x/guess, x]
    0x01 shr        // [new_guess, x]
    
    dup2 dup2 div add 0x01 shr  // iterasi 2
    dup2 dup2 div add 0x01 shr  // iterasi 3
    dup2 dup2 div add 0x01 shr  // iterasi 4
    dup2 dup2 div add 0x01 shr  // iterasi 5
    dup2 dup2 div add 0x01 shr  // iterasi 6
    dup2 dup2 div add 0x01 shr  // iterasi 7
    
    // Ambil min(guess, x/guess) untuk floor sqrt
    dup2 dup2 div   // [x/guess, guess, x]
    dup2            // [guess, x/guess, guess, x]
    gt              // [guess>x/guess?, guess, x]
    finalize jumpi  // [guess, x]
    swap1 pop       // [guess]
    end jump
    
    finalize:
    dup2 swap1 div  // [x/guess, x]
    swap1 pop       // [x/guess]
    end jump
    
    is_zero:
    // x = 0, sqrt = 0
    end:
}

Kalkulasi Minimum dan Maksimum Tanpa Branching

#define macro MIN() = takes(2) returns(1) {
    // takes: [a, b]
    // min tanpa branching: a ^ ((a ^ b) & -(a > b))
    dup2 dup2       // [a, b, a, b]
    gt              // [a>b?, a, b]
    0x00 sub        // [mask, a, b]  — mask = 0xfff... jika a>b, 0 jika tidak
    dup3 dup3       // [a, b, mask, a, b]
    xor             // [a^b, mask, a, b]
    and             // [(a^b)&mask, a, b]
    swap2 pop       // [(a^b)&mask, a]
    xor             // [result]
}

Teknik branchless ini menghemat ~8 gas dibanding pendekatan JUMPI karena menghindari overhead percabangan.

Pola Produksi: Sandwich Bot Skeleton

#define macro MAIN() = takes(0) returns(0) {
    // Auth check
    IS_OPERATOR()
    
    // Baca opcode dari calldata[0]
    0x00 calldataload 0xf8 shr  // [op]
    
    switch_op:
    dup1 0x01 eq buy jumpi      // op 1: frontrun buy
    dup1 0x02 eq sell jumpi     // op 2: backrun sell
    dup1 0x03 eq withdraw jumpi // op 3: withdraw profit
    0x00 0x00 revert
    
    buy:
    pop
    FRONTRUN_BUY()
    stop
    
    sell:
    pop
    BACKRUN_SELL()
    stop
    
    withdraw:
    pop
    WITHDRAW()
    stop
}

Testing Kontrak Huff

Gunakan Foundry dengan foundry-huff:

forge test --match-contract HuffTest -vvvv

Tulis test di Solidity yang men-deploy dan memanggil kontrak Huff Anda:

contract HuffTest is Test {
    HuffDeployer deployer;
    address bot;
    
    function setUp() public {
        bot = HuffDeployer.deploy("src/Bot");
    }
    
    function testSwap() public {
        // Panggil bot dengan calldata kustom
        (bool ok,) = bot.call(abi.encodePacked(uint8(0x01), amount));
        assertTrue(ok);
    }
}

Kesimpulan

Huff lanjutan menggabungkan eksekusi adaptif, autentikasi yang dioptimasi, layout memory yang direncanakan, dan komputasi on-chain yang efisien. Teknik-teknik ini membentuk fondasi untuk kontrak produksi MEV di mana setiap gas berarti. Kunci suksesnya adalah perencanaan yang matang dan pengujian yang ketat — debug Huff jauh lebih sulit dari Solidity.