Smarta blockkedjekontrakt med Solidity · Lektion

Vanliga sårbarheter (reentrancy med mera)

Förstå och motverka vanliga sårbarheter i smarta kontrakt, till exempel reentrancy, heltalsöverflöden och underflöden samt front-running-attacker.

Lektion 1 av 412 steg

Vanliga sårbarheter (reentrancy med mera) är en gratis lektion i Smarta blockkedjekontrakt med Solidity på CoddyKit. Detta är lektion 1 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för Smarta blockkedjekontrakt med Solidity, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Smarta blockkedjekontrakt med Solidity innehåller totalt 4 lektioner.

Säkerhet för smarta kontrakt: översikt

Välkommen till denna viktiga lektion om säkerhet för smarta kontrakt! Till skillnad från traditionell programvara kan buggar i smarta kontrakt leda till oåterkalleliga förluster av tillgångar.

Eftersom kontrakt på blockkedjan ofta är oföränderliga är det oerhört svårt, om inte omöjligt, att åtgärda sårbarheter efter distributionen. Säkerhet måste vara högsta prioritet från första dagen.

Förstå återinträdesattacker

Återinträde är en kritisk sårbarhet där ett externt anrop till ett opålitligt kontrakt kan återgå till det ursprungliga kontraktet innan det första funktionsanropet har slutförts.

Detta gör det möjligt för angriparen att upprepade gånger tömma tillgångar eller manipulera tillståndet genom att anropa den sårbara funktionen flera gånger.

Återinträde: Ett sårbart exempel

Betrakta detta förenklade uttagskontrakt. Kan du upptäcka det potentiella problemet?

Tillståndet (balances[msg.sender]) uppdateras *efter* det externa anropet till msg.sender.call. Denna fördröjning skapar ett utrymme för en attack.

pragma solidity ^0.8.0;

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

  constructor() payable {
    // Fund contract for demo purposes
  }

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

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

    // External call FIRST, state update LATER
    (bool success, ) = msg.sender.call{value: _amount}("");
    require(success, "Transfer failed");

    balances[msg.sender] -= _amount; // This line is vulnerable!
  }

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

Så går återinträdesattacken till

Så här utnyttjar en angripare det föregående kontraktet:

  • 1. Insättning: Angriparen sätter in tillgångar i VulnerableWithdraw.
  • 2. Uttag: Angriparen anropar withdraw(amount).
  • 3. Återinträde: När msg.sender.call överför Ether till angriparen aktiveras dennes skadliga fallback-funktion.
  • 4. Upprepning: Fallback-funktionen anropar omedelbart withdraw(amount) igen, innan det ursprungliga anropet uppdaterar saldot. Detta upprepas tills tillgångarna är tömda.

Förhindra återinträde: Lösningen

Det effektivaste sättet att förhindra återinträde är att följa mönstret Checks-Effects-Interactions (CEI):

  • 1. Checks: Kontrollera alla villkor, till exempel require-satser.
  • 2. Effects: Uppdatera alla tillståndsvariabler, till exempel balances[msg.sender] -= _amount.
  • 3. Interactions: Gör externa anrop, till exempel msg.sender.call.

Detta säkerställer att tillståndet uppdateras *innan* opålitlig extern kod kan köras.

Återinträde: Det korrigerade kontraktet

Här är den korrigerade versionen av uttagskontraktet, där CEI-mönstret tillämpas. Observera ordningen på operationerna.

Nu minskas saldot *innan* det externa anropet, vilket stänger utrymmet för återinträde.

pragma solidity ^0.8.0;

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

  constructor() payable {
    // Fund contract for demo purposes
  }

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

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

    // 2. Effects: Update state BEFORE external call
    balances[msg.sender] -= _amount;

    // 3. Interactions: Make external call LAST
    (bool success, ) = msg.sender.call{value: _amount}("");
    require(success, "Transfer failed");
  }

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

Heltalsöverflöden och heltalsunderflöden

Heltalsöverflöden inträffar när en aritmetisk operation resulterar i ett värde som är större än det maximala värdet som variabeltypen kan lagra. Värdet 'slår runt' till sitt minsta värde.

Heltalsunderflöden är motsatsen: resultatet är mindre än det minsta värdet och slår runt till det maximala värdet.

