Sopimusten tietoturvan parhaat käytännöt
Tutustu älysopimusten kehityksen keskeisiin tietoturvakäytäntöihin, kuten uudelleenkutsusuojauksiin, checks-effects-interactions-malliin ja käyttöoikeuksien hallintaan.
Sopimusten tietoturvan parhaat käytännöt on ilmainen Web3:n ja DApp-sovellusten kehityksen perusteet-oppitunti CoddyKitissä. Tämä on oppitunti 2/3. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu Web3:n ja DApp-sovellusten kehityksen perusteet-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Web3:n ja DApp-sovellusten kehityksen perusteet-kurssilla on yhteensä 3 oppituntia.
Älysopimusten tietoturvan perusteet
Tervetuloa älysopimusten tietoturvan kriittiseen maailmaan! Toisin kuin perinteisessä ohjelmistossa, älysopimusten virheet voivat johtaa varojen peruuttamattomaan menettämiseen.
Koska älysopimuksia ei voi muuttaa käyttöönoton jälkeen, haavoittuvuuksien korjaaminen on erittäin vaikeaa. Se edellyttää usein monimutkaisia päivitysmekanismeja tai jopa uuden sopimuksen käyttöönottoa.
Tässä oppitunnissa tutustumme keskeisiin käytäntöihin, joiden avulla rakennetaan turvallisempia ja vankempia älysopimuksia.
Uudelleenkutsun ymmärtäminen
Yksi tunnetuimmista haavoittuvuuksista on uudelleenkutsu (reentrancy). Se syntyy, kun ulkoinen kutsu toiseen sopimukseen tai osoitteeseen "palaa" kutsuvaan sopimukseen ennen kuin alkuperäisen funktion tilapäivitykset on tehty.
Kuvittele pankkiautomaatti, josta voi nostaa rahaa. Jos se veloittaa tililtäsi vasta *sen jälkeen*, kun se on antanut rahat, uudelleenkutsuhyökkäys vastaisi sitä, että pyytäisit rahaa toistuvasti ennen kuin järjestelmä päivittää saldosi ja tyhjentäisit automaatin.
Haavoittuva nostokoodi
Tarkastellaan tätä yksinkertaistettua sopimusta, jossa käyttäjä voi tallettaa ja nostaa Etheriä. Huomaatko vaaran?
withdraw()-funktio lähettää ensin Etherin ja päivittää sitten saldon. Hyökkääjä voi kutsua withdraw()-funktiota uudelleen haitallisesta sopimuksestaan ulkoisen kutsun aikana, ennen kuin hänen saldokseen asetetaan nolla.
/// 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;
}
}Uudelleenkutsujen estäminen: tilalukot
Yleinen ja tehokas tapa estää uudelleenkutsut on käyttää uudelleenkutsusuojaa (reentrancy guard). Siinä sopimuksen tila lukitaan ulkoisen kutsun ajaksi ja avataan sen jälkeen.
Jos uudelleenkutsuva kutsu yrittää suorittaa lukitun funktion, se kumoutuu. OpenZeppelinin ReentrancyGuard on suosittu toteutus, mutta voit rakentaa myös yksinkertaisen suojan itse.
Uudelleenkutsusuojan toteuttaminen
Lisätään yksinkertainen uudelleenkutsusuoja totuusarvomuuttujan avulla. Näin varmistetaan, ettei withdraw-funktiota voi kutsua uudelleen ennen nykyisen suorituksen päättymistä ja tilan päivittämistä.
nonReentrant-muokkain asettaa lukituksen, suorittaa toiminnon ja vapauttaa sitten lukituksen.
/// 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;
}
}CEI-malli
Checks-Effects-Interactions (CEI) -malli on keskeinen tietoturvan parhaiden käytäntöjen mukainen toimintatapa. Se määrittää funktiossa suoritettavien toimien järjestyksen:
- Checks: Tarkista ehdot (esimerkiksi
require-lauseet jaonlyOwner). - Effects: Päivitä sopimuksen tila (esimerkiksi
balances[msg.sender] -= amount). - Interactions: Tee ulkoisia kutsuja muihin sopimuksiin tai osoitteisiin.
CEI-mallin noudattaminen auttaa estämään erilaisia hyökkäyksiä, kuten uudelleenkutsuja, koska se varmistaa sopimuksen tilan viimeistelyn *ennen* ulkoisia kutsuja.
CEI nostofunktiossa
Huomaa, kuinka SecureBank-sopimuksemme withdraw-funktio noudattaa jo CEI-mallia:
- Checks: Muokkaimen
require(balances[msg.sender] >= _amount, ...)jarequire(!_locked, ...). - Effects:
balances[msg.sender] -= _amount;päivittää tilan. - Interactions:
msg.sender.call{value: _amount}("");suorittaa ulkoisen siirron.
Tämä järjestys on ratkaisevan tärkeä uudelleenkutsujen estämiseksi ja tilan johdonmukaisuuden varmistamiseksi.
/// 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");
}
}Käyttöoikeuksien rajoittaminen
Kaikkien ei pitäisi voida kutsua kaikkia älysopimuksen funktioita. Käyttöoikeuksien hallinta varmistaa, että vain valtuutetut osoitteet tai roolit voivat suorittaa tiettyjä arkaluonteisia toimintoja.
Yleisiä esimerkkejä ovat:
onlyOwner-muokkain hallinnollisia toimintoja varten.- Roolipohjainen käyttöoikeuksien hallinta (RBAC), jossa eri rooleilla (esimerkiksi
MINTERjaPAUSER) on tietyt käyttöoikeudet.
Asianmukainen käyttöoikeuksien hallinta on välttämätöntä luvattomien toimien estämiseksi ja sopimuksen eheyden säilyttämiseksi.
Omistajalle rajoitettu funktio
Näin toteutetaan yksinkertainen onlyOwner-käyttöoikeuksien hallinta muokkaimen avulla. Sopimus tallentaa käyttöönottajan osoitteen owner-muuttujaan, ja vain tämä osoite voi kutsua setNewAdmin-funktiota.
Tätä mallia käytetään laajasti kriittisissä hallinnollisissa toiminnoissa.
/// 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;
}
}Tietoturvan parhaiden käytäntöjen testi
Olette oppineet uudelleenkutsuista, CEI-mallista ja käyttöoikeuksien hallinnasta. Mitkä seuraavista väitteistä pitävät paikkansa turvallisessa älysopimuskehityksessä?
Kertaus: turvalliset sopimukset
Hienoa työtä! Olette oppineet älysopimusten tietoturvan keskeiset käytännöt:
- Uudelleenkutsu: Kriittinen haavoittuvuus, jossa ulkoiset kutsut voivat "palata" funktioon ennen tilapäivityksiä.
- Uudelleenkutsusuojat: Mekanismit, kuten mutex-lukot tai muokkaimet, joilla sopimuksen tila lukitaan ulkoisten kutsujen ajaksi.
- CEI-malli: Suositeltu toimintojen järjestys (Checks, Effects, Interactions), jolla varmistetaan tilan päivittäminen ennen ulkoisia kutsuja.
- Käyttöoikeuksien hallinta: Arkaluonteisten funktioiden rajoittaminen valtuutetuille osoitteille, usein
onlyOwner-muokkaimilla.
Nämä käytännöt ovat ratkaisevan tärkeitä vankkojen ja luotettavien hajautettujen sovellusten rakentamisessa. Jatkakaa harjoittelua ja pysykää valppaina!
Opi Web3:n ja DApp-sovellusten kehityksen perusteet tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 29
- Oppitunnit
- 105
Usein kysytyt kysymykset
Onko oppitunti ”Sopimusten tietoturvan parhaat käytännöt” ilmainen?
Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa Web3:n ja DApp-sovellusten kehityksen perusteet-oppimispolun 3 oppituntia, myös oppitunnin “Sopimusten tietoturvan parhaat käytännöt”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Web3:n ja DApp-sovellusten kehityksen perusteet-kurssilla on yhteensä 3 oppituntia.
Mitä opin oppitunnilla ”Sopimusten tietoturvan parhaat käytännöt”?
Tutustu älysopimusten kehityksen keskeisiin tietoturvakäytäntöihin, kuten uudelleenkutsusuojauksiin, checks-effects-interactions-malliin ja käyttöoikeuksien hallintaan. Harjoittelet Web3:n ja DApp-sovellusten kehityksen perusteet-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni Web3:n ja DApp-sovellusten kehityksen perusteet-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin Web3:n ja DApp-sovellusten kehityksen perusteet-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 2/3.
Kuinka kauan ”Sopimusten tietoturvan parhaat käytännöt”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä Web3:n ja DApp-sovellusten kehityksen perusteet-oppitunnilla?
Kyllä. Jokainen Web3:n ja DApp-sovellusten kehityksen perusteet-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- ERC-standardit (ERC-20, ERC-721)
- Sopimusten tietoturvan parhaat käytännöt
- Päivitettävät sopimukset