Analise smart-contract
07.08.2024

Üldiste ERC-20 arukate lepingute vigade mõistmine Solidity's

Ethereum'i ökosüsteemi tarkvaralepingud sisaldavad sageli keerulist loogikat, et tagada detsentraliseeritud rakenduste turvalisus ja funktsionaalsus. Siiski võivad erinevatel põhjustel tekkida vead, mis viivad ebaõnnestunud tehinguteni ja potentsiaalsete haavatavusteni. See blogipostitus käsitleb mõningaid levinumaid vigu ERC-20 tokenite tehingutes, nende põhjuseid ja lahendusi.

1. Pancake: K

Viga tekib, kui invariant 'reservide toote peab olema konstantne' on rikutud. See tingimus tagab, et pärast vahetuse teostamist ei ole uue reservide toote (koos komisjonitasudega) väärtus väiksem kui vana toote väärtus. Seda tingimust võib rikkuda, kui:

  1. Kui basseinile sisestatud tokenid (amount0In või amount1In) ei vasta invariantide valemiga oodatud väärtustele. Pärast vahetust tekkis saldo arvutamisel viga.
  2. Keegi üritas basseini manipuleerida, mis põhjustas tokenide saldode muutumise, mööda minnes standardsetest vahetusprotsessidest.
  3. Kui see tingimus ei ole täidetud, tekib 'Pancake: K' viga, mis signaalib matemaatilise invariantide rikkumist.

Invariantide rikkumine tähendab, et üks fundamentaalsetest tingimustest, mis tagab süsteemi õige toimimise, ei ole enam täidetud. Detsentraliseeritud vahetustes, nagu PancakeSwap, on invariant tavaliselt seotud matemaatilise võrrandiga, mis peab jääma tõeks, et säilitada tasakaal tokenite reservide vahel likviidsuse basseinides.


require(balance0Adjusted.mul(balance1Adjusted) >= uint(_reserve0).mul(_reserve1).mul(10000**2), 'Pancake: K');

Lahendus:
Kontrollige, et basseinil oleks piisavalt likviidsust vahetuse tegemiseks ja et väärtused ei ületaks reserve (_reserve0, _reserve1). Jätkake basseinide reservide pidevat jälgimist ja võtke vajadusel meetmeid nende täiendamiseks.

2. TransferHelper: TRANSFER_FROM_FAILED

See viga tähistab ebaõnnestunud tokeni ülekannet, kasutades `safeTransferFrom` meetodit, mis on tavaline muster ERC-20 tokenite turvaliseks edastamiseks.


function safeTransferFrom(address token, address from, address to, uint value) 
  internal {
    // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
    (bool success, bytes memory data) = 
token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
    require(success && (data.length == 0 || abi.decode(data, (bool))), 
'TransferHelper: TRANSFER_FROM_FAILED');
  }

Põhjus:

  1. Aadressilt 'from' ei ole antud või pole antud piisavalt õigusi, et msg.sender saaks tokenite edastamist teostada (allowance, approve).
  2. Aadressilt 'from' ei ole piisavalt tokenit edastamiseks. See võib olla ka tingitud sellest, et tokeni administraatoritel on võimalus tokeni saldo muutmiseks, ja välja võtmisel võib investeerijal puududa piisav saldo väljavõtmiseks.
  3. Tokeni leping ei pruugi rakendada `transferFrom` funktsiooni või rakendab seda valesti.
  4. Tokeni leping võib sisaldada täiendavaid kontrollimisi või piiranguid `transferFrom` funktsioonis, mis võivad põhjustada tehingu tühistamise.
  5. Kui tehingu täitmiseks pole piisavalt gaasi, võib tehing ebaõnnestuda.

Lahendus:

  1. Veenduge, et aadress 'from' oleks andnud piisavalt õigusi msg.sender'ile. Seda saab teha tokeni lepingu `allowance` funktsiooni kutsumisega.
  2. Veenduge, et aadress 'from' omaks piisavalt tokenit, et teostada ülekannet.
  3. Kontrollige, et tokeni lepingu aadress oleks õige ja et leping oleks ERC-20 standardiga kooskõlas.
  4. Kontrollige tokeni lepingu `transferFrom` funktsiooni rakendust. Veenduge, et see on õigesti rakendatud ega sisalda täiendavaid piiranguid, mis võiksid põhjustada ebaõnnestumist.
  5. Proovige suurendada gaasi limiiti, kui kutsute tehingut, et veenduda, et probleem ei ole gaasi puuduses.

3. INSUFFICIENT_LIQUIDITY

See viga tekib, kui proovite välja võtta rohkem likviidsust, kui on saadaval likviidsuse basseinide reservides.


(uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
        require(amount0Out < _reserve0 && amount1Out < _reserve1, 'Pancake:
INSUFFICIENT_LIQUIDITY');

Põhjus:

  1. Likviidsuse bassein ei sisalda piisavalt ühe või mõlema tokeni kogust, et täita nõutud vahetust.
  2. Nõutud tokenite kogus väljavõtmiseks (amount0Out või amount1Out) ületab basseinis saadaval oleva tokenite arvu.
  3. Lepingu reservide ja basseinide tegeliku oleku vahel esinev erinevus. Lepingu salvestatud reservid ei pruugi vastata basseinide tegelikule tokeni saldo olekule vigade või manipuleerimise tõttu.

Lahendus:

  1. Kontrollige basseinide reserve ja veenduge, et need oleksid piisavad nõutud vahetuse täitmiseks. Seda saab teha `getReserves` funktsiooni abil.
  2. Veenduge, et `amount0Out` ja `amount1Out` parameetrid oleksid õiged ega ületaks basseinide saadaval olevate tokenite arvu.
  3. Veenduge, et lepingu reservid vastaksid tegelikule tokeni saldo olekule. Selleks võite lisada kontrollimise ja reservide värskendamise enne vahetuse tegemist.

INSUFFICIENT_LIQUIDITY

4. APPROVE_FAILED

`APPROVE_FAILED` viga tekib `safeApprove` funktsiooni täitmisel. See funktsioon on mõeldud selleks, et määrata tokenite kogus, mille omanik lubab kulutajal enda nimel kasutada.


function safeApprove(address token, address to, uint value) internal {
  (bool success, bytes memory data) = 
token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
  require(success && (data.length == 0 || abi.decode(data, (bool))),
'TransferHelper: APPROVE_FAILED');
}

Põhjus:

  1. Tokeni lepingul ei pruugi olla `approve` funktsiooni või see võib olla valesti rakendatud.
  2. Tokeni lepingu olekus võib olla probleem, nagu piisava saldo või õiguste puudumine.
  3. `approve` funktsioon võib tagastada vea turvakaalutlustel, mis on rakendatud tokeni lepingus.

Lahendus:

  1. Veenduge, et tokeni leping vastaks ERC-20 standardile ja sisaldaks õigesti rakendatud `approve` funktsiooni.
  2. Kontrollige tokeni lepingu olekut ja veenduge, et kontol oleks piisavalt tokenit heakskiitmiseks.
  3. Kontrollige, et `safeApprove` funktsioonile edastatud aadress ja kogus oleksid õiged.
  4. Täiendav tõrkeotsing, kontrollides konkreetset veateadet või tagasilükkamise põhjust tokeni lepingus.

5. Viga 'ds-math-sub-underflow'

`ds-math-sub-underflow` viga visatakse, kui lahutustöötlus alavoolab, st kui lahutuse tulemus on väiksem kui null.


    function sub(uint x, uint y) internal pure returns (uint z) {
      require((z = x - y) <= x, 'ds-math-sub-underflow');
    } 

Põhjus:
See viga tekib, kuna lahutustöötlus `x - y` annab negatiivse numbri, mis ei ole Soliditys lubatud unsigned täisarvude jaoks.

Lahendus:

  1. Veenduge, et `y` väärtus oleks alati väiksem või võrdne `x`-iga enne lahutuse teostamist.
  2. Rakendage oma koodis kontrollid, et käsitleda juhtumeid, kus `y` võib olla suurem kui `x` ja võtke vastavad meetmed, nagu tehingu tagasivõtmine või loogika kohandamine.

6. Viga 'ERC20: ülekande summa ületab lubatud piiri'

Viga 'ERC20: ülekande summa ületab lubatud piiri' tekib siis, kui proovite edastada tokenite summat teise kasutaja nimel, kuid edastatav summa ületab tokeni omaniku määratud lubatud piiri kulutajale.

Põhjus:
See viga visatakse ERC-20 tokeni lepingu `transferFrom` funktsiooni poolt, kui edastatav summa on suurem kui tokeni omaniku määratud lubatud piirmäär.

Lahendus:

  1. Veenduge, et tokeni omanik oleks määranud kulutajale piisava lubatud piiri `approve` funktsiooni abil.
  2. Kontrollige praegust lubatud piiri enne `transferFrom` operatsiooni proovimist.
  3. Kui vajalik, paluge tokeni omanikul suurendada lubatud piiri, kutsudes `approve` funktsiooni suurema väärtusega.

7. TRANSFER_FAILED

See viga tekib siis, kui tokenite edastamine ühelt aadressilt teisele ebaõnnestub. Funktsioon `_safeTransfer` tagab, et edastamise operatsioon õnnestub ja tagastatud andmed, kui neid on, dekodeeruvad `true` väärtuseks.


    `function _safeTransfer(address token, address to, uint value) private { (bool 
    success, bytes memory data) = token.call(abi.encodeWithSelector(SELECTOR, to,
    value)); require(success && (data.length == 0 || abi.decode(data, (bool))),
    'Pancake: TRANSFER_FAILED'); }`

Põhjus:

  1. Funktsioon `token.call` ei täitu edukalt (st `success` on `false`).
  2. Kutsumine tagastab andmed, mis ei dekodeeru `true` väärtuseks, näidates tokeni lepingu `transfer` funktsiooni ebaõnnestumist.

Lahendus:

  1. Veenduge, et tokeni leping vastaks ERC-20 standardile, sealhulgas `transfer` funktsiooni õigele rakendusele.
  2. Kontrollige parameetreid: veenduge, et aadress `to` oleks kehtiv ja väärtus `value` oleks lubatud piirides, arvestades saatja saldo ja lepingu loogikat.
  3. Kontrollige täiendavaid tingimusi: vaadake, kas tokeni leping nõuab täiendavaid tingimusi, nagu kulutamise summa eelnevalt heakskiitmine (`approve` ja `allowance` funktsioonid).

INSUFFICIENT_LIQUIDITY

8. INSUFFICIENT_OUTPUT_AMOUNT

See viga tekib detsentraliseeritud vahetuse kontekstis, kui tokenite vahetuse väljundsumma on väiksem kui kasutaja määratud minimaalne summa. See on turvameede, et tagada, et kasutajad ei saaks vähem tokenite kui nad ootasid, libisemise või hinnamuutuste tõttu tehingu ajal.


    `require(amounts[amounts.length - 1] >= amountOutMin,
    'PancakeRouter: INSUFFICIENT_OUTPUT_AMOUNT');`

Põhjus:

  1. Turuhinna kõikumine mõjutab tokenite hindu tehingu alguse ja täitmise vahel.
  2. Suured libisemise seaded, mis võimaldavad olulisi kõrvalekaldeid oodatud väljundites.
  3. Likviidsuse puudumine kauplemisbasseinis, mis põhjustab suuremaid hinnamõjusid.

Lahendus:

  1. Veenduge, et tokeni leping vastaks ERC-20 standardile, sealhulgas `transfer` funktsiooni õigele rakendusele.
  2. Kontrollige parameetreid: veenduge, et aadress `to` oleks kehtiv ja väärtus `value` oleks lubatud piirides, arvestades saatja saldo ja lepingu loogikat.
  3. Kontrollige täiendavaid tingimusi: vaadake, kas tokeni leping nõuab täiendavaid tingimusi, nagu kulutamise summa eelnevalt heakskiitmine (`approve` ja `allowance` funktsioonid).

9. INSUFFICIENT_INPUT_AMOUNT

See viga tekib, kui kumbki tokenite vahetuse sisend summa ei ole suurem kui null. See tagab, et vähemalt üks sisend summadest (`amount0In` või `amount1In`) on positiivne, et jätkata vahetust.


    uint amount0In = ...; // Input amount of token0
    uint amount1In = ...; // Input amount of token1
    require(amount0In > 0 || amount1In > 0, 'Pancake: INSUFFICIENT_INPUT_AMOUNT');

Põhjus:

  1. Vale sisendparameetrid vahetuse funktsioonile.
  2. Kasumi puudumine kasutaja kontol.
  3. Vead sisendi summade arvutamise loogikas.

Lahendus:

  1. Kontrollige sisend summasid: veenduge, et sisend summad on õigesti seadistatud enne vahetuse funktsiooni kutsumist. See hõlmab kasutaja sisendi valideerimist ja parameetrite seadistamist.
  2. Kontrollige kasutaja saldosid: veenduge, et kasutajal on piisav saldo vahetuse jaoks mõeldud tokenite kohta. Seda saab teha, kutsudes vastava tokeni lepingu `balanceOf` funktsiooni.

10. Viga

Põhjus:

  1. Tehingut ei saa täita, kuna selleks puudub piisavalt gaasi kõigi operatsioonide lõpuleviimiseks.
  2. Vale loogika või tingimused nutilepingus võivad põhjustada täitmise ebaõnnestumise (näiteks `require` või `assert` funktsiooni ebaõnnestumine).
  3. Proovimine täita tokeni või krüptovaluuta tehingut, kui konto saldo on ebapiisav.
  4. Kui töötate ERC-20 ja ERC-721 standardi tokenitega, võib tehing ebaõnnestuda piisava lubade puudumise tõttu.
  5. Nutilepingu kutsumine võib tagasi lükata, kui tingimusi ei täideta (näiteks `revert` funktsiooni kasutamine).

Lahendus:

  1. Suurendage tehingu saatmisel gaasi limiiti.
  2. Kontrollige nutilepingu tingimusi ja loogikat.
  3. Veenduge, et kontol oleks piisavalt vahendeid tehingu täitmiseks.
  4. Kutsuge `approve` funktsioon piisava väärtusega enne `transferFrom` funktsiooni kutsumist.
  5. Kontrollige tingimusi, mis põhjustavad tehingu tagasi lükkamise.
  6. Kontrollige oma saldo komisjonitasude jaoks.

Kokkuvõte

Nende levinud vigade mõistmine ja lahendamine ERC-20 nutilepingutes nõuab kindlat arusaamist Solidity programmeerimisest, ERC-20 standardist ja detsentraliseeritud vahetuste sisemistest toimimisest. Põhjalik probleemide põhjuste ülevaatus ja soovitatud lah enduste rakendamine aitavad arendajatel luua tugevamaid ja usaldusväärsemaid nutilepinguid, tagades sujuva kogemuse kasutajatele detsentraliseeritud ökosüsteemis.

All posts

Connect to a wallet

Metamask