Analise smart-contract
07.08.2024

Comprendere gli errori comuni dei contratti smart ERC-20 in Solidity

I contratti intelligenti nell'ecosistema Ethereum spesso contengono logiche complesse per garantire la sicurezza e la funzionalità delle applicazioni decentralizzate. Tuttavia, possono sorgere errori per vari motivi, portando a transazioni fallite e potenziali vulnerabilità. Questo post del blog esplorerà alcuni errori comuni riscontrati nelle transazioni di token ERC-20, le loro cause e soluzioni.

1. Pancake: K

L'errore si verifica se viene violata l'invarianza 'il prodotto delle riserve deve essere costante'. Questa condizione garantisce che dopo l'esecuzione dello swap, il nuovo prodotto delle riserve (comprese le commissioni) non sarà inferiore al vecchio prodotto. Una violazione di questa condizione può verificarsi se:

  1. I token immessi nella pool (amount0In o amount1In) non corrispondono ai valori previsti secondo la formula dell'invarianza. C'è stato un errore nel calcolo dei saldi dopo lo swap.
  2. Qualcuno ha cercato di manipolare la pool, il che ha causato cambiamenti nei saldi dei token, eludendo il processo di swap standard.
  3. Se questa condizione non è soddisfatta, viene sollevato l'errore ‘Pancake: K’, segnalando una violazione dell'invarianza matematica.

Una violazione dell'invarianza significa che una delle condizioni fondamentali che garantiscono il corretto funzionamento del sistema non è più rispettata. Nel contesto degli scambi decentralizzati come PancakeSwap, l'invarianza è solitamente associata a un'equazione matematica che deve rimanere vera per mantenere l'equilibrio tra le riserve di token nella pool di liquidità.


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

Soluzione:
Controlla che la pool abbia liquidità sufficiente per effettuare lo scambio e che i valori non superino le riserve (_reserve0, _reserve1). Monitora continuamente le riserve della pool e adotta misure per reintegrarle se necessario.

2. TransferHelper: TRANSFER_FROM_FAILED

Questo errore indica un trasferimento di token fallito utilizzando il metodo safeTransferFrom, che è un modello comune per trasferire in modo sicuro i token ERC-20.


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');
  }

Cause:

  1. L'indirizzo from non ha concesso o non ha concesso abbastanza permessi per l'indirizzo msg.sender per trasferire i token (allowance, approve).
  2. L'indirizzo from non ha abbastanza token per effettuare il trasferimento. Questo può essere dovuto anche al fatto che gli amministratori del token hanno la possibilità di modificare il saldo del token e al momento del prelievo l'utente che ha effettuato l' investimento potrebbe non avere abbastanza saldo per eseguire il prelievo.
  3. Il contratto del token potrebbe non implementare la funzione transferFrom o implementarla in modo errato.
  4. Il contratto del token potrebbe contenere controlli o restrizioni aggiuntive nella funzione transferFrom, che possono causare l'annullamento della transazione.
  5. Se non c'è abbastanza gas per eseguire la transazione, la transazione potrebbe fallire.

Soluzione:

  1. Assicurati che l'indirizzo from abbia concesso abbastanza allowance per msg.sender. Questo può essere fatto chiamando la funzione allowance del contratto del token.
  2. Assicurati che l'indirizzo from abbia abbastanza token per effettuare il trasferimento.
  3. Verifica che l'indirizzo del contratto del token sia corretto e che il contratto sia conforme agli standard ERC-20.
  4. Controlla l'implementazione della funzione transferFrom nel contratto del token. Assicurati che sia implementata correttamente e che non ci siano vincoli aggiuntivi che potrebbero causare un fallimento.
  5. Prova ad aumentare il limite di gas quando chiami la transazione per assicurarti che il problema non sia dovuto alla mancanza di gas.

3. INSUFFICIENT_LIQUIDITY

Questo errore si verifica quando si tenta di prelevare più liquidità di quella disponibile nelle riserve di una pool di liquidità.


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

Cause:

  1. La pool di liquidità non contiene una quantità sufficiente di uno o entrambi i token per soddisfare lo scambio richiesto.
  2. La quantità richiesta di token per il prelievo (amount0Out o amount1Out) supera il numero disponibile di token nella pool.
  3. Disallineamento tra le riserve nel contratto e lo stato reale della pool. Le riserve memorizzate nel contratto potrebbero non corrispondere al saldo reale dei token nella pool a causa di errori o manipolazioni.

