Belajar Blockchain Developer - Oracles & Data
Episode 11 of 28

Belajar Blockchain Developer - Oracles & Data

Menjembatani kontrak dengan dunia nyata: konsep oracle, price feeds Chainlink, memilih data feed yang benar, serta praktik mengintegrasikan oracle ke dalam kontrak

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Setelah di episode 10 kalian membangun NFT, pada episode ini kita menjawab satu masalah yang paling sering diremehkan pemula: bagaimana kontrak tahu harga ETH saat ini? Blockchain, dengan segala kekuatannya, adalah mesin yang buta — ia hanya tahu apa yang ada di dalam dirinya. Harga pasar, cuaca, hasil olahraga, atau saldo bank ada di dunia luar.

Di sinilah oracle berperan: jembatan yang membawa data dunia nyata ke on-chain. Episode ini fokus pada Chainlink — jaringan oracle terbesar — dan cara mengintegrasikannya dengan aman.

Masalah "Buta" Blockchain

100%

Kontrak tidak bisa memanggil API eksternal langsung — eksekusi harus deterministik agar semua node mencapai hasil yang sama. Maka data eksternal harus diantarkan ke on-chain oleh oracle, atau dipicu oleh pihak luar.

Ada dua jenis pola oracle yang wajib kalian bedakan:

PolaCara KerjaContoh
PushOracle mengupdate data on-chain secara berkalaPrice feeds Chainlink
Pull (Request/Response)Kontrak meminta data, oracle menjawabVerifikasi event olahraga, random number

Price feed adalah pola push yang paling banyak dipakai: jaringan node Chainlink mengirimkan harga agregat ke kontrak aggregator yang ter-update berkala. Kontrak kalian cukup membaca harga terbaru.

Alamat aggregator berbeda-beda per chain dan per pair. Integrasi dasarnya:

contracts/PriceConsumer.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
 
interface IPriceFeed {
    function latestRoundData()
        external
        view
        returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
        );
}
 
contract PriceConsumer {
    IPriceFeed public immutable priceFeed;
 
    // Feed ETH/USD di Sepolia
    constructor(address _priceFeed) {
        priceFeed = IPriceFeed(_priceFeed);
    }
 
    function getLatestPrice() public view returns (uint256) {
        (, int256 answer, , uint256 updatedAt, ) =
            priceFeed.latestRoundData();
 
        require(block.timestamp - updatedAt < 3600, "stale price");
 
        // Harga dikembalikan dengan 8 desimal
        return uint256(answer);
    }
}

Perhatikan: kita selalu memeriksa stale price (updatedAt terlalu lama = data usang). Data feed yang basi adalah sumber bug halus yang sering ditemukan audit.

Warning

Jangan pernah membaca harga dari satu sumber tanpa validasi. Di production, pastikan: (1) harga tidak stale, (2) feed sesuai dengan chain tempat kontrak berjalan, dan (3) pahami unit harga (biasanya 8 desimal, tapi cek dokumentasi pair). Kesalahan kecil di sini bisa menguras dana protokol.

Memilih Feed yang Tepat

Bukan semua pasangan harga tersedia di semua chain. Sebelum menulis kode, cek Chainlink data feeds registry untuk pair dan chain yang kalian butuhkan. Aturan praktis:

  • Pakai pair langsung jika ada (misal ETH/USD), bukan turunan.
  • Untuk aset non-USD, gabungkan dua feed (misal token/ETH + ETH/USD) — tapi pastikan urutan dan presisi desimal benar.
  • Feed khusus chain (misal BNB/USD di BNB Chain) lebih aman daripada memakai feed lintas chain.

Contoh kombinasi dua feed:

contracts/CrossPrice.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
 
interface IPriceFeed {
    function latestRoundData()
        external
        view
        returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
        );
}
 
contract CrossPrice {
    // TOKEN/ETH dan ETH/USD → harga token dalam USD
    function getTokenUsd(
        address _tokenEthFeed,
        address _ethUsdFeed
    ) external view returns (uint256) {
        (, int256 tokenEth, , uint256 updatedAt, ) =
            IPriceFeed(_tokenEthFeed).latestRoundData();
        require(block.timestamp - updatedAt < 3600, "stale token/eth");
 
        (, int256 ethUsd, , uint256 updatedAt2, ) =
            IPriceFeed(_ethUsdFeed).latestRoundData();
        require(block.timestamp - updatedAt2 < 3600, "stale eth/usd");
 
        // tokenEth (8 des) * ethUsd (8 des) → 16 desimal
        return (uint256(tokenEth) * uint256(ethUsd)) / 1e8;
    }
}

Data Acak dan Verifikasi

Selain harga, oracle juga menyediakan random number (untuk NFT dan game) dan verifikasi event (untuk prediksi). Chainlink VRF (Verifiable Random Function) adalah standar untuk randomness yang bisa dibuktikan — penting karena block.timestamp atau blockhash adalah sumber randomness yang bisa dimanipulasi (kita bahas di episode 18).

contracts/VRFRandom.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
 
import "@chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2Plus.sol";
 
contract VRFRandom is VRFConsumerBaseV2Plus {
    uint256 public requestId;
    uint256 public randomNumber;
 
    // Konstruktor menerima SUBSCRIPTION_ID dan keyHash
    constructor(
        address _vrfCoordinator,
        uint256 _subId,
        bytes32 _keyHash
    )
        VRFConsumerBaseV2Plus(_vrfCoordinator)
    {}
 
    function requestRandom(uint256 _subId, bytes32 _keyHash)
        external
        returns (uint256)
    {
        requestId = s_vrfCoordinator.requestRandomWords(
            VRFV2PlusClient.RandomWordsRequest({
                keyHash: _keyHash,
                subId: _subId,
                requestConfirmations: 3,
                callbackGasLimit: 100_000,
                numWords: 1
            })
        );
        return requestId;
    }
 
    function fulfillRandomWords(
        uint256 _requestId,
        uint256[] calldata _randomWords
    ) internal override {
        randomNumber = _randomWords[0];
    }
}

VRF memakai pola callback: kontrak meminta, oracle menghitung randomness on-chain yang bisa diverifikasi, lalu memanggil fungsi callback. Pola request/response seperti ini adalah standar untuk semua data yang tidak bisa di-push berkala.

Tip

Untuk menguji integrasi oracle tanpa biaya, gunakan local node (anvil/hardhat node) dengan mock feed. forge test dengan vm.mockCall juga bisa mensimulasikan respons feed untuk menguji logika kontrak kalian secara menyeluruh.

Penutup

Inti yang harus dibawa pulang:

  • Blockchain buta terhadap dunia luar; oracle adalah jembatannya.
  • Price feeds = pola push; request/response = pola pull.
  • Selalu cek staleness dan unit desimal saat membaca feed.
  • Kombinasi feed harus memperhatikan presisi dan chain.
  • VRF untuk random number yang bisa dibuktikan.

Di episode 12 selanjutnya kita memperluas cakrawala — multi-chain development: Solana, BNB Chain, Base, dan Polygon, strategi multi-chain 2026, dan praktik men-deploy lintas chain. Mari lanjut ke episode 12!

Belajar Blockchain Developer - Oracles & Data | Belajar Blockchain Developer