Rapporto di audit del contratto intelligente per Dusa

Sommario di gestione

Dusa ha contattato Sayfer per eseguire un controllo di sicurezza sui loro contratti intelligenti. 

Questo rapporto documenta la ricerca condotta da Sayfer mirata alle risorse selezionate definite nell'ambito della ricerca. In particolare, questo rapporto mostra la revisione della posizione di sicurezza per i contratti intelligenti di Dusa.

Nel corso di un periodo di ricerca di 4 settimane, abbiamo scoperto 17 vulnerabilità nel contratto.

Nel complesso, Dusa è un protocollo ben costruito. Il fatto che sia derivato e tradotto da TraderJoe lo rende un protocollo molto solido con un'architettura abbastanza comune, ma considerata ottimale. Tuttavia, abbiamo alcune raccomandazioni che riteniamo potrebbero migliorare la qualità e la sicurezza del protocollo. Queste raccomandazioni sono dettagliate nella sezione "Revisione dell'architettura".

In conclusione, a seguito del rapporto dovrebbero essere implementate diverse soluzioni, ma il livello di sicurezza del sistema è adeguato.

Dopo una revisione da parte del team Sayfer, certifichiamo che tutti i problemi di sicurezza menzionati in questo rapporto sono stati affrontati o riconosciuti dal team Dusa.

Metodologia del rischio

Noi di Sayfer ci impegniamo a fornire ai nostri clienti audit di contratti intelligenti della massima qualità. Ecco perché abbiamo implementato un modello completo di valutazione del rischio per valutare la gravità dei nostri risultati e fornire ai nostri clienti le migliori raccomandazioni possibili per la mitigazione.

Il nostro modello di valutazione del rischio si basa su due fattori chiave: IMPATTO ed PROBABILITÀ. L'impatto si riferisce al danno potenziale che potrebbe derivare da un problema, come una perdita finanziaria, un danno alla reputazione o un sistema non operativo. La probabilità si riferisce alla probabilità che si verifichi un problema, tenendo conto di fattori quali la complessità del contratto e il numero di potenziali aggressori.

Combinando questi due fattori, possiamo creare una comprensione completa del rischio posto da un particolare problema e fornire ai nostri clienti una valutazione chiara e attuabile della gravità del problema. Questo approccio ci consente di dare priorità alle nostre raccomandazioni e garantire che i nostri clienti ricevano la migliore consulenza possibile su come proteggere i loro contratti intelligenti.

Il rischio è definito come segue:

Vulnerabilità per rischio

Alta – Minaccia diretta ai processi aziendali chiave.
Medio – Minaccia indiretta ai processi aziendali chiave o minaccia parziale ai processi aziendali.
Basso – Non esiste alcuna minaccia diretta. La vulnerabilità può essere sfruttata utilizzando altre vulnerabilità.
Informativo – Questo risultato non indica vulnerabilità, ma riporta un commento che segnala difetti di progettazione e implementazione impropria che potrebbero causare problemi a lungo termine.

Gravità
# di problemi
Alta
2
Medio
1
Basso
8
Informativo
6
critico
0

Approccio

Introduzione

Dusa ha contattato Sayfer per eseguire un controllo di sicurezza sui loro contratti intelligenti.

Questo rapporto documenta la ricerca condotta da Sayfer mirata alle risorse selezionate definite nell'ambito della ricerca. In particolare, questo rapporto mostra la revisione del livello di sicurezza per i contratti sopra menzionati.

Panoramica dell'ambito

Insieme al team del cliente abbiamo definito il seguente contratto come ambito del progetto.

Contratto Sha-256
Fabbrica.ts b86a4c350c37a0d8c62495bde0be2b0dca2c8a9f343149238548690df5104cee
main.ts d0073078a6ef26a402bcfb368e94dfb9dddc3f2a629eabc842e2b62d62772b6a
Coppia.ts 186f3bd5fab92cb4e98ea5daef31f44d1889f28e683663d056ff6649685ce36c
Quoter.ts b51c762d8ebe50c6b966c9b52a33819a674fb7cf056062ebe34d8f425d879aad
Router.ts 038e32c21432ad173cf8f3b77a586f222a99a8d0f8e033e40145643671ff87ee
WMAS.ts bcef456ec5e27527ae560e21b00fb9f4c8300016aae584da3aa1e869c7018832

I nostri test sono stati eseguiti tra gennaio e febbraio 2024.

Non lasciare che sia troppo tardi!

Inizia la tua verifica con Sayfer

Convalida dell'ambito

Abbiamo iniziato assicurandoci che l'ambito definito dal cliente fosse tecnicamente logico. Decidere quale ambito è corretto per un dato sistema fa parte della discussione iniziale.

Modello di minaccia

noi definoto che la più grande minaccia attuale per il sistema è la capacità degli utenti malintenzionati di farlo rubare fondi dal contratto.

Non lasciare che sia troppo tardi!

Inizia la tua verifica con Sayfer

Panoramica del protocollo

Introduzione al protocollo

Dusa è un protocollo di finanza decentralizzata (DeFi) rivoluzionario, che introduce un'esperienza di market maker (AMM) automatizzata completamente decentralizzata e avanzata. Costruito sulla blockchain di Massa, Dusa enfatizza principi chiave come la completa decentralizzazione, l'accessibilità per tutti i profili utente, l'interoperabilità con le future applicazioni decentralizzate (DApp) e un forte impegno per la sicurezza e la resistenza alla censura. La sua tabella di marcia delinea un approccio graduale, che comprende ricerca e sviluppo, test, missioni incentivate e l'implementazione di uno scambio decentralizzato (DEX). Le caratteristiche uniche di Dusa includono liquidità concentrata, commissioni variabili, liquidità autonoma e ordini di trading complessi, tutti progettati per migliorare l'esperienza dell'utente e la massimizzazione del rendimento. Con un team dedicato, investitori strategici e consulenti, Dusa mira a aprire la strada all’adozione di contratti intelligenti autonomi ed estendere le sue soluzioni decentralizzate ad altri ecosistemi.

Revisione dell'architettura

Riconoscendo che Dusa è un derivato di una soluzione consolidata, TraderJoe, e si allinea con un modello architetturale riconosciuto, notiamo raccomandazioni aggiuntive limitate per l'architettura attuale. Tuttavia, la nostra valutazione dell’architettura del protocollo Dusa ha portato a una visione completa, che combina informazioni preziose con raccomandazioni ponderate per il miglioramento:

  • Dal punto di vista delle best practice, consigliamo di considerare in futuro l’implementazione di un portafoglio multisig per la gestione dei ruoli privilegiati. Pur prendendo atto del recente rilascio del codice multisig Massa (https://github.com/massalabs/massa-standards/tree/feature/multisig-sc/smart-contracts/assembly/contracts/multisig), consigliamo prudenza e consideriamo l'uso di una chiave privata standard come un'opzione praticabile anche per il momento.
  • Un’altra raccomandazione intelligente suggerisce di adottare un modello di liquidità unificato, prevedendo un Vault/PoolManager globale invece di contratti individuali per pool. Questo cambiamento strategico, ispirato dai recenti progressi nelle AMM come Uniswap V4 e Balancer, promette vantaggi significativi. Questi includono swap multi-hop convenienti e una maggiore capacità di prestito flash, attribuita all’accesso semplificato all’intero pool di liquidità.

Valutazione della sicurezza

Test specifici di Dusa

Poiché Dusa si trova nella situazione unica di rispecchiare TraderJoe in un linguaggio di programmazione diverso, abbiamo eseguito numerosi test aggiuntivi oltre a quelli abituali per garantire che non ci fossero parti mancanti. Ecco un elenco dei test eseguiti specificatamente per il protocollo Dusa:

Controlli di sicurezza

  • Controlli di overflow/underflow, soprattutto a causa del cambiamento nella base di codice da un linguaggio con controlli predefiniti a uno in cui sono richiesti controlli espliciti.
  • Utilizzo di librerie sicure (selezionato_*).
  • Coerenza tra i contratti per quanto riguarda il flusso di fondi e le chiamate.
  • Visibilità delle funzioni per garantire che le funzioni corrette vengano esportate.
  • Implementazione del controllo degli accessi e protezione delle funzioni sensibili.
  • Protezione dello swap per proteggere le interazioni con la liquidità dallo slippage.

Autenticazione e autorizzazione

  • Controllo dell'intero processo di autenticazione, dei diritti del proprietario e dello schema di autorizzazione dei singoli punti di ingresso pubblici.
  • Identificazione di potenziali vulnerabilità che portano ad autorizzazioni dannose per gli aggressori.

Matematica e gestione delle variabili

  • Problemi relativi al calcolo, in particolare con più tipi di variabili, casting e gestione dei numeri a virgola mobile.
  • Errori decimali legati all'aspetto unico di MASSA che ha 9 decimali.
  • Gestione delle funzionalità di overflow/underflow.

Prestito Flash e Gestione della Liquidità

  • Esame degli errori tipici legati ai prestiti lampo, inclusi errori di calcolo e blocco dei fondi.
  • Problemi relativi alla creazione di fabbriche e coppie, come la creazione di pool pericolosi e la gestione della liquidità.
  • Verifica dei calcoli di rimozione della liquidità, considerando le commissioni ottenute durante la fornitura di liquidità.

Funzionalità e implementazione

  • Implementazione di swap rispetto ad altri DEX, concentrandosi sulla gestione delle commissioni e sulle differenze nei tipi di token.
  • Possibilità di attacchi DoS quando si opera su tipi non sicuri come Vector o Array.
  • Verifica dei problemi di centralizzazione, come la potenziale influenza sui prezzi, i trasferimenti di token utente e le modifiche alla configurazione.

Gestione dei dati contestuali

  • Verificare il passaggio dei dati di contesto corretti alle funzioni per evitare vulnerabilità.

 

Test generici

I seguenti casi di test sono stati la linea guida durante l'audit del sistema. Questa lista di controllo è una versione modificata del SCSVS v1.2, con grammatica, chiarezza, concisione e criteri aggiuntivi migliorati. Dove c'è una lacuna nella numerazione è stato eliminato un criterio originario. I criteri contrassegnati da un asterisco sono stati aggiunti da noi.

Architettura, design e modellazione delle minacce

Architettura, design e modellazione delle minacce Nome del test
G1.2 Ogni modifica di progettazione introdotta è preceduta dalla modellazione delle minacce.
G1.3 La documentazione definisce in modo chiaro e preciso tutti i limiti di fiducia nel contratto (relazioni di fiducia con altri contratti e flussi di dati significativi).
G1.4 Il SCSVS, i requisiti di sicurezza o la politica è disponibile per tutti gli sviluppatori e i tester.
G1.5 Gli eventi per le operazioni (cambiamento di stato/cruciali per il business) sono definiti.
G1.6 Il progetto include un meccanismo in grado di interrompere temporaneamente le funzionalità sensibili in caso di attacco. Questo meccanismo non dovrebbe bloccare l'accesso degli utenti alle loro risorse (ad esempio token).
G1.7 La quantità di criptovalute inutilizzate conservate sul contratto è controllata e al livello minimo accettabile in modo da non diventare un potenziale bersaglio di un attacco.
G1.8 Se la funzione di fallback può essere richiamata da chiunque, è inclusa nel modello di minaccia.
G1.9 La logica aziendale è coerente. Importanti cambiamenti nella logica dovrebbero essere applicati a tutti i contratti.
G1.10 Per rilevare le vulnerabilità vengono utilizzati strumenti di analisi automatica del codice.
G1.11 Viene utilizzata l'ultima major release di Solidity.
G1.12 Quando si utilizza un'implementazione esterna di un contratto, viene utilizzata la versione più recente.
G1.13 Quando le funzioni vengono sovrascritte per estendere la funzionalità, la parola chiave super viene utilizzata per mantenere la funzionalità precedente.
G1.14 L'ordine di eredità è accuratamente specificato.
G1.15 È presente un componente che monitora l'attività del contratto utilizzando gli eventi.
G1.16 Il modello di minaccia include transazioni di balene.
G1.17 La perdita di una chiave privata non compromette la sicurezza dell'intero progetto.

Politiche e procedure

Politiche e procedure Nome del test
G2.2 La sicurezza del sistema è costantemente monitorata (es. il livello previsto di fondi).
G2.3 Esiste una politica per tenere traccia delle nuove vulnerabilità di sicurezza e per aggiornare le librerie all'ultima versione sicura.
G2.4 Il dipartimento di sicurezza può essere contattato pubblicamente e che la procedura per la gestione dei bug segnalati (ad es. bug bounty completa) sia ben definita.
G2.5 Il processo di aggiunta di nuovi componenti al sistema è ben definito.
G2.6 Il processo delle principali modifiche al sistema prevede la modellazione delle minacce da parte di un'azienda esterna.
G2.7 Il processo di aggiunta e aggiornamento dei componenti al sistema include un controllo di sicurezza da parte di un'azienda esterna.
G2.8 In caso di hack, è in atto una procedura di mitigazione chiara e ben nota.
G2.9 La procedura in caso di hack definisce chiaramente quali persone devono eseguire le azioni richieste.
G2.10 La procedura include allarmare altri progetti sull'hacking attraverso canali attendibili.
G2.11 Viene definita una procedura di mitigazione della perdita di chiave privata.

Aggiornabilità

Aggiornabilità Nome del test
G3.2 Prima dell'aggiornamento, viene effettuata un'emulazione in un fork della rete principale e tutto funziona come previsto sulla copia locale.
G3.3 Il processo di aggiornamento viene eseguito da un contratto multisig in cui più di una persona deve approvare l'operazione.
G3.4 I timelock vengono utilizzati per operazioni importanti in modo che gli utenti abbiano il tempo di osservare i cambiamenti imminenti (si prega di notare che la rimozione di potenziali vulnerabilità in questo caso potrebbe essere più difficile).
G3.5 inizializzare() può essere chiamato una sola volta.
G3.6 inizializzare() può essere chiamato solo da un ruolo autorizzato tramite opportuni modificatori (es inizializzatore, onlyOwner).
G3.7 Il processo di aggiornamento viene eseguito in un'unica transazione in modo che nessuno possa eseguirlo in anticipo.
G3.8 I contratti aggiornabili hanno spazi riservati sugli slot per impedire la sovrascrittura.
G3.9 Il numero di slot riservati (come intervallo) è stato ridotto in modo appropriato se sono state aggiunte nuove variabili.
G3.10 Non ci sono cambiamenti nell'ordine in cui vengono dichiarate le variabili di stato del contratto, né i loro tipi.
G3.11 I nuovi valori restituiti dalle funzioni sono gli stessi delle versioni precedenti del contratto (es proprietario(), saldoDi(indirizzo)).
G3.12 L'implementazione viene inizializzata.
G3.13 L'implementazione non può essere distrutta.

 

Logica di business

Logica di business Nome del test
G4.2 La logica del contratto e l'implementazione dei parametri del protocollo corrispondono alla documentazione.
G4.3 La business logic procede in un ordine sequenziale e non è possibile saltare i passaggi o eseguirli in un ordine diverso da quello progettato.
G4.4 Il contratto ha correttamente rispettato i limiti di business.
G4.5 La logica di business non si basa sui valori recuperati da contratti non attendibili (soprattutto quando sono presenti più chiamate allo stesso contratto in un singolo flusso).
G4.6 La logica aziendale non si basa sull'equilibrio del contratto (ad esempio, saldo == 0).
G4.7 Le operazioni sensibili non dipendono dai dati del blocco (ad es. blocco hash, timestamp).
G4.8 Il contratto utilizza meccanismi che mitigano gli attacchi di ordine delle transazioni (front-running) (ad esempio schemi di pre-commit).
G4.9 Il contratto non invia fondi automaticamente, ma consente agli utenti di prelevare fondi in transazioni separate.

Access Control

Access Control Nome del test
G5.2 Il principio del minimo privilegio è rispettato. Altri contratti dovrebbero poter accedere solo a funzioni e dati per i quali sono in possesso di specifica autorizzazione.
G5.3 I nuovi contratti con accesso al contratto verificato aderiscono automaticamente al principio dei diritti minimi. I contratti devono disporre di autorizzazioni minime o nulle fino a quando l'accesso alle nuove funzionalità non viene concesso in modo esplicito.
G5.4 Il creatore del contratto rispetta il principio del minimo privilegio ei suoi diritti seguono rigorosamente quelli delineati nella documentazione.
G5.5 Il contratto applica le regole di controllo degli accessi specificate in un contratto attendibile, in particolare se il controllo degli accessi lato client dApp è presente e potrebbe essere aggirato.
G5.6 Le chiamate a contratti esterni sono consentite solo se necessario.
G5.7 Il codice modificatore è chiaro e semplice. La logica non deve contenere chiamate esterne a contratti non attendibili.
G5.8 Tutti gli attributi degli utenti e dei dati utilizzati dai controlli di accesso sono conservati in contratti attendibili e non possono essere manipolati da altri contratti se non specificamente autorizzati.
G5.9 I controlli di accesso falliscono in modo sicuro, anche quando si verifica un ripristino.
G5.10 Se l'input (parametri della funzione) viene convalidato, ove possibile viene utilizzato l'approccio di convalida positiva (whitelisting).

Comunicazione

Comunicazione Nome del test
G6.2 Vengono identificate le librerie che non fanno parte dell'applicazione (ma su cui si basa il contratto intelligente per funzionare).
G6.3 La chiamata delegata non viene utilizzata con contratti non attendibili.
G6.4 I contratti di terze parti non nascondono funzioni speciali (ad es. Revert).
G6.5 Il contratto non controlla se l'indirizzo è un contratto che utilizza il codice operativo extcodesize.
G6.6 Gli attacchi di rientro vengono mitigati bloccando le chiamate ricorsive da altri contratti e seguendo il modello Check-Effects-Interactions. Non utilizzare la funzione di invio a meno che non sia indispensabile.
G6.7 Il risultato di chiamate di funzioni di basso livello (ad es invia, delegachiama, chiama) da altri contratti è controllato.
G6.8 Il contratto si basa sui dati forniti dal mittente corretto e non si basa sul valore tx.origin.

Aritmetica

Aritmetica Nome del test
G7.2 I valori e le operazioni matematiche sono resistenti agli overflow di numeri interi. Utilizza la libreria SafeMath per le operazioni aritmetiche prima della solidità 0.8.*.
G7.3 I frammenti di codice non controllati da Solidity ≥ 0.8.* non introducono under/overflow di numeri interi.
G7.4 I valori estremi (es. valori massimi e minimi del tipo di variabile) sono considerati e non modificano il flusso logico del contratto
G7.5 La disuguaglianza non rigorosa viene utilizzata per l'uguaglianza di equilibrio.
G7.6 Nei calcoli vengono utilizzati gli ordini di grandezza corretti.
G7.7 Nei calcoli, la moltiplicazione viene eseguita prima della divisione per la precisione.
G7.8 Il contratto non presuppone la precisione a virgola fissa e utilizza un moltiplicatore o memorizza sia il numeratore che il denominatore.

Denial of Service

Denial of Service Nome del test
G8.2 Il contratto non esegue iterazioni su cicli non associati.
G8.3 La funzionalità di autodistruzione viene utilizzata solo se necessario. Se è incluso nel contratto, dovrebbe essere chiaramente descritto nella documentazione.
G8.4 La business logic non è bloccata se un attore (es. contratto, account, oracolo) è assente.
G8.5 La logica aziendale non disincentiva gli utenti a utilizzare i contratti (ad esempio, il costo della transazione è superiore al profitto).
G8.6 Le espressioni di funzioni assert o require hanno una variante passante.
G8.7 Se la funzione di fallback non è richiamabile da nessuno, non sta bloccando le funzionalità del contratto.
G8.8 Non ci sono operazioni costose in un ciclo.
G8.9 Non ci sono chiamate a contratti non attendibili in un ciclo.
G8.10 Se esiste la possibilità di sospendere l'esecuzione del contratto, è anche possibile riprenderlo.
G8.11 Se vengono utilizzate whitelist e blacklist, non interferiscono con il normale funzionamento del sistema.
G8.12 Non ci sono DoS causati da overflow e underflow.

Dati Blockchain

Dati Blockchain Nome del test
G9.2 Qualsiasi dato salvato nei contratti non è considerato sicuro o privato (anche variabili private).
G9.3 Nessun dato riservato viene memorizzato nella blockchain (password, dati personali, token ecc.).
G9.4 I contratti non utilizzano valori letterali stringa come chiavi per i mapping. Le costanti globali vengono utilizzate invece per prevenire l'attacco Homoglyph.
G9.5 Il contratto non genera banalmente numeri pseudocasuali basati sulle informazioni dalla blockchain (ad esempio seeding con il numero del blocco).

Utilizzo e limitazioni del gas

Utilizzo e limitazioni del gas Nome del test
G10.1 L'utilizzo del gas è previsto, definito e ha limiti chiari che non possono essere superati. Sia la struttura del codice che l'input dannoso non dovrebbero causare l'esaurimento del gas.
G10.2 L'esecuzione e la funzionalità della funzione non dipendono dalle tariffe del gas codificate (sono destinate a variare).

Chiarezza e leggibilità

Chiarezza e leggibilità Nome del test
G11.2 La logica è chiara e modularizzata in molteplici semplici contratti e funzioni.
G11.3 Ogni contratto ha un breve commento di 1-2 frasi che ne spiega lo scopo e la funzionalità.
G11.4 Vengono utilizzate implementazioni standard, questo è chiarito nel commento. Se queste implementazioni sono state modificate, le modifiche sono annotate in tutto il contratto.
G11.5 L'ordine di ereditarietà viene preso in considerazione nei contratti che utilizzano più funzioni di ereditarietà e shadow.
G11.6 Ove possibile, i contratti utilizzano codice testato esistente (ad esempio contratti token o meccanismi come possedibile) invece di implementarne uno proprio.
G11.7 Modelli di denominazione coerenti vengono seguiti durante tutto il progetto.
G11.8 Le variabili hanno nomi distintivi.
G11.9 Tutte le variabili di archiviazione vengono inizializzate.
G11.10 Le funzioni con il tipo restituito specificato restituiscono un valore di quel tipo.
G11.11 Vengono utilizzate tutte le funzioni e le variabili.
G11.12 richiedere è usato al posto di ritornare in if dichiarazioni.
G11.13 I affermare La funzione viene utilizzata per verificare la presenza di errori interni e il file richiedere La funzione viene utilizzata per garantire una condizione valida in ingresso da utenti e contratti esterni.
G11.14 Il codice assembly viene utilizzato solo se necessario.

Copertura del test

Copertura del test Nome del test
G12.2 Le narrazioni sugli abusi dettagliate nel modello di minaccia sono coperte da unit test
G12.3 Le funzioni sensibili nei contratti verificati sono coperte con test in fase di sviluppo.
G12.4 L'implementazione dei contratti verificati è stata verificata per le vulnerabilità della sicurezza utilizzando sia l'analisi statica che quella dinamica.
G12.5 Le specifiche del contratto sono state formalmente verificate
G12.6 La specifica ei risultati della verifica formale sono inclusi nella documentazione.

Finanza decentralizzata

Finanza decentralizzata Nome del test
G13.1 Il contratto del prestatore non presuppone che il suo saldo (utilizzato per confermare il rimborso del prestito) venga modificato solo con le proprie funzioni.
G13.2 Le funzioni che modificano il saldo dei prestatori e/o prestano criptovaluta non sono rientranti se lo smart contract consente di prendere in prestito la criptovaluta della piattaforma principale (ad es. Ethereum). Blocca gli attacchi che aggiornano il saldo del mutuatario durante l'esecuzione del prestito flash.
G13.3 Le funzioni di prestito flash possono chiamare solo funzioni predefinite sul contratto ricevente. Se possibile, definire un sottoinsieme attendibile di contratti da richiamare. Di solito, il contratto di invio (prestito) è quello da richiamare.
G13.4 Se include operazioni potenzialmente pericolose (ad es. restituzione di più ETH/token di quelli presi in prestito), la funzione del destinatario che gestisce ETH o token presi in prestito può essere richiamata solo dal pool e all'interno di un processo avviato dal proprietario del contratto ricevente o da un'altra fonte attendibile (ad es. multiseg).
G13.5 I calcoli della quota del pool di liquidità vengono eseguiti con la massima precisione possibile (ad esempio, se il contributo è calcolato per ETH dovrebbe essere fatto con una precisione di 18 cifre – per Wei, non Ether). Il dividendo va moltiplicato per 10 alla potenza del numero di cifre decimali (es. dividendo * 10^18 / divisore).
G13.6 I premi non possono essere calcolati e distribuiti all'interno della stessa chiamata di funzione che deposita i token (dovrebbe essere definita anche come non rientrante). Questo protegge dalle fluttuazioni momentanee delle azioni.
G13.7 I contratti di governance sono protetti dagli attacchi di prestiti flash. Una possibile tecnica di mitigazione è richiedere il processo di deposito dei token di governance e proporre una modifica da eseguire in transazioni diverse incluse in blocchi diversi.
G13.8 Quando si utilizzano oracoli su catena, i contratti sono in grado di sospendere le operazioni in base al risultato degli oracoli (in caso di oracolo compromesso).
G13.9 I contratti esterni (anche fidati) che sono autorizzati a modificare gli attributi di un contratto di progetto (es. prezzo del token) hanno le seguenti limitazioni implementate: soglie per la modifica (es. non più/meno del 5%) e un limite di aggiornamenti (es. un aggiornamento al giorno).
G13.10 Gli attributi del contratto che possono essere aggiornati dai contratti esterni (anche fidati) vengono monitorati (ad es. utilizzando gli eventi) e viene implementata una procedura di risposta agli incidenti (ad es. durante un attacco in corso).
G13.11 Operazioni matematiche complesse che consistono in operazioni sia di moltiplicazione che di divisione eseguono prima le moltiplicazioni e poi le divisioni.
G13.12 Quando si calcolano i prezzi di scambio (ad es. da ETH a token o viceversa), il numeratore e il denominatore vengono moltiplicati per le riserve (vedere il getInputPrice funzione nel ScambioUniswap contrarre).

 

Controllo dell'ordine da Sayfer





    Questo sito è protetto da reCAPTCHA e Google Informativa sulla Privacy ed Termini di Servizio applicare.

    Risultati dell'audit

    [H] Rischio di corsa iniziale durante la creazione di una nuova coppia

    ID DIRE-01
    Stato dei servizi Fissa
    Rischio Alta
    Affari Impact In alcuni casi, gli utenti potrebbero perdere i fondi depositati per finanziare la creazione di coppie. Un pioniere malintenzionato può creare una coppia a spese di un altro utente, oppure più utenti potrebbero tentare di creare una coppia contemporaneamente, riuscendoci o fallendo in modo casuale.
    Dove
    • Router.ts; createLBPair(StaticArray )
    • Fabbrica.ts; createLBPair(StaticArray )

    Descrizione

    Per creare una nuova coppia, l'utente deve chiamare Router::createLBPair(StaticArray ). Sotto il cofano, questa funzione chiama Factory::createLBPair(StaticArray ), che a sua volta chiama Massa transferCoins(Indirizzo, numero).

    • Fabbrica.ts:264; createLBPair(StaticArray )

    transferCoins(_pair._origin, 200 * ONE_COIN);

    Secondo il documentazione, questa funzione trasferisce semplicemente le monete dall'indirizzo corrente a un determinato indirizzo. Ciò significa che questi fondi devono essere precedentemente inviati Fabbrica. D'altra parte, gli utenti hanno la possibilità di chiamare createPair dal Router, che è il punto di ingresso predefinito per altre operazioni. Tuttavia, se vengono depositati in una transazione separata, esiste la possibilità che qualcuno, intenzionalmente o meno, chiami createLBPair(StaticArray ).

    Quando un blocco con transazioni viene finalizzato, queste verranno disposte in un ordine sconosciuto. Quindi, per la prima transazione inclusa, questi fondi verranno trasferiti da Factory a una nuova coppia, mentre per il secondo utente (quest'ultima transazione) la transazione verrà annullata a causa della mancanza di fondi disponibili.

    Mitigazione

    Il finanziamento della creazione della coppia deve effettivamente avvenire nella stessa transazione per evitare problemi di riordino delle transazioni. 

    Ad esempio, uno dei modi per ottenerlo potrebbe essere un meccanismo che controlla il saldo di fabbrica e il saldo del pool alla fine di una funzione e restituisce il surplus, simile a questo https://github.com/massalabs/coin-vester/blob/master/smart-contract/assembly/contracts/main.ts#L34

    Il meccanismo sarà in vigore nel creareLBPair funzione di Fabbrica), nel costruttore, menta, bruciare, raccogliereCommissioni, aumentareOracleLength, safeTransferFrom & safeBatchTransferFrom (di coppia). Queste sono le funzioni che possono spendere Massa per lo storage in quanto possono creare nuove voci nello storage (modificare lo storage non costa nulla). Anche le funzioni che interagiscono con queste funzioni devono avere questo meccanismo. 

    Possono essere distinti in due diverse tipologie:

    • Funzioni che interagiscono con questi e che non interagiscono con WMAS (creareLBPair dal router e dalla fabbrica + aggiungiLiquidità, rimuovereLiquidità) trasferirà tutti i file monete trasferite, salva il saldo della SC in modo costante e, dopo la chiamata della SC, ritrasferisci al chiamante la differenza tra il nuovo saldo e il saldo salvato.
    • Funzioni che interagiscono con questi e che interagiscono con WMAS (aggiungiLiquiditàMAS, rimuoviLiquiditàMAS) avrà bisogno di un ulteriore parametro per conoscere il numero di monete che devono essere incartate, invierai la differenza monete trasferite e questo numero nella chiamata. Il resto del meccanismo di queste funzioni sarà lo stesso di quello precedente.

     

    [H] I fondi depositati per la creazione della coppia potrebbero andare persi

    ID DIRE-02
    Stato dei servizi Fissa
    Rischio Alta
    Impatto sul business Gli utenti che depositano fondi sul router per creare una coppia potrebbero perdere i propri soldi senza vedere alcun risultato. Abbiamo valutato questo problema come elevato (piuttosto che critico) perché esiste un flusso di lavoro alternativo: le chiamate factory::createLBPair(StaticArray ) direttamente con i fondi.
    Dove
    • Router.ts; createLBPair(StaticArray )
    • Fabbrica.ts:264; createLBPair(StaticArray )

    Descrizione

    Questo problema è il risultato di come è progettata la creazione della coppia. Un utente può chiamare Router::createLBPair(StaticArray ) e poiché la creazione di una coppia richiede un deposito, può allegare fondi alla chiamata di funzione, il che sembra una soluzione intuitiva.

    Tuttavia, se l'utente lo fa, i fondi non raggiungeranno mai la coppia e andranno persi nel contratto (anche se potranno essere recuperati dal proprietario). Questo perché rimarranno bloccati nel contratto Router, mentre la creazione della coppia avviene nel contratto Factory, dove viene invece utilizzato transferCoins(), che detrae fondi dall'indirizzo corrente (della fabbrica).

    • Fabbrica.ts:264; createLBPair(StaticArray )

    transferCoins(_pair._origin, 200 * ONE_COIN);

    Poiché è implementato in fabbrica, i fondi inviati al router non raggiungeranno la fabbrica, che inoltre non avrà i fondi per creare una coppia e ripristinarla.

    Mitigazione

    Un'opzione è implementare la soluzione suggerita in DIRE-01.
    Al contrario, Fabbrica.ts può essere chiamato direttamente per creare coppie e richiedere agli utenti di inviare l'importo esatto richiesto insieme alla chiamata alla funzione, OPPURE almeno l'importo richiesto con il rimborso di eventuali fondi in eccesso inviati.

     

    [M] Più coppie dello stesso tipo possono diluire la liquidità

    ID DIRE-03
    Stato dei servizi Fissa
    Rischio Medio
    Impatto sul business Se un’applicazione AMM consente la creazione di più pool con gli stessi parametri, la liquidità potrebbe essere diluita tra questi pool, invece di essere concentrata in uno solo. Ciò potrebbe avere un impatto negativo sugli utenti e potrebbe comportare scambi meno favorevoli disponibili per gli utenti del protocollo.

    Inoltre, la coppia precedente non verrà più utilizzata per il routing. Ciò può comportare liquidità o manipolazione dei prezzi.

    Dove
    • Fabbrica.ts; createLBPair(StaticArray )
    • Router.ts; createLBPair(StaticArray )

    Descrizione

    Quando si crea una nuova coppia, non è possibile verificare se esiste già esattamente la stessa coppia. Ciò potrebbe disperdere la liquidità degli utenti su più pool equivalenti. I pool a bassa liquidità sono più inclini alla manipolazione dei prezzi e offrono operazioni meno favorevoli e dovrebbero pertanto essere evitati.

    Mitigazione

    Controlla se una coppia di determinati parametri esiste già al momento della creazione della coppia, in tal caso ripristina.

     

    [L] Il controllo esatto del saldo dopo un prestito flash può essere oggetto di abuso

    ID DIRE-04
    Stato dei servizi Fissa
    Rischio Basso
    Impatto sul business Un destinatario del prestito flash potrebbe eseguire chiamate esterne nella richiamata. Poiché il sistema richiede che il saldo dopo il prestito flash sia esattamente il saldo prima più le commissioni, questi contratti esterni potrebbero trasferire un importo molto piccolo alla coppia durante l'esecuzione per garantire che il prestito flash fallisca (il che potrebbe essere redditizio per loro). in determinate situazioni).
    Dove
    • Coppia.ts:280; flashLoan(StaticArray )

    Descrizione

    Dopo un prestito lampo, il sistema richiede che il saldo sia esattamente il saldo prima del prestito lampo più le commissioni.

    • flashLoan(StaticArray )

    assert(

      _balanceAfter == SafeMath256.add(_balanceBefore, _fees.total),

      LBPair__FlashLoanInvalidBalance(),

    );

    In genere, è necessario che il saldo sia maggiore, poiché richiedere una corrispondenza esatta è restrittivo.

    Mitigazione

    Controlla solo se il saldo è superiore al saldo prima del prestito flash più commissioni. Questa è anche la logica che TraderJoe utilizza nella sua funzione di prestito flash.

     

    [L] Ignorare una coppia LB non emette un evento

    ID DIRE-05
    Stato dei servizi Fissa
    Rischio Basso
    Affari Impact Gli indicizzatori fuori catena potrebbero ricevere informazioni errate, portando a calcoli errati.
    Dove
    • Fabbrica.ts; setLBPairInformation(StaticArray )

    Descrizione

    La funzione setLBPairIgnored(StaticArray ) può essere utilizzato per controllare se una coppia deve essere ignorata o meno per il routing. Qualsiasi modifica nel flag tramite questa funzione emette l'evento SET_LBPAIR_IGNORED. Tuttavia è anche possibile modificare il flag tramite setLBPairInformation(StaticArray ), che non emette un evento.

    Mitigazione

    Emetti sempre un evento quando cambi il flag per garantire che i sistemi off-chain sappiano quali coppie verranno prese in considerazione per il routing.

    [L] Riscossione delle commissioni incoerente

    ID DIRE-06
    Stato dei servizi Riconosciuto
    Rischio Basso
    Affari Impact Qualsiasi utente può attivare la riscossione delle tariffe per altri utenti, mentre la riscossione delle tariffe del protocollo può essere avviata solo dal proprietario.
    Dove
    • Coppia.ts; CollectFees(StaticArray )
    • Coppia.ts:723-726; collectorProtocolFees(StaticArray )

    Descrizione

    Chiunque può chiamare CollectFees(StaticArray ) per qualsiasi indirizzo per distribuire le commissioni a questo indirizzo. Ciò potrebbe essere indesiderato per alcuni utenti che desiderano controllare quando vengono loro distribuite le commissioni. 

    Anche questo non è coerente con collectorProtocolFees(StaticArray ), che può essere chiamato solo dal destinatario.

    • collectorProtocolFees(StaticArray )

    assert(

      Context.caller().equals(_feeRecipient),

      LBPair__OnlyFeeRecipient(_feeRecipient, Context.caller()),

    );

    Mitigazione

    Considera l'idea di cambiare la logica CollectFees(StaticArray ) in modo che corrisponda collectorProtocolFees(StaticArray ), ovvero consentendo al destinatario di riscuotere solo le proprie commissioni.

    [L] Utilizzo incoerente di SafeMath

    ID DIRE-07
    Stato dei servizi Fissa
    Rischio Basso
    Affari Impact Overflow o underflow nel codice possono portare a ripristini e/o calcoli errati imprevisti. 
    Dove -

    Descrizione

    Sebbene SafeMath viene utilizzato in molti luoghi, alcune funzioni che utilizzano operazioni aritmetiche vengono lasciate non protette, il che può di conseguenza portare a overflow o underflow.

    Mitigazione

    Sebbene non sia stato individuato alcun luogo in cui una situazione del genere potrebbe essere probabile, a causa delle grandi dimensioni della base di codice e della moltitudine di calcoli, raccomandiamo di implementare SafeMath nel maggior numero di operazioni possibile.

    [L] Enumerazione delle risorse inefficiente

    ID DIRE-08
    Stato dei servizi Fissa
    Rischio Basso
    Affari Impact Alcune funzioni di fabbrica consumeranno più gas del necessario. Nel peggiore dei casi, se il proprietario registra una quantità molto elevata di beni, ciò potrebbe portare a un DoS. Ma questo è improbabile.
    Dove
    • Fabbrica.ts:102-106; isQuoteAsset(Indirizzo)

    Descrizione

    ecco due problemi con questa funzione: 

    1. Il ciclo non si interrompe dopo aver trovato una risorsa e ripete inutilmente il resto dell'array. Quindi, ogni caso is il caso peggiore.
    2. Una mappatura sarebbe più efficiente in questo caso, poiché ha una ricerca temporale costante.
    • isQuoteAsset(Indirizzo)

    for (let i = 0; i < quoteAssets.length; i++) {

      if (quoteAssets[i].equals(_token)) {

        isQuoteAsset = true;

      }

    }

    Mitigazione

    Ci sono due soluzioni qui:

    1. Mantieni l'attuale algoritmo di ricerca lineare e aggiungi semplicemente un'interruzione nel file if blocco dopo l'impostazione isQuoteAsset vero.
    2. Una soluzione migliore sarebbe passare a una mappatura. Quando un nuovo token viene aggiunto al sistema, quoteAssets[token] dovrebbe essere impostato su vero. D'ora in poi sarà possibile accedervi quando necessario, senza bisogno di cercarlo. Forse l'intera funzione può essere semplicemente rifattorizzata.

    [L] La tariffa massima per il prestito Flash non viene impostata dopo la distribuzione

    ID DIRE-09
    Stato dei servizi Fissa
    Rischio Basso
    Affari Impact È possibile avere una commissione di prestito flash superiore a MAX_TARIFFA.
    Dove
    • Fabbrica.ts:80; costruttore(StaticArray )

    Descrizione

    Ogni volta che la tariffa del prestito flash viene impostata utilizzando setFlashLoanFee(), viene convalidato che è inferiore al valore MAX_TARIFFA. Tuttavia, questo controllo non viene eseguito al momento della inizializzazione del contratto ed è possibile impostare una commissione di prestito flash arbitrariamente elevata.

    Mitigazione

    Convalidare la tariffa del prestito flash nel costruttore.

    [L] Protezione dallo slittamento incompleto – Controllo della scadenza mancata

    ID DIRE-10
    Stato dei servizi Fissa
    Rischio Basso
    Affari Impact Esiste una maggiore probabilità che gli utenti ottengano operazioni meno favorevoli quando utilizzano l'AMM.
    Dove Router.ts

    • addLiquidità(bs: StaticArray )
    • addLiquidityMAS(bs: StaticArray )

    Descrizione

    Lo slippage è il risultato di una volatilità nelle soluzioni di tipo AMM e significa semplicemente che il prezzo quando si richiede una modifica di operazione/swap/liquidità è diverso rispetto a quando la transazione viene eseguita. Per proteggere gli utenti da enormi slittamenti, che possono essere naturali o il risultato di attacchi intenzionali come il Sandwiching, esistono due tipi generici di protezioni: importo minimo, che è presente, e controllo delle scadenze, che manca.

    Tali controlli dovrebbero essere implementati su qualsiasi swap, aggiunta e rimozione di liquidità, poiché tutti sono soggetti a slittamento.

    Un controllo della scadenza semplicemente non consente di includere la transazione dopo un certo punto temporale, che ad esempio può essere intenzionalmente incluso in seguito da un block builder dannoso per tentare comunque di eseguire la transazione a condizioni di prezzo meno favorevoli. Tuttavia, poiché viene controllato un importo minimo di token, l'impatto di questo problema è limitato.

    Mitigazione

    Realizzare  _assicurare(scadenza) allo stesso modo è già presente in tutte le altre funzioni che si occupano di liquidità.

    [L] Trasferimento della proprietà in un unico passaggio

    ID DIRE-11
    Stato dei servizi Fissa
    Rischio Basso
    Affari Impact Fornire un indirizzo errato potrebbe comportare la perdita irrevocabile della titolarità del contratto.
    Dove
    • Fabbrica.ts; trasferimentoProprietà([u8])

    Descrizione

    In Fabbrica.ts, il passaggio di proprietà avviene tramite il vecchio proprietario chiamando il trasferimentoProprietà([u8]) con il nuovo proprietario. La funzione quindi modifica il file PROPRIETARIO variabile di stato.

    • trasferimentoProprietà([u8])

    export function transferOwnership(bs: StaticArray<u8>): void {

      _onlyOwner();

      const _newOwner = new Address(new Args(bs).nextString().unwrap());

      _setFeeRecipient(_newOwner);

      Storage.set(OWNER, _newOwner.toString());

    }

    Mitigazione

    Ti consigliamo di implementare un processo in due passaggi per il trasferimento della proprietà. Ciò è in linea con le buone pratiche ampiamente riconosciute e potrebbe prevenire trasferimenti accidentali. Per illustrare, utilizzeremo l'implementazione di OpenZepplin.

    Un trasferimento di proprietà in due passaggi richiede innanzitutto che l'attuale proprietario avvii il trasferimento.

    function transferOwnership(address newOwner) public virtual override onlyOwner {

     _pendingOwner = newOwner;

     emit OwnershipTransferStarted(owner(), newOwner);

    }

    Ma per completare il processo, il nuovo proprietario deve approvare il trasferimento.

    function acceptOwnership() public virtual {

     address sender = _msgSender();

     if (pendingOwner() != sender) {

         revert OwnableUnauthorizedAccount(sender);

     }

     _transferOwnership(sender);

    }

    Ciò garantisce che il nuovo proprietario sia l'obiettivo previsto.

    [I] Emissione di eventi insufficiente

    ID DIRE-12
    Stato dei servizi Fissa
    Rischio Informativo
    Affari Impact Diminuzione della tracciabilità e della visibilità dei cambiamenti storici dello stato chiave che influiscono sul protocollo.
    Dove Fabbrica.ts

    • setLBPairInformation(bs: StaticArray )
    • forceDecay(bs: StaticArray )
    • transferOwnership(bs: StaticArray )

    Descrizione

    Alcuni dei cambiamenti di stato chiave del protocollo non emettono un evento associato.

    Nota: transferOwnership(bs: StaticArray ) emette un evento, ma solo per _setFeeRecipient.

    Mitigazione

    Aggiungi l'emissione di eventi nelle posizioni specificate.

    [I] Getter e setter sono confusi con funzioni esterne

    ID DIRE-13
    Stato dei servizi Fissa
    Rischio Informativo
    Affari Impact Mixing, getter, setter, entrypoint e funzioni interne rendono il codice meno leggibile.
    Dove
    • Factory.ts:631, 639
    • Coppia.ts:1031, 1227

    Descrizione

    Alcuni contratti hanno sezioni separate contenenti funzioni che cambiano lo stato (setter), lo leggono (getter) o fanno parte dell'albero delle chiamate di funzione (interno).

    In alcuni contratti, tuttavia, quest’ordine è disturbato: le funzioni sono confuse. A volte, anche le funzioni esportate (punti di ingresso) vengono confuse con quelle interne.

    Mitigazione

    Si consiglia di separare adeguatamente le sezioni del codice, di separare i punti di ingresso dalle funzioni interne e di mantenere la convenzione di utilizzare il segno _ prima delle funzioni private.

    [I] Mancanza di test unitari

    ID DIRE-14
    Stato dei servizi Riconosciuto
    Rischio Informativo
    Affari Impact Scenari di test e test unitari aiutano gli sviluppatori a rilevare bug e vulnerabilità che altrimenti sfuggirebbero in una semplice analisi statica. I test dinamici hanno un valore inestimabile per garantire la qualità del prodotto finito.
    Dove -

    Descrizione

    A parte una dozzina circa di test per una serie di funzionalità della libreria, il codice non prevedeva test unitari, funzionali o di integrazione. Non tutti i difetti possono essere rilevati con la semplice analisi statica, lasciando il prodotto in una posizione precaria.

    Mitigazione

    È considerata una buona pratica garantire che la copertura del codice per i test sia la più elevata possibile e che gli scenari di test includano percorsi sia felici che infelici.

    [I] Codice non necessario

    ID DIRE-15
    Stato dei servizi Fissa
    Rischio Informativo
    Affari Impact Questo problema non ha alcun impatto diretto sul codice o sul protocollo ed è stato pertanto classificato come informativo.
    Dove Router.ts:770-772; _getAmountsIn(u64[], Indirizzo[], IERC20[], u256)

    Descrizione

    La funzione _getAmountsIn() prende i passi bin come argomento ed esegue il seguente controllo:

    • _getAmountsIn(u64[], Indirizzo[], IERC20[], u256)

    if (_binStep == 0) {

      // means TraderJoe V1 swap

    } else {

      ...

    }

    Tuttavia, ciò non è necessario. Il sistema non supporta gli scambi di tipo V1 e il resto della funzione non considera i passaggi del contenitore, poiché riceve le coppie (corrispondenti ai passaggi del contenitore) come argomento aggiuntivo.

    Mitigazione

    Valuta la possibilità di rimuovere l'argomento _pairBinSteps e la clausola if non necessaria.

    [I] Importazioni non utilizzate

    ID DIRE-16
    Stato dei servizi Fissa
    Rischio Informativo
    Affari Impact Questo problema non ha alcun impatto diretto sul codice o sul protocollo ed è stato pertanto classificato come informativo.
    Dove
    • Coppia.ts:35,
    • Router.ts:4,
    • WMAS.ts:5,6,
    • interfacce/IPair.ts:5

    Descrizione

    Sembra che le importazioni specificate non vengano mai utilizzate nei rispettivi contratti. Potrebbero essere rimossi.

    Mitigazione

    Rimuovere le importazioni inutilizzate.

    [I] Utilizzo dei "numeri magici"

    ID DIRE-17
    Stato dei servizi Riconosciuto
    Rischio Informativo
    Affari Impact Ciò potrebbe aumentare la difficoltà di analisi del codice per lettori non familiari.
    Dove
    • Coppia.ts:113
    • Factory.ts:264, 735

    Descrizione

    In più punti il ​​contratto utilizza valori numerici non ben documentati, descritti o commentati.

    Mitigazione

    Aggiungere commenti che spieghino la scelta delle costanti.

    Puoi trovare maggiori informazioni a riguardo sul nostro Blog

    Il blog di Sayfer si concentra su web3, sicurezza e ricerca sulle vulnerabilità. Riteniamo che nel settore della sicurezza informatica sia fondamentale rimanere aggiornati sulle ultime tendenze e progressi. Attualmente, il nostro team di ricercatori esperti si diverte a ricercare tecnologie blockchain e web3 all'avanguardia.
    Contattaci

    Rimaniamo in contatto

    Dove
    Tel Aviv, Israele
    messaggeri:
    Non esitate a contattarci, saremo lieti di rispondere!





      Questo sito è protetto da reCAPTCHA e Google Informativa sulla Privacy ed Termini di Servizio applicare.
      Salta al contenuto