Soluzione:

  1. Controlla le riserve della pool e assicurati che siano sufficienti per soddisfare lo scambio richiesto. Questo può essere fatto utilizzando la funzione getReserves.
  2. Assicurati che i parametri amount0Out e amount1Out siano corretti e non superino il numero disponibile di token nella pool.
  3. Assicurati che le riserve nel contratto corrispondano al saldo reale dei token. Per fare ciò, puoi aggiungere controlli e aggiornamenti delle riserve prima di effettuare lo scambio.

INSUFFICIENT_LIQUIDITY

4. APPROVE_FAILED

L'errore `APPROVE_FAILED` si verifica durante l'esecuzione della funzione `safeApprove`. Questa funzione è progettata per impostare l'importo di token che un proprietario consente a un spender di utilizzare per conto suo.


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');
}

Cause:

  1. Il contratto del token potrebbe non avere la funzione `approve` o potrebbe essere implementata in modo errato.
  2. Potrebbe esserci un problema con lo stato del contratto del token, come saldo insufficiente o allowance.
  3. La funzione `approve` potrebbe revertire per motivi di sicurezza implementati nel contratto del token.

Soluzione:

  1. Assicurati che il contratto del token sia conforme allo standard ERC-20 e includa una funzione `approve` implementata correttamente.
  2. Controlla lo stato del contratto del token e assicurati che l'account abbia abbastanza token da approvare.
  3. Verifica che l'indirizzo e l'importo passati alla funzione `safeApprove` siano corretti.
  4. Debugga ulteriormente controllando il messaggio di errore specifico o il motivo del revert nel contratto del token.

5. Fallimento con errore 'ds-math-sub-underflow'

L'errore `ds-math-sub-underflow` viene sollevato quando un'operazione di sottrazione produce un underflow, cioè quando il risultato della sottrazione è inferiore a zero.


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

Cause:
Questo errore si verifica perché l'operazione di sottrazione `x - y` produce un numero negativo, che non è consentito per gli interi senza segno in Solidity.

Soluzione:

  1. Assicurati che il valore di `y` sia sempre inferiore o uguale a `x` prima di eseguire la sottrazione.
  2. Implementa controlli nel tuo codice per gestire i casi in cui `y` potrebbe essere maggiore di `x` e adotta le azioni appropriate, come revertire la transazione o modificare la logica.

6. Errore 'ERC20: transfer amount exceeds allowance'

L'errore `ERC20: transfer amount exceeds allowance` si verifica quando si tenta di trasferire token per conto di un altro utente, ma l'importo trasferito supera il limite di autorizzazione che il proprietario del token ha impostato per lo spender.

Causa:
Questo errore viene sollevato dalla funzione `transferFrom` del contratto del token ERC-20 quando l'importo da trasferire è superiore al limite autorizzato impostato dal proprietario del token.

Soluzione:

  1. Assicurati che il proprietario del token abbia impostato un'adeguata autorizzazione per lo spender utilizzando la funzione `approve`.
  2. Controlla l'autorizzazione attuale prima di tentare l'operazione `transferFrom`.
  3. Se necessario, chiedi al proprietario del token di aumentare l'autorizzazione chiamando la funzione `approve` con un valore più alto.

7. TRANSFER_FAILED

Questo errore si verifica quando il trasferimento di token da un indirizzo a un altro fallisce. La funzione `_safeTransfer` garantisce che l'operazione di trasferimento abbia successo e che i dati restituiti, se presenti, decodificano in `true`.


    `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'); }`

Causa:

  1. La funzione `token.call` non viene eseguita con successo (cioè, `success` è `false`).
  2. La chiamata restituisce dati che non si decodificano in `true`, indicando un fallimento nella funzione `transfer` del contratto del token.

Soluzione:

  1. Assicurati della conformità all'ERC-20: Verifica che il contratto del token rispetti lo standard ERC-20, che include l'implementazione corretta della funzione `transfer`.
  2. Parametri corretti: Assicurati che l'indirizzo `to` sia valido e che il valore sia entro i limiti consentiti, considerando il saldo del mittente e la logica del contratto.
  3. Condizioni aggiuntive: Verifica se il contratto del token richiede condizioni aggiuntive, come l'approvazione preventiva dell'importo speso (funzioni `approve` e `allowance`).

INSUFFICIENT_LIQUIDITY

8. INSUFFICIENT_OUTPUT_AMOUNT

Questo errore si verifica in un contesto di scambio decentralizzato quando l'importo di output di uno swap di token è inferiore all'importo minimo specificato dall'utente. Questo è un meccanismo di protezione per garantire che gli utenti non ricevano meno token di quanto previsto a causa di slippage o variazioni di prezzo durante la transazione.


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

Causa:

  1. La volatilità del mercato influisce sui prezzi dei token tra il momento in cui la transazione è avviata e quando viene eseguita.
  2. Impostazioni di slippage elevate, che permettono deviazioni significative negli output previsti.
  3. Liquidità insufficiente nella pool di trading, causando impatti di prezzo maggiori.

Soluzione:

  1. Assicurati della conformità all'ERC-20: Verifica che il contratto del token rispetti lo standard ERC-20, che include l'implementazione corretta della funzione `transfer`.
  2. Parametri corretti: Assicurati che l'indirizzo `to` sia valido e che il valore sia entro i limiti consentiti, considerando il saldo del mittente e la logica del contratto.
  3. Condizioni aggiuntive: Verifica se il contratto del token richiede condizioni aggiuntive, come l'approvazione preventiva dell'importo speso (funzioni `approve` e `allowance`).

9. INSUFFICIENT_INPUT_AMOUNT

Questo errore si verifica quando nessuno degli importi di input per uno swap di token è maggiore di zero. Assicura che almeno uno degli importi di input (`amount0In` o `amount1In`) sia positivo per procedere con lo swap.


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

Causa:

  1. Parametri di input errati per la funzione di swap.
  2. Fondini insufficienti nel conto dell'utente.
  3. Errori nella logica che calcola gli importi di input.

Soluzione:

  1. Valida gli importi di input: Assicurati che gli importi di input siano impostati correttamente prima di invocare la funzione di swap. Questo include la validazione dell'input dell'utente e la configurazione dei parametri.
  2. Controlla i saldi degli utenti: Verifica che l'utente abbia un saldo sufficiente dei token destinati allo swap. Questo può essere fatto chiamando la funzione `balanceOf` dei rispettivi contratti di token.

10. Errore

Causa:

  1. Una transazione non può essere eseguita perché manca di gas sufficiente per completare tutte le operazioni.
  2. Logica o condizioni errate all'interno di un contratto intelligente possono causare il fallimento dell'esecuzione (ad esempio, una chiamata a `require` o `assert` che fallisce).
  3. Tentativo di eseguire una transazione di token o criptovaluta quando il saldo del conto è insufficiente.
  4. Nel caso di token standard ERC-20 ed ERC-721, la transazione potrebbe fallire a causa di autorizzazioni insufficienti.
  5. Una chiamata a un contratto intelligente potrebbe essere annullata a causa del mancato soddisfacimento delle condizioni al suo interno (ad esempio, utilizzando la funzione `revert`).

Soluzione:

  1. Aumenta il limite di gas quando invii la transazione.
  2. Controlla le condizioni e la logica all'interno del contratto intelligente.
  3. Assicurati che il conto abbia fondi sufficienti per completare la transazione.
  4. Chiama la funzione `approve` con un valore sufficiente prima di chiamare `transferFrom`.
  5. Controlla le condizioni che causano l'annullamento della transazione.
  6. Controlla il tuo saldo per le commissioni.

Conclusione

Comprendere e risolvere questi errori comuni nei contratti intelligenti ERC-20 richiede una solida conoscenza della programmazione Solidity, dello standard ERC-20 e del funzionamento interno degli scambi decentralizzati. Esaminando attentamente le cause e implementando le soluzioni suggerite, gli sviluppatori possono creare contratti intelligenti più robusti e affidabili, assicurando un'esperienza senza problemi per gli utenti nell'ecosistema decentralizzato.

All posts

Connect to a wallet

Metamask