En uint8 kan till exempel innehålla värden från 0 till 255. Om värdet är 255 och du adderar 1 blir det 0 (överflöde). Om värdet är 0 och du subtraherar 1 blir det 255 (underflöde).

Exempel på överflöde och underflöde

Före Solidity 0.8.0 slog dessa operationer tyst runt. Sedan Solidity 0.8.0 kontrolleras aritmetiska operationer som standard med avseende på överflöden och underflöden, och operationen återställs om ett sådant inträffar.

Det är ändå viktigt att förstå konceptet, särskilt när du arbetar med äldre kodbaser eller använder unchecked-block för gasoptimering.

pragma solidity ^0.8.0;

contract MathVulnerabilities {
  uint8 public smallNumber = 255; // Max for uint8

  function triggerOverflow() public {
    // In Solidity 0.8.0+, this transaction will revert.
    // In older versions, smallNumber would become 0.
    smallNumber = smallNumber + 1;
  }

  function triggerUnderflow() public {
    smallNumber = 0; // Reset for demo
    // In Solidity 0.8.0+, this transaction will revert.
    // In older versions, smallNumber would become 255.
    smallNumber = smallNumber - 1;
  }
}

Front-running-attacker

Front-running är en attack där en angripare observerar en väntande transaktion och skickar in en egen transaktion med högre gasavgift för att få den körd först.

Detta är vanligt inom DeFi (decentraliserad finans), där transaktioner som stora byten eller likvideringar kan förutses och utnyttjas för att skapa vinst.

Förhindra front-running

Det är svårt att förhindra front-running på grund av mempoolens offentliga natur (poolen med väntande transaktioner). Det finns dock några strategier:

  • Commit-reveal-scheman: Användare skickar in en hashad version av sin avsikt (commit) och avslöjar sedan de faktiska uppgifterna.
  • Batchning: Transaktioner grupperas för att minska synligheten för enskilda transaktioner.
  • Decentraliserade sequencers/L2-lösningar: Lösningar används som erbjuder mer privat eller kontrollerad ordning för transaktioner.
  • Slippagekontroll: Användare anger den högsta accepterade prisförändringen för byten.

Sårbarhetskontroll

Du har lärt dig om tre stora sårbarheter i smarta kontrakt. Nu testar vi dina kunskaper!

Sammanfattning: Säkerheten först

I den här lektionen gick vi igenom kritiska sårbarheter i smarta kontrakt: återinträde, heltalsöverflöden och heltalsunderflöden samt front-running.

  • Vi såg hur återinträde utnyttjar externa anrop och hur mönstret Checks-Effects-Interactions ger ett robust skydd.
  • Vi förstod hur heltalsaritmetik kan leda till oväntade värden och hur viktigt det är med kompilatorkontroller (Solidity 0.8.0+).
  • Slutligen diskuterade vi front-running och metoder som commit-reveal för att begränsa det.

Prioritera alltid säkerheten när du utvecklar smarta kontrakt!

Gratis att börja

Lär dig Smarta blockkedjekontrakt med Solidity med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
12
Lektioner
48

Vanliga frågor

Är lektionen ”Vanliga sårbarheter (reentrancy med mera)” gratis?

Ja – hela texten till ”Vanliga sårbarheter (reentrancy med mera)” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i Smarta blockkedjekontrakt med Solidity, kan Ni uppgradera till CoddyKit PRO. Kursen i Smarta blockkedjekontrakt med Solidity innehåller totalt 4 lektioner.

Vad lär jag mig i ”Vanliga sårbarheter (reentrancy med mera)”?

Förstå och motverka vanliga sårbarheter i smarta kontrakt, till exempel reentrancy, heltalsöverflöden och underflöden samt front-running-attacker. Ni övar på Smarta blockkedjekontrakt med Solidity med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig Smarta blockkedjekontrakt med Solidity?

Du behöver inga förkunskaper. Utbildningen i Smarta blockkedjekontrakt med Solidity på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 1 av 4.

Hur lång tid tar lektionen ”Vanliga sårbarheter (reentrancy med mera)”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här Smarta blockkedjekontrakt med Solidity-lektionen?

Ja. Varje Smarta blockkedjekontrakt med Solidity-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Vanliga sårbarheter (reentrancy med mera)
  2. Mönster för åtkomstkontroll
  3. Säker kodning med SafeMath
  4. Granskning, testning och bug bounty-program
← Tillbaka till Smarta blockkedjekontrakt med Solidity