Asas Pembangunan Web3 & DApp · Pelajaran

Amalan Terbaik Keselamatan Kontrak

Temui amalan keselamatan penting untuk pembangunan kontrak pintar, termasuk pengawal kemasukan semula, corak semakan-kesan-interaksi dan kawalan akses.

Pelajaran 2 daripada 311 langkah

Amalan Terbaik Keselamatan Kontrak ialah pelajaran Asas Pembangunan Web3 & DApp percuma di CoddyKit. Ini ialah pelajaran 2 daripada 3. Sebanyak 3 pelajaran dalam laluan pembelajaran ini boleh dibaca sepenuhnya secara percuma — selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan praktikal dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Asas Pembangunan Web3 & DApp, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Asas Pembangunan Web3 & DApp merangkumi sejumlah 3 pelajaran.

Pengenalan kepada Keselamatan Kontrak Pintar

Selamat datang ke dunia keselamatan kontrak pintar yang penting! Tidak seperti perisian tradisional, pepijat dalam kontrak pintar boleh menyebabkan kehilangan dana yang tidak boleh dipulihkan.

Oleh sebab kontrak pintar tidak boleh diubah selepas digunakan, pembaikan kerentanan amat sukar dan sering memerlukan mekanisme penaiktarafan yang rumit atau penggunaan semula kontrak baharu.

Dalam pelajaran ini, kami akan meneroka amalan penting untuk membina kontrak pintar yang lebih selamat dan kukuh.

Memahami Serangan Kemasukan Semula

Salah satu kerentanan yang paling terkenal ialah kemasukan semula. Ia berlaku apabila panggilan luaran kepada kontrak atau alamat lain "masuk semula" ke dalam kontrak yang memanggilnya sebelum kemas kini keadaan fungsi asal selesai.

Bayangkan sebuah ATM yang membenarkan anda mengeluarkan wang. Jika ATM menolak jumlah daripada akaun anda *selepas* memberikan wang tunai, serangan kemasukan semula adalah seperti meminta wang tunai berulang kali sebelum sistem mengemas kini baki anda, sehingga mengosongkan ATM.

Kod Pengeluaran yang Rentan

Pertimbangkan kontrak ringkas ini, yang membenarkan pengguna mendeposit dan mengeluarkan Ether. Bolehkah anda mengenal pasti bahayanya?

Fungsi withdraw() mula-mula menghantar Ether, kemudian mengemas kini baki. Penyerang boleh memanggil withdraw() sekali lagi daripada kontrak berniat jahat mereka semasa panggilan luaran berlangsung, sebelum baki mereka ditetapkan kepada sifar.

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

contract VulnerableBank {
    mapping(address => uint) public balances;

    function deposit() public payable {
        balances[msg.sender] += msg.value;
    }

    function withdraw(uint _amount) public {
        require(balances[msg.sender] >= _amount, "Insufficient balance");

        // Vulnerable point: send Ether BEFORE updating balance
        (bool success, ) = msg.sender.call{value: _amount}("");
        require(success, "Failed to send Ether");

        balances[msg.sender] -= _amount; // This happens AFTER the external call
    }

    function getBalance() public view returns (uint) {
        return address(this).balance;
    }
}

Mencegah Kemasukan Semula: Kunci Keadaan

Cara yang biasa dan berkesan untuk mencegah kemasukan semula ialah menggunakan pengawal kemasukan semula. Cara ini melibatkan penguncian keadaan kontrak semasa panggilan luaran dan membukanya semula selepas itu.

Jika panggilan yang cuba masuk semula cuba melaksanakan fungsi yang dikunci, panggilan itu akan dibatalkan. ReentrancyGuard milik OpenZeppelin ialah pelaksanaan yang popular, tetapi anda juga boleh membina pelaksanaan yang ringkas.

Melaksanakan Pengawal Kemasukan Semula

Mari kita tambahkan pengawal kemasukan semula yang ringkas menggunakan penanda boolean. Ini memastikan fungsi withdraw tidak boleh dipanggil semula sehingga pelaksanaan semasa selesai dan keadaan telah dikemas kini.

Pengubah suai nonReentrant menetapkan kunci, melaksanakan operasi, kemudian melepaskan kunci tersebut.

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

contract SecureBank {
    mapping(address => uint) public balances;
    bool private _locked; // Reentrancy guard flag

    modifier nonReentrant() {
        require(!_locked, "Reentrant call detected");
        _locked = true;
        _;
        _locked = false;
    }

    function deposit() public payable {
        balances[msg.sender] += msg.value;
    }

    function withdraw(uint _amount) public nonReentrant {
        require(balances[msg.sender] >= _amount, "Insufficient balance");

        balances[msg.sender] -= _amount; // Update balance BEFORE external call (CEI)

        (bool success, ) = msg.sender.call{value: _amount}("");
        require(success, "Failed to send Ether");
    }

    function getBalance() public view returns (uint) {
        return address(this).balance;
    }
}

Corak CEI

Corak Checks-Effects-Interactions (CEI) ialah amalan terbaik keselamatan yang asas. Corak ini menetapkan susunan khusus untuk operasi dalam sesuatu fungsi:

  • Checks: Sahkan syarat (contohnya, pernyataan require, onlyOwner).
  • Effects: Kemas kini keadaan kontrak (contohnya, balances[msg.sender] -= amount).
  • Interactions: Lakukan panggilan luaran kepada kontrak atau alamat lain.

Mematuhi CEI membantu mencegah pelbagai serangan, termasuk kemasukan semula, dengan memastikan keadaan kontrak dimuktamadkan *sebelum* panggilan luaran.

CEI dalam Fungsi Pengeluaran

Perhatikan bahawa fungsi withdraw milik SecureBank kita sudah mengikuti corak CEI:

  • Checks: require(balances[msg.sender] >= _amount, ...) dan require(!_locked, ...) daripada pengubah suai.
  • Effects: balances[msg.sender] -= _amount; mengemas kini keadaan.
  • Interactions: msg.sender.call{value: _amount}(""); melakukan pemindahan luaran.

Susunan ini penting untuk mencegah kemasukan semula dan memastikan keadaan kekal konsisten.

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

contract CEIDemo {
    mapping(address => uint) public balances;
    bool private _locked;

    modifier nonReentrant() {
        require(!_locked, "Reentrant call detected");
        _locked = true;
        _;
        _locked = false;
    }

    function deposit() public payable {
        balances[msg.sender] += msg.value;
    }

    function withdraw(uint _amount) public nonReentrant {
        // --- CHECKS ---
        require(balances[msg.sender] >= _amount, "Insufficient balance");

        // --- EFFECTS ---
        balances[msg.sender] -= _amount; // State updated BEFORE external call

        // --- INTERACTIONS ---
        (bool success, ) = msg.sender.call{value: _amount}("");
        require(success, "Failed to send Ether");
    }
}

Mengehadkan Akses

Tidak semua fungsi dalam kontrak pintar patut boleh dipanggil oleh semua orang. Kawalan akses memastikan hanya alamat atau peranan yang dibenarkan boleh melaksanakan operasi sensitif tertentu.

Contoh yang biasa termasuk:

  • Pengubah suai onlyOwner untuk fungsi pentadbiran.
  • Kawalan akses berasaskan peranan (RBAC), dengan peranan yang berbeza (contohnya, MINTER, PAUSER) mempunyai keizinan khusus.

Kawalan akses yang betul amat penting untuk mencegah tindakan tanpa kebenaran dan mengekalkan integriti kontrak.

Fungsi Terhad kepada Pemilik

Berikut ialah cara melaksanakan kawalan akses onlyOwner yang ringkas menggunakan pengubah suai. Kontrak menyimpan alamat pengguna yang menggunakan kontrak sebagai owner, dan hanya alamat ini boleh memanggil fungsi setNewAdmin.

Corak ini digunakan secara meluas untuk fungsi pentadbiran yang kritikal.

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

contract AccessControlled {
    address public owner;
    address public admin;

    constructor() {
        owner = msg.sender; // Deployer is the owner
        admin = msg.sender;
    }

    modifier onlyOwner() {
        require(msg.sender == owner, "Only owner can call this function");
        _;
    }

    function setNewAdmin(address _newAdmin) public onlyOwner {
        admin = _newAdmin;
    }

    function getAdmin() public view returns (address) {
        return admin;
    }
}

Semakan Amalan Terbaik Keselamatan

Anda telah mempelajari tentang kemasukan semula, corak CEI dan kawalan akses. Antara pernyataan berikut, yang manakah benar berkaitan pembangunan kontrak pintar yang selamat?

Imbas Kembali: Kontrak Selamat

Syabas! Anda telah memahami amalan asas keselamatan kontrak pintar:

  • Kemasukan Semula: Kerentanan kritikal apabila panggilan luaran boleh "masuk semula" ke dalam fungsi sebelum keadaan dikemas kini.
  • Pengawal Kemasukan Semula: Mekanisme seperti mutex atau pengubah suai untuk mengunci keadaan kontrak semasa panggilan luaran.
  • Corak CEI: Susunan operasi yang disyorkan (Checks, Effects, Interactions) untuk memastikan keadaan dikemas kini sebelum panggilan luaran.
  • Kawalan Akses: Mengehadkan fungsi sensitif kepada alamat yang dibenarkan, selalunya menggunakan pengubah suai onlyOwner.

Amalan ini penting untuk membina aplikasi terdesentralisasi yang kukuh dan boleh dipercayai. Teruskan berlatih dan sentiasa berwaspada!

Percuma untuk bermula

Pelajari Asas Pembangunan Web3 & DApp dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
29
Pelajaran
105

Soalan Lazim

Adakah pelajaran “Amalan Terbaik Keselamatan Kontrak” percuma?

Ya — sebanyak 3 pelajaran dalam laluan pembelajaran Asas Pembangunan Web3 & DApp, termasuk “Amalan Terbaik Keselamatan Kontrak”, boleh dibaca sepenuhnya secara percuma di web ini. Selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan interaktif dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Kursus Asas Pembangunan Web3 & DApp merangkumi sejumlah 3 pelajaran.

Apakah yang akan saya pelajari dalam “Amalan Terbaik Keselamatan Kontrak”?

Temui amalan keselamatan penting untuk pembangunan kontrak pintar, termasuk pengawal kemasukan semula, corak semakan-kesan-interaksi dan kawalan akses. Anda berlatih Asas Pembangunan Web3 & DApp menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Asas Pembangunan Web3 & DApp?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Asas Pembangunan Web3 & DApp di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 2 daripada 3.

Berapa lamakah pelajaran “Amalan Terbaik Keselamatan Kontrak” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Asas Pembangunan Web3 & DApp ini?

Ya. Setiap pelajaran Asas Pembangunan Web3 & DApp menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Piawaian ERC (ERC-20, ERC-721)
  2. Amalan Terbaik Keselamatan Kontrak
  3. Kontrak Boleh Dinaik Taraf
← Kembali ke Asas Pembangunan Web3 & DApp