← Semua pembelajaran / Blockchain Nol → RWA
Fase 1 · Solidity & Smart Contract

OpenZeppelin — Ownable & access control

Kontrak yang menyimpan aset bernilai adalah target yang diperiksa banyak orang, termasuk yang berniat jahat. OpenZeppelin adalah pustaka kontrak yang sudah diaudit berulang kali dan dipakai di ribuan proyek produksi — pola pertama yang perlu kamu kenal sebelum menulis kontrak sendiri.

Intisari

  • Jangan tulis ulang logika access control, ERC-20/721, atau matematika aman dari nol — pakai OpenZeppelin, yang sudah melalui banyak audit publik dan dipakai luas.
  • Ownable: satu pemilik, cocok untuk kontrak sederhana dengan satu admin.
  • AccessControl: role-based, satu address bisa punya banyak role, cocok untuk sistem dengan beberapa jenis admin (mis. MINTER_ROLE terpisah dari PAUSER_ROLE).
  • Instalasi lewat package manager standar tiap tooling — npm untuk Hardhat, forge install untuk Foundry — lalu import seperti pustaka biasa.
  • Warisi (is Ownable), jangan salin-tempel kodenya — supaya kalau OpenZeppelin merilis patch keamanan, kamu tinggal npm update, bukan menambal manual di banyak file.

Kenapa tidak menulis sendiri

Pola "hanya pemilik boleh melakukan X" terlihat sepele untuk ditulis sendiri — beberapa baris require(msg.sender == owner). Masalahnya bukan kesulitan menulisnya, tapi risiko kasus tepi yang terlewat: transfer kepemilikan ke address nol yang mengunci kontrak selamanya, race condition saat mengganti pemilik, atau lupa event saat kepemilikan berpindah. OpenZeppelin sudah menangani semua kasus tepi itu, dan kodenya sudah dibaca ribuan auditor sebelum kamu.

Instalasi

# Hardhat
npm install @openzeppelin/contracts

# Foundry
forge install OpenZeppelin/openzeppelin-contracts

Ownable — satu pemilik

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "@openzeppelin/contracts/access/Ownable.sol";

contract GoldToken is Ownable {
    constructor(address pemilikAwal) Ownable(pemilikAwal) {}

    function mintGold(address ke, uint256 jumlah) external onlyOwner {
        // hanya pemilik yang lolos modifier onlyOwner
    }
}

Ownable menyediakan onlyOwner, owner(), transferOwnership(address baru), dan renounceOwnership() — lengkap dengan perlindungan terhadap transfer ke address(0) yang bisa mengunci kontrak permanen tanpa pemilik.

AccessControl — banyak role

Begitu sistemmu butuh lebih dari satu jenis admin — misalnya tim operasional yang boleh mint tapi tidak boleh mengubah parameter kontrak — Ownable jadi terlalu sempit. AccessControl menyediakan role sebagai bytes32, dan satu address bisa memegang beberapa role sekaligus.

import "@openzeppelin/contracts/access/AccessControl.sol";

contract GoldToken is AccessControl {
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");

    constructor(address admin) {
        _grantRole(DEFAULT_ADMIN_ROLE, admin);   // role bawaan: bisa grant/revoke role lain
        _grantRole(MINTER_ROLE, admin);
    }

    function mintGold(address ke, uint256 jumlah) external onlyRole(MINTER_ROLE) {
        // logika mint
    }

    function jeda() external onlyRole(PAUSER_ROLE) {
        // logika jeda
    }
}
OwnableAccessControl
Jumlah "jenis" adminSatuSebanyak role yang kamu definisikan
Satu address, banyak peran?Tidak relevan — cuma ada satu peranYa, lewat grantRole berulang
Cabut akses satu peran sajaTidak bisa — harus ganti pemilik seutuhnyarevokeRole(MINTER_ROLE, address)
KompleksitasRendahSedang — perlu memikirkan hierarki role

Warisi, jangan salin-tempel. Kalau kamu menyalin kode Ownable.sol ke proyekmu lalu mengedit-editnya, kamu kehilangan manfaat terbesarnya: saat OpenZeppelin merilis versi baru yang menambal bug keamanan, proyek yang memakai import + npm update langsung mendapat perbaikannya. Proyek yang menyalin kode harus menemukan sendiri bug itu, lalu menambalnya sendiri.

Latihan: ubah kontrak Sertifikat dari dua materi sebelumnya supaya mewarisi AccessControl dengan dua role: PENERBIT_ROLE (boleh terbitkan()) dan DEFAULT_ADMIN_ROLE (boleh grantRole/revokeRole). Deploy di Remix, beri satu address lain PENERBIT_ROLE, lalu buktikan address itu bisa terbitkan() tanpa pernah menjadi "owner" tunggal.

Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.