December 16, 2021
Introducere
1inch echipa ne-a cerut să le revizuim și să le audităm Protocolul de comandă limită contracte inteligente v2. Ne-am uitat la cod și acum publicăm rezultatele noastre.
domeniu
Am auditat commit 4d94eea25e4dac6271bfd703096a5c4a4d899b4a
a 1inch/limit-order-protocol
repertoriu. În domeniul de aplicare au fost următoarele contracte:
- OrderMixin.sol
- OrderRFQMixin.sol
- PredicateHelper.sol
- RevertReasonParser.sol
- Permitable.sol
- ChainlinkCalculator.sol
- ArgumentsDecoder.sol
- AmountCalculator.sol
- NonceManager.sol
- LimitOrderProtocol.sol
- ImmutableOwner.sol
- InteractiveNotificationReceiver.sol
- AggregatorInterface.sol
- IDaiLikePermit.sol
Toate celelalte fișiere de proiect și directoare (inclusiv teste), împreună cu dependențele și proiectele externe, teoria jocurilor și proiectarea stimulentelor, au fost, de asemenea, excluse din domeniul de aplicare al acestui audit. S-a presupus că dependențele externe ale codului și contractului funcționează ca documente, iar serviciile de back-end furnizate de 1inch s-au presupus că acționează în cel mai bun interes al protocolului.
Sănătate generală
În general, am găsit că baza de cod a proiectului este lizibilă și bine organizată, deși ar putea beneficia de o documentație mai extinsă, în special în jurul blocurilor de cod de asamblare, cazuri marginale ale protocolului, active/predicate/resurse-externe care vor fi utilizate, responsabilitățile/limitările serviciului back-end furnizat și interacțiunile dintre actori. Proiectul face eforturi mari pentru a face acțiunile eficiente din punct de vedere al gazelor, ocazional chiar cu riscul de a face codul mai dificil de raționat; ridicăm probleme legate de aceasta mai jos. Pe parcursul auditului, echipa de 1 inch a fost foarte disponibilă, receptivă și foarte ușor de lucrat.
Prezentare generală a sistemului
Protocolul de ordine limită permite comanda makers
pentru a semna comenzi în afara lanțului pentru schimburi de jetoane. Protocolul facilitează apoi completarea comenzilor semnate anterior prin comandă takers
. Comenzile sunt foarte extensibile și pot apela static contracte externe în mai multe puncte de-a lungul procesului de completare a comenzilor. Această extensibilitate îmbunătățește protocolul cu utilitate, dar adaugă atât complexitate, cât și o suprafață de atac mai mare pentru comenzile în sine.
Este important de remarcat că nu există stocare în lanț a detaliilor comenzii. Starea de completare sau starea de anulare a comenzilor este urmărită numai prin hash-uri de comandă. Acest lucru necesită ca comenzile să fie partajate peer-to-peer sau printr-o parte centralizată. În acest caz, echipa de 1 inch intenționează să acționeze ca acea parte centralizată, cumulând ordinele semnate și folosind acele ordine ca sursă de lichiditate pentru celelalte protocoale ale lor. Comenzile vor fi publicate prin intermediul propriului API, astfel încât utilizatorii să poată interacționa cu ele.
Această centralizare oferă echipei de 1 inch control extrem asupra comenzilor care sunt publicate și în cele din urmă executate. Acest lucru le oferă, de asemenea, capacitatea de a cenzura comenzile, ceea ce ar putea fi util în cazul comenzilor rău intenționate sau înșelătoare, dar ar putea fi, de asemenea, abuzat și să le permită să conducă în fața oricărui alt utilizator în cazul unei comenzi favorabile, nefiind-o prin API.
Roluri privilegiate
Deși contractele în care este utilizat rolul au fost în afara domeniului de aplicare, a fost identificat un rol privilegiat. Un immutableOwner
este setat la creatorul unui contract de proxy în momentul construcției și este utilizat pentru a limita accesul la proxy-ul. external
funcții.
Dependențe externe și ipoteze de încredere
Proiectarea acestui protocol necesită componente off-chain și on-chain, iar acest model hibrid poate fi utilizat pentru a atenua unii vectori de atac pe care îi identificăm în raportul nostru, dar costul acestei abilități este o dependență crescută de echipa de 1 inch și infrastructură.
În plus, Protocolul Ordinului Limită oferă funcții care sunt menite să recupereze prețurile de la oracolele Chainlink. Am presupus că acele oracole sunt oneste, accesibile și funcționează corespunzător.
Mai mult, datorită flexibilității unei comenzi, există mai multe puncte de contact cu contracte externe care nu sunt validate. Aceasta înseamnă că un utilizator rău intenționat ar putea abuza de astfel de apeluri și uzurpa identitatea predicatelor, activelor sau oracolelor cu contracte rău intenționate pentru a executa acțiuni în timpul umplerii comenzilor. Deși proiectul este protejat în unele zone împotriva reintrării, astfel de vectori ar putea provoca atacuri de denegare a serviciului sau comenzi de spam nedetectate. Echipa de 1 inch este conștientă de faptul că pot apărea anumite probleme atunci când se utilizează contracte necunoscute pentru protocol și și-a indicat intenția ca doar activele majore „blue chip” să fie pe deplin susținute de proiect. Cu toate acestea, trebuie remarcat faptul că, chiar și cu cele mai populare active, există comportamente intrinseci de la fiecare activ care pot cauza probleme la protocoalele care nu le abordează corect, cum ar fi o taxă în timpul transferurilor cu USDT sau returnarea unui cod de eroare în loc de un succes boolean cu cTokens.
Constatări
Aici vă prezentăm constatările noastre.
Severitate critică
Nici unul.
Severitate ridicată
[H01] Date inconsistente au fost transmise în _makeCall
În OrderMixin
contractul, cel _makeCall
funcția este utilizată pentru a transfera active de la primitor la producator și apoi de la producator la primitor. În ultimul transfer, cel _makeCall
funcția este trecută incorect de comanda makerAsset
ca ultim parametru, când ar trebui să fie al comenzii makerAssetData
.
Ca rezultat, orice funcționalitate proxy care se bazează pe makerAssetData
argumentul se va rupe.
Pentru a fi în concordanță cu apelul anterior la _makeCall
și pentru a sprijini pe deplin funcționalitatea proxy, luați în considerare actualizarea order.makerAsset
parametru pentru a order.makerAssetData
.
Actualizați: Fixat în cerere de tragere #57.
[H02] Comenzile private parțial completate pot fi completate de oricine
Protocolul permite crearea de comenzi private și publice. La comenzi private, doar allowedSender
adresa, specificată de producător în timpul creării comenzii, este capabilă să completeze comanda.
Cu toate acestea, în OrderMixin
contracta, validare pentru allowedSender
adresa este incorect acoperit, ceea ce înseamnă că este evaluat doar în interiorul logicii care se ocupă de prima completare a unei comenzi. Dacă o comandă privată este parțial completată, atunci cecul pentru allowedSender
adresa nu mai este accesibilă și comanda devine completabilă de oricine.
Pentru a clarifica intenția dacă orice utilizator ar trebui să poată completa comenzi private parțial completate sau nu, luați în considerare fie documentarea motivului comportamentului actual, fie validarea allowedSender
adresa în afara domeniului de aplicare a primei completari pentru a se asigura că va fi validată de fiecare dată când se încearcă o completare.
Actualizați: Fixat în cerere de tragere #58.
[H03] Producătorul rău intenționat ar putea profita de completările parțiale pentru a fura activele utilizatorului
Comenzi de la OrderMixin
contract au capacitatea de a fi parțial completat. Pentru a suporta completările parțiale, protocolul necesită o modalitate de a calcula ambele părți ale swap-urilor. Ambii getMakerAmount
și getTakerAmount
câmpurile sunt definite de către producătorul comenzii în acest scop exact.
Atunci când completează o comandă, beneficiarii trebuie să furnizeze fie makingAmount
sau takingAmount
valori precum și a thresholdAmount
valoare. Există două căi de cod diferite care pot fi luate, în funcție de dacă makingAmount
sau takingAmount
a fost oferit.
Prima este atunci când makingAmount
parametrul este definit. Ar putea trunchia il makingAmount
valoare și de asemenea calculează takingAmount
valoare pentru ea. În această situație, thresholdAmount
asigură că takingAmount
valoarea luată este nu neașteptat de mare.
Al doilea este atunci când takingAmount
parametrul este definit. În acest caz, va fi calculează makingAmount
valoare, cu posibilitatea de trunchiindu-l și recalculând takingAmount
valoare dacă se întâmplă asta. În această situație, thresholdAmount
valoarea asigură că makingAmount
valoarea returnată este nu neașteptat de mic.
Există două metode de exploatare, fiecare unică pentru una dintre căile de cod menționate anterior. Aceste metode de exploatare necesită rău intenționat getMakerAmount
și getTakerAmount
funcții. O simplă implementare a acestor funcții ar avea un comportament identic cu AmountCalculator
„s getMakerAmount
și getTakerAmount
funcții, dar cu un comutator hard-coded care îi va forța să returneze o valoare controlată de atacator atunci când este necesar.
Primul model de exploatare, mai puțin sever, implică prima cale de cod în care makingAmount
valoarea este specificată într-o ordine de completare. Un producător rău intenționat ar aștepta o comandă de completare care specifică makingAmount
pentru a apărea în mempool pentru a-l promova. Ar scurge toată valoarea, cu excepția 1, din partea producătorului și apoi ar forța _callGetTakerAmount
să returneze suma specificată în cea a utilizatorului thresholdAmount
valoarea (sau alocația lor dacă este mai mică). Când tranzacția utilizatorului se încheie în sfârșit, acesta își va schimba integral thresholdAmount
în valoare de takerAsset
pentru o singură unitate de makerAsset
. Acest exploit este limitat de suma dată de thresholdAmount
valoarea sau suma takerAsset
utilizatorul a permis pe LimitOrderProtocol
contracta.
Al doilea model de exploatare, mai sever, implică a doua cale de cod în care takingAmount
valoarea este specificată. Producătorul rău intenționat ar aștepta, în mod similar, o comandă de completare care specifica a takingAmount
valoare care va apărea în mempool. Ei ar conduce tranzacția și ar forța makingAmount
valoare returnată de _callGetMakerAmount
funcția să fie mai mare decât atât remainingMakerAmount
si thresholdAmount
. De asemenea, ar seta takingAmount
valoarea returnată de _callGetTakerAmount
să fie suma de takerAsset
activ permis pe LimitOrderProtocol
de către primitor. Când tranzacția beneficiarului va fi finalizată, va fi trunchia makingAmount
valoare și apoi recalculați takingAmount
valoare. Cu toate acestea, această recalculare nu este garantată a fi mai mică și, în acest caz, va epuiza persoana care ia toate takerAsset
pe care le-au permis în contract. În această cale de cod, thresholdAmount
valoarea este asigurându-se că makingAmount
nu este prea jos, deci luând toate cele ale primitorului takerAsset
activul este nebifat. Fondurile pierdute sunt limitate de suma takerAsset
activ pe care utilizatorul l-a permis pe LimitOrderProtocol
contracta.
Aceste exploatări nu sunt posibile fără comenzi parțiale și, mai precis, comenzi parțiale cu malware getMakerAmount
și getTakerAmount
implementări.
Problema principală a thresholdAmount
Verificarea valorii este că acoperă doar o parte a schimbului, dar cealaltă parte poate fi manipulată prin frontrunning. Nu există asigurări că valoarea propusă inițial de primitorul rămâne neschimbată. Luați în considerare eliminarea makingAmount
trunchierea ambelor căi de cod și revenirea în cazul în care comanda nu poate suporta o umplere atât de mare cât este cerută. Făcând acest lucru, thresholdAmount
poate fi folosit pentru a restricționa suficient cealaltă parte a schimbului și pentru a evita comportamentul neașteptat, chiar și în cazul comenzilor rău intenționate.
Actualizați: Fixat în cerere de tragere #83.
Severitate medie
[M01] Argumente statice transmise după argumente dinamice
În OrderMixin
contractul, cel getTakerAmount
și getMakerAmount
câmpurile de octeți sunt folosite ca argumente pentru _callGetTakerAmount
și _callGetMakerAmount
funcții. Aceste apeluri oferă o modalitate de a calcula o parte a schimbului în funcție de cealaltă parte și permit utilizatorilor să completeze parțial comenzile.
getTakerAmount
/getMakerAmount
câmpurile sunt variabile dinamice și sunt împachetate în fața takerAmount
și makerAmount
valori în _callGetTakerAmount
și _callGetMakerAmount
funcții. Este posibil ca un producător rău intenționat să furnizeze mai multe date decât se aștepta în getTakerAmount
șigetMakerAmount
câmpuri pentru a împinge takerAmount
și makerAmount
octeți dincolo de unde se presupune că sunt atunci când sunt decodați în următoarea funcție. Acest lucru îi permite producătorului să schimbe cantitatea de preluare sau producător transmisă cu un octeți întregi spre dreapta și chiar să le înlocuiască complet dacă sunt furnizați 32 de octeți suplimentari de date.
Utilizatorii trebuie deja să revizuiască manual getTakerAmount
și getMakerAmount
câmpurile în ordine, dar această tehnică este destul de greu de identificat. De remarcat, de asemenea, acest atac se aplică chiar și celor de încredere în interior getMakerAmount
și getTakerAmount
funcții. Pentru majoritatea atacurilor, furnizarea unui prag rezonabil va preveni pierderea de fonduri.
Pentru a preveni acest lucru, luați în considerare codificarea argumentelor statice înaintea argumentelor dinamice pentru a evita să oferiți argumentelor dinamice o metodă de a controla argumentele statice.
Actualizați: Nereparat. Echipa de 1 inch a declarat:
Vom avea o grijă deosebită cu validarea getters. Vom încerca să implementăm validarea corectă a getter-urilor în SDK-ul nostru, care va ajuta la filtrarea comenzilor potențial rău intenționate.
[M02] Comenzile ERC721 pot fi manipulate
Este posibil să schimbați mai mult decât doar ERC20 prin intermediul OrderMixin
prin implementarea unui contract care împarte același selector de funcții ca și IERC20 transferFrom
, și furnizarea respectivului contract ca makerAsset
sau takerAsset
într-o ordine.
Proxy-urile în afara domeniului de aplicare, și anume, ERC721Proxy
, ERC721ProxySafe
, și ERC1155Proxy
contractele urmează acest model pentru a oferi sprijin pentru ERC721
și ERC1155
jetoane. Deoarece proxy-urile trebuie apelate cu același model ca un IERC20 transferFrom
apel, semnătura trebuie să înceapă cu address from
, address to
și uint256 amount
. Orice altceva necesită proxy poate fi transmis după și este definit în ordine ca makerAssetData
și takerAssetData
.
ERC1155-urile pot transfera în mod natural mai multe jetoane identice simultan, ceea ce înseamnă că ERC1155Proxy
contractul face uz de amount
camp. Pe de altă parte, ERC721
s nu au o utilizare evidentă pentru amount
camp. Deoarece ele reprezintă jetoane nefungibile, un anumit tokenId va avea doar unul existent, redând amount
câmp inutil. Din această cauză, implementarea pentru ambele ERC721Proxy
și ERC721ProxySafe
contractele folosesc necesarul amount
câmp ca tokenId
in schimb.
Această supraîncărcare a amount
parametrul creează posibilitatea de umplere parțială ERC721
comenzi pentru a cumpăra jetoane listate separat la prețuri reduse. De exemplu, ar putea exista un caz în care un singur utilizator are mai multe ERC721
s din același contract permise a fi transferate de către ERC721Proxy
contract și le listează în ordine limită separate.
Dacă ordinele limită oferă și getMakerAmount
și getTakerAmount
câmpuri, va fi posibilă completarea parțială a acestora ERC721
Comenzi. Din momentul comenzii amount
câmpul corespunde de fapt cu tokenId
, un utilizator rău intenționat poate introduce o umplere parțială pe fișierul ERC721
cu tokenId mai mare, rezultând a makingAmount
/takingAmount
unui ERC721
care ar putea corespunde unei mai mici tokenId
. Rezultatul este ERC721
cu cea inferioară tokenId
ar fi transferat la prețul de (higher tokenId price) * (lower tokenId's id) / (higher tokenId's id)
.
Acest exploit are câteva cerințe:
- Multiplu
ERC721
s din același contract să fie permise pe oricareERC721
procură de către un singur proprietar. - Comandă deschisă pentru unul dintre
ERC721
s asta nu este cel mai mictokenId
dintre cele permise. - Completari parțiale permise pe comandă.
Pentru a elimina complet posibilitatea parțială ERC721
umple, luați în considerare separarea amount
și tokenId
argumente. Indiferent dacă argumentele sunt separate sau nu, luați în considerare și documentarea acestui lucru pentru a alerta utilizatorii despre acest comportament și pentru a evita acest tipar în viitor.
Actualizați: Fixat în cerere de tragere #59.
[M03] Ipoteze zecimale nedocumentate
LimitOrderProtocol
contractul moștenește ChainlinkCalculator
contract prin intermediul OrderMixin
contracta. Acest contract expune două funcții pentru a permite utilizarea oracolelor Chainlink în timpul verificarea predicatelor și căutarea suma producatorului/suma de primitor.
Cu toate acestea, contractul face presupuneri nedocumentate cu privire la numărul de zecimale în care oracolele Chainlink ar trebui să le raporteze, precum și numărul de zecimale pe care ar trebui să-l conțină parametrii funcției. În anumite scenarii, acest lucru ar putea duce la comportamente neașteptate, inclusiv prețuri greșite ale activelor și pierderea neintenționată a fondurilor.
Mai precis, pe tot parcursul contractului presupunerea implicită este că oracolele Chainlink vor raporta cu 18 zecimale de precizie. Cu toate acestea, nu toate oracolele Chainlink raportați cu acest număr de zecimale. De fapt, dacă oracolul raportează o pereche de token care este în termeni de monedă (USD, de exemplu), va avea doar 8 zecimale de precizie. Deoarece nu există restricții cu privire la care pot fi folosite oracole, nu trebuie făcute presupuneri implicite cu privire la numărul de zecimale cu care vor raporta.
În mod similar, există o presupunere implicită că amount
parametru pentru ChainlinkCalculator
funcțiile vor folosi 18 zecimale, împreună cu declarația explicită înșelătoare că singlePrice
funcţie Calculates price of token relative to ETH scaled by 1e18
. În realitate, chiar și cu un oracol care face raportați cu 18 zecimale, valoarea returnată a singlePrice
funcția ar fi scalată cu numărul de zecimale ale amount
parametru, care poate să nu fie neapărat de 18 zecimale.
În mod similar, doublePrice
funcția presupune că două oracole Chainlink vor raporta cu același număr de zecimale, determinând ca rezultatul funcției să se abate de la așteptări.
Luați în considerare documentarea explicită a ipotezelor cu privire la numărul de zecimale pe care ar trebui să le fie parametrii și valorile returnate. Mai mult, luați în considerare fie limitarea calculelor care depind de oracole care încalcă acele ipoteze, fie ca calculele relevante să ia în considerare numărul real de zecimale.
Actualizați: Fixat în cerere de tragere #75.
Severitate scăzută
[L01] Constante nu sunt declarate explicit
Există câteva apariții în care valorile literale sunt folosite cu sens neexplicat în baza de cod. De exemplu:
- În
OrderMixin
contractul, cel_remaining
maparea este supraîncărcată semantic (după cum este explicat în problema Supraîncărcarea semantică a cartografierii) pentru a urmări cantitatea de activ rămasă pentru o comandă finalizată parțial precum și dacă o comandă a fost complet completată. Specific,0
înseamnă că nu au fost efectuate completări asociate cu o comandă,1
înseamnă că o comandă nu mai poate fi completată și ceva mai mare decât1
înseamnă că există o sumă rămasă asociată comenzii care poate fi completată. - În
ChainlinkCalculator
contract, valoarea literală1e18
este utilizat însinglePrice
Funcția.
Pentru a îmbunătăți lizibilitatea codului și pentru a facilita refactorizarea, luați în considerare definirea unei constante pentru fiecare număr magic, oferindu-i un nume clar și auto-explicativ. Pentru valori complexe, luați în considerare adăugarea unui comentariu inline care să explice cum au fost calculate sau de ce au fost alese.
Actualizați: Fixat în cerere de tragere #75 și cerere de tragere #76.
[L02] Părțile rău intenționate ar putea împiedica executarea ordinelor permise
OrderMixin
contractul permite utilizatorilor producătorului să trimită comenzi permise astfel încât acestea pot fi executate într-o singură tranzacție, mai degrabă decât să fie necesară o tranzacție separată pentru aprobări. De asemenea, cei care iau comenzi pot depune propriul permis in timpul completarii comenzii in acelasi scop.
Cu toate acestea, deoarece permisul producătorului este conținut în interiorul comandă, atât permisele producătorului, cât și cele ale primitorului ar fi accesibile în timp ce tranzacția de completare a comenzii este în mempool. Acest lucru ar face posibil ca orice utilizator rău intenționat să ia acele permise și să le execute pe respectivele contracte de active în timp ce derulează tranzacția de completare. Deoarece aceste permise au un nonce
pentru a preveni un atac de cheltuieli duble, tranzacția de umplere a comenzii ar eșua ca urmare a încercării de a utiliza același permis care tocmai a fost folosit în timpul frontrun.
Deși nu există niciun risc de securitate, iar producătorul ar putea crea o nouă comandă și ar putea aproba tranzacția în prealabil, acest atac ar putea afecta cu siguranță utilizarea comenzilor permise. Într-adevăr, un atacator motivat ar putea bloca toate comenzi permise cu acest atac. Luați în considerare validarea dacă permisul a fost deja depus sau dacă alocația este suficientă, în timpul umplerii comenzii. De asemenea, luați în considerare informarea utilizatorilor despre acest posibil atac în timpul compoziției comenzii.
Actualizați: Nereparat. Echipa de 1 inch spune:
Am avut înainte verificări de aprobare, dar am decis să simplificăm fluxul de permise pentru a reveni doar la aprobările nereușite. Ne vom gândi la modalitățile de a notifica producătorii despre problemă.
[L03] Cod duplicat
Există cazuri de cod duplicat în baza de cod. Dublarea codului poate duce la probleme mai târziu în ciclul de viață al dezvoltării și lasă proiectul mai predispus la introducerea de erori. Astfel de erori pot fi introduse din neatenție atunci când modificările de funcționalitate nu sunt replicate în toate instanțele de cod care ar trebui să fie identice. Exemple de cod duplicat includ:
În loc să duplicați codul, luați în considerare un singur contract sau o bibliotecă care să conțină codul duplicat și să îl utilizați ori de câte ori este necesară funcționalitatea duplicată.
Actualizați: Parțial fixat în cerere de tragere #60.
[L04] Suită de teste eronată sau înșelătoare
Există cazuri în suita de teste în care testele se abat de la comportamentul așteptat. De exemplu:
-
ChainlinkCalculator
contractul este moștenit de cătreOrderMixin
contracta. Cu toate acestea, în timpul testelorAmountCalculator.arbitraryStaticCall
funcția este folosită pentru a apelaChainlinkCalculator
contract ca un contract extern, independent. Chiar dacă rezultatul este cel așteptat, testul ar trebui să reflecte comportamentul cu designul actual al sistemului și cazul de utilizare anticipat prin apelareaChainlinkCalculator
funcţionează direct fără a utiliza apelul static arbitrar. - Deși contractele de proxy au fost în afara domeniului de aplicare, am observat că la testarea protocolului cu active ERC721,
ERC721Proxy
contractul nu este utilizat pentru a schimba activele din acesta suită de testare.
Întrucât suita de teste în sine nu face obiectul acestui audit, vă rugăm să luați în considerare revizuirea amănunțită a suitei de teste pentru a vă asigura că toate testele rulează cu succes în conformitate cu specificațiile protocolului.
Actualizați: Fixat în cerere de tragere #57, cerere de tragere #59, și cerere de tragere #61.
[L05] Erori și omisiuni în evenimente
În întreaga bază de cod, evenimentele sunt în general emise atunci când se fac modificări sensibile la contracte. Cu toate acestea, multor evenimente le lipsesc parametrii indexați și/sau le lipsesc parametri importanți. De exemplu:
Există, de asemenea, acțiuni sensibile cărora le lipsesc evenimentele, cum ar fi:
Luați în considerare indexarea mai completă a evenimentelor existente și adăugarea de noi parametri acolo unde acestea lipsesc. De asemenea, luați în considerare emiterea tuturor evenimentelor într-o manieră atât de completă încât să poată fi folosite pentru a reconstrui starea contractului de către serviciile off-chain.
Actualizați: Nereparat. Cu toate acestea, echipa de 1 inch a adăugat un orderRemaining
parametru la OrderCanceled
eveniment în cerere de tragere #62.
Echipa de 1 inch spune:
Am descoperit că doar un subset limitat de date este necesar pentru a satisface nevoile de front-end. În cazul unei analize extinse, toate câmpurile sugerate sunt disponibile prin urmărire. Pentru
OrderRFQMixin
ne așteptăm ca creatorii de piață să-și construiască propriul mod sofisticat de a urmări ce comenzi au fost anulate.
[L06] Depozitarea se modifică în timpul emisiei evenimentului
În NonceManager
contract, când NonceIncreased
evenimentul este emis, este de asemenea crescut nonce al expeditorului mesajului.
Executarea simultană a mai multor operațiuni poate face baza de cod mai greu de raționat, mai predispusă la erori și poate duce la trecerea cu vederea sau la înțelegerea greșit a operațiunilor.
Pentru a îmbunătăți intenționalitatea generală, lizibilitatea și claritatea codului, luați în considerare creșterea valorii nonce înainte de a emite evenimentul.
Actualizați: Fixat în cerere de tragere #63.
[L07] Metodologiile inconsecvente de decodare ar putea cauza discrepanțe de rezultat
Pentru a susține toată extensibilitatea și flexibilitatea sa, Protocolul de ordine limită trebuie să se ocupe de obicei de date dinamice de octeți și de valori de returnare arbitrare din contracte externe. Ca urmare, protocolul include un ArgumentsDecoder
bibliotecă pentru a converti mai eficient valorile octeților dinamici în tipuri de date de bază. Cu toate acestea, această bibliotecă nu este utilizată exclusiv și în unele cazuri abi.decode
este folosit în schimb. În plus, se folosesc unele contracte abi coder v1
în timp ce alții folosesc abi coder v2
. Primul funcționează mai asemănător cu cel al ArgumentsDecoder
bibliotecă, în timp ce acesta din urmă efectuează verificări suplimentare la decodare.
Utilizarea inconsecventă a acestor metodologii diferite de decodare poate duce la discrepanțe subtile între intenția și comportamentul real al bazei de cod.
De exemplu, simulateCalls
funcția folosește numai ArgumentsDecoder.decodeBool
funcţie. Dacă simulateCalls
funcția este folosită pentru a verifica apelurile care ar fi făcute în partea de predicat a unei ordine, atunci rezultatele acesteia ar putea să se abate de la ceea ce se întâmplă de fapt atunci când sunt evaluate condițiile de predicat, deoarece sunt folosite diferite metodologii de decodare.
Deci, de exemplu, dacă un predicat face un extern staticcall
la o funcție care returnează a uint256
valoare mai mare decât unu, mai degrabă decât cea așteptată bool
, atunci apelul se va reveni, deoarece valoarea returnată este decodificat cu abi coder v2
„s abi.decode
care nu va accepta astfel de valori ca bool
. Totuși, dacă se face exact același apel cu simulateCalls
, atunci acesta va fi pur și simplu marcat ca true
, Deoarece decodeBool
tratează orice valoare mai mare decât zero ca true
.
Pentru a face simulateCalls
funcția oglindește pe deplin comportamentul apelurilor de predicate reale, luați în considerare modificarea acesteia pentru utilizare abi.decode
.
Actualizați: Fixat în cerere de tragere #82.
[L08] Lipsa validării intrărilor
fillOrderToWithPermit
și fillOrderTo
funcțiile funcției OrderMixin
contract, precum și fillOrderRFQToWithPermit
și fillOrderRFQTo
funcțiile funcției OrderRFQMixin
contract, nu validați target
parametrul adresei.
Acest lucru face posibil ca un utilizator să treacă din neatenție adresa zero și, ca urmare, să blocheze activele pe care trebuie să le primească după completarea unei comenzi.
Pentru a vă asigura că utilizatorii nu își blochează accidental fondurile, luați în considerare validarea target
adresa nu este egală cu adresa zero în funcțiile citate.
Actualizați: Fixat în cerere de tragere #78.
[L09] Acoperire scăzută a testului unitar
Acoperirea testului unitar pentru întregul proiect este de aproximativ 75%, unele dintre contracte având o acoperire deosebit de scăzută.
Având în vedere importanța testelor unitare pentru validarea codului și prevenirea regresiilor la refactorizarea și dezvoltarea de noi funcții, încurajăm creșterea semnificativă a acoperirii testelor unitare la cel puțin 95% și includerea cazurilor marginale care acoperă chiar și situații puțin probabile.
Actualizați: Nereparat.
[L10] Documentație inline înșelătoare sau incompletă
De-a lungul bazei de cod, au fost identificate câteva cazuri de documentație inline înșelătoare și/sau incompletă și ar trebui remediate.
Următoarele sunt cazuri de documentație inline înșelătoare:
- În
ChainlinkCalculator
contractul, celsinglePrice
funcție NatSpec@notice
etichetă spune căCalculates price of token relative to ETH scaled by 1e18
, dar de fapt, rezultatul său este valoare ofamount
jetoane scalate de1e18
, unde oracolul poate să nu raporteze în termeni de ETH (pentru o pereche care nu include ETH, de exemplu). - În
OrderRFQMixin
contractul, celinvalidatorForOrderRFQ
funcție NatSpec@return
etichetă este înșelătoare, deoarece este posibil ca citatul să nu fi fost completat pentru ca bitul de invalidare respectiv să fi fost setat. Comanda poate fi, de asemenea, anulată. - Pe linii 147, 165, și 188 of
OrderMixin.sol
, NatSpec@param
etichetele sunt negramaticale. - Pe net 20 of
ERC1155Proxy.sol
,@notice
eticheta afirmă că hashul calculat este rezultatul hashinguluifunc_733NCGU
funcția, unde ar trebui să fiefunc_301JL5R
funcţionează în schimb.
Următoarele sunt cazuri de documentație inline incompletă:
- Funcții în
AmountCalculator
contractul nu descriu niciunul dintre parametri. - În
ChainlinkCalculator
contractul, celsinglePrice
șidoublePrice
funcțiile nu descriu toți parametrii. - În
ImmutableOwner
contract, variabila publică și modificatorul nu au NatSpec. - În
InteractiveNotificationReceiver
contractul, celnotifyFillOrder
funcția nu descrie niciunul dintre parametri. - În
LimitOrderProtocol
contractul, celDOMAIN_SEPARATOR
funcția nu are NatSpec. - Evenimente și mapări în
NonceManager
nu au NatSpec. - În
OrderRFQMixin
contracta,cancelOrderRFQ*
funcțiile nu descriu valorile returnate. - În
OrderMixin
contract, mai multe funcții nu completează NatSpec. - Pe net 168 of
OrderMixin.sol
si on line 71 ofOrderRFQMixin.sol
, îi lipsește@dev
etichetă. - Funcții în
PredicateHelper
contractul nu descriu toți parametrii.
Documentația clară în linie este fundamentală pentru a sublinia intențiile codului. Nepotrivirile dintre documentația inline și implementare pot duce la concepții greșite serioase despre modul în care se așteaptă să se comporte sistemul. Luați în considerare remedierea acestor erori pentru a evita confuzia pentru dezvoltatori, utilizatori și auditori deopotrivă.
Actualizați: Parțial fixat. Documentație înșelătoare abordată în cerere de tragere #75 și cerere de tragere #77.
Echipa de 1 inch spune:
Am remediat documentele înșelătoare. Completarea documentelor se va face mai târziu.
[L11] Comenzi DoS posibile atunci când se utilizează cârlige
OrderMixin
contractul implementează funcționalitatea pentru a completa comenzi de swap generice în afara lanțului care ar putea avea condiții pentru succesul acestora. În timpul completării comenzii, comanda poate verificați condițiile „predicate” predefinite înainte de a continua cu execuția.
Cu toate acestea, deoarece aceste condiții predicate ar putea viza logica oricărui contract arbitrar, un producător rău intenționat ar putea păcăli cei care iau o comandă să creadă că o comandă se comportă corect și că este valabilă atunci când o verifică în afara lanțului, dar apoi eșuează atunci când încearcă să completeze aceeași comandă. în lanț. Această modificare a comportamentului predicatului poate fi realizată fie prin avansarea unei stări variabile de care depind predicatele, prin examinarea gazului trimis sau chiar a adreselor implicate în apel, fie printr-o altă logică.
În plus, dacă producătorul a definit a interacțiunea în timpul schimbului, interactionTarget
contractul s-ar putea anula sau revoca alocația pentru a preveni completarea cu succes a comenzii, ducând în esență la același rezultat ca și predicate rău intenționate.
Deși activele nu vor fi în pericol, utilizatorii sau roboții care găsesc o comandă favorabilă vor avea sarcina sporită de a încerca să identifice aceste tipuri de comenzi spam care pot părea legitime la suprafață. În cazul în care nu reușesc să identifice acest tip de comenzi, vor suporta costuri irosite de gaz. Pentru a reduce cantitatea de comenzi spam, luați în considerare restricționarea țintelor disponibile pentru aceste hook-uri. De asemenea, luați în considerare avertizarea utilizatorilor cu privire la această posibilitate înainte de a încerca să completeze comenzi.
Actualizați: Nereparat. Echipa de 1 inch spune:
Ne ocupăm de asta pe backend-ul nostru și ne vom gândi la modalitățile de a notifica posibilii participanți cu privire la problemă.
[L12] Rotunjirea poate fi nefavorabilă pentru taker
În OrderMixin
și OrderRFQMixin
contracte, atunci când o comandă este în curs de finalizare și beneficiarul oferă doar a makingAmount
or takingAmount
suma, protocolul încearcă să calculeze suma contrapartidă a swapului.
Există două probleme cu aceste calcule, prima fiind că nu există nicio documentație sau o logică care să limiteze numărul de zecimale pe care ar trebui să le folosească parametrii de cantitate, ceea ce am abordat în Ipoteze zecimale nedocumentate problema.
A doua problemă este că, în cursul acestor calcule, protocolul se rotește în favoarea producătorului. Problema rotunjirii poate fi mult exacerbată atunci când ipotezele zecimale implicite sunt încălcate, dar chiar și atunci când totul este în termenii așteptați, rotunjirea va avea loc cu sume mici, impare.
Luați în considerare posibilitatea de a permite primitorului să specifice o cantitate minimă de makerAsset
bun pe care sunt dispuși să îl primească împreună cu o sumă maximă de takerAsset
activ pe care sunt dispuși să îl schimbe, astfel încât acceptarea oricărei rotunjiri să fie mai explicită.
Actualizați: Nereparat. Echipa de 1 inch spune:
Valoarea pragului ar trebui să fie suficientă pentru protecția primitorului.
[L13] Gestionare contradictorie a comenzii în lipsa parametrilor
În OrderMixin
contractul, cel fillOrderTo
funcția efectuează apeluri interne către _callGetMakerAmount
și _callGetTakerAmount
funcţionează ori de câte ori se încearcă o umplere şi fie makingAmount
sau takingAmount
parametrii sunt zero, respectiv, sau dacă makingAmount
valoarea este mai mare decât remainingMakerAmount
valoare.
_callGetMakerAmount
și _callGetTakerAmount
apelurile vor duce la reveniri dacă comanda nu a fost creată cu getMakerAmount
or getTakerAmount
parametrii, respectiv, și se execută o umplere parțială.
An comentariu inline alături _callGetMakerAmount
si un comentariu inline alături _callGetTakerAmount
susțin că „sunt permise doar umplerile întregi” dacă comanda nu a fost creată cu getMakerAmount
or getTakerAmount
parametri.
Cu toate acestea, există căi de cod pentru care acest lucru nu se aplică, deoarece acele căi nu verifică length
s din ambele getMakerAmount
și getTakerAmount
parametri.
Specific, când un taker
specifică a takerAmount
valoare pentru o comandă care are doar a getMakerAmount
, cu excepția cazului în care apelul la getMakerAmount
returnează o sumă mai mare decât remainingMakerAmount
, o completare parțială poate fi executată în contradicție cu documentația inline.
Acest lucru lasă neclară intenționalitatea acelor căi de cod. Dacă acesta este comportamentul așteptat, luați în considerare modificarea documentației inline, astfel încât să fie mai explicită. Dacă acesta este un comportament neintenționat, luați în considerare întotdeauna verificarea lungimii ambelor getMakerAmount
si getTakerAmount
parametrii simultan, astfel încât implementarea să întărească comportamentul descris de documentația inline.
Actualizați: Fixat în cerere de tragere #79.
[L14] Utilizarea apelurilor Chainlink depreciate
ChainlinkCalculator
contractul este destinat să fie utilizat pentru a interoga oracolele Chainlink. O face prin apeluri către ei latestTimestamp
și latestAnswer
metode, ambele au fost depreciate. De fapt, metodele nu mai sunt prezente în API-ul agregatorilor Chainlink începând cu versiunea trei.
Pentru a evita potențialele incompatibilități viitoare cu oracolele Chainlink, luați în considerare utilizarea latestRoundData
metoda in schimb.
Actualizați: Fixat în cerere de tragere #67.
Note și informații suplimentare
[N01] Nu se importă interfețele
AggregatorInterface
interfața pare a fi un subset de cod din care copiat ChainLink
depozitul de cod public al lui. Interfața completă este inclusă în ChainLink
pachetul contract npm al lui.
Când este posibil, pentru a reduce potențialul de nepotrivire a interfeței și problemele rezultate, în loc să redefiniți și/sau să rescrieți interfețele altui proiect, luați în considerare utilizarea interfețelor instalate prin pachetele lor oficiale npm.
Actualizați: Fixat în cerere de tragere #66.
[N02] Dependențe de proiect depreciate
În timpul instalării dependențele proiectului, NPM avertizează că unul dintre pachetele instalate, Highlight
, „nu va mai fi acceptat și nu va mai primi actualizări de securitate în viitor”.
Chiar dacă este puțin probabil ca acest pachet să provoace un risc de securitate, luați în considerare actualizarea dependenței care utilizează acest pachet la o versiune menținută.
Actualizați: Fixat în cerere de tragere #64.
[N03] Apelurile externe pentru vizualizarea metodelor nu sunt apeluri statice
În cea mai mare parte a bazei de cod, protocolul efectuează în mod explicit apeluri externe prin OpenZeppelin functionStaticCall
metodă de a restrânge posibilitatea schimbărilor de stare atunci când acestea fie nu sunt așteptate, fie nu sunt de dorit. Cu toate acestea, în ChainlinkCalculator
contract, în ciuda intenției de a efectua apeluri externe numai către view
metode pe oracole Chainlink, apelurile externe în singlePrice
și doublePrice
funcțiile nu sunt realizate prin explicit staticcall
s.
Deși nu am identificat probleme de securitate imediate care decurg din aceasta, pentru a reduce suprafața de atac, a îmbunătăți consistența și a clarifica intenția, luați în considerare utilizarea explicită staticcall
s, pentru toate apelurile externe către view
funcții în ChainlinkCalculator
contracta.
Actualizați: Nereparat. Echipa de 1 inch spune:
Credem că complicația de sintaxă anulează îmbunătățirile în consistență.
[N04] Nu eșuează devreme cu comenzi nevalide
În OrderMixin
contractul, cel fillOrderTo
funcția gestionează condiția specială când o comandă nu a fost trimisă anterior (remainingMakerAmount == 0
), dar nu tratează în mod explicit condiția când comanda nu mai este valabilă (remainingMakerAmount == 1
).
În ultimul scenariu, funcția se va reveni în cele din urmă, dar numai după arderea unor cantități nebanale de gaz. Pentru a clarifica intenția, a crește lizibilitatea și a reduce consumul de gaz, luați în considerare gestionarea explicită a scenariului de ordine nevalidă la începutul funcției.
Actualizați: Fixat în cerere de tragere #68.
[N05] Contractele de ajutor nu sunt marcate ca abstract
În Solidity, cuvântul cheie abstract
este utilizat pentru contracte care fie nu sunt contracte funcționale în sine, fie nu sunt menite să fie utilizate ca atare. In schimb, abstract
contractele sunt moștenite de alte contracte din sistem pentru a crea contracte funcționale de sine stătătoare.
În întreaga bază de cod, există exemple de contracte de ajutor care nu sunt marcate ca abstracte, în ciuda faptului că nu sunt menite să fie implementate pe cont propriu. De exemplu, cel AmountCalculator
, ChainlinkCalculator
, ImmutableOwner
, NonceManager
, și PredicateHelper
contractele sunt toate compuse dintr-un set de bază de funcții care sunt destinate a fi utilizate de contractele moștenite.
Luați în considerare marcarea contractelor de ajutor ca abstract
pentru a indica în mod clar că acestea sunt concepute exclusiv pentru a adăuga funcționalitate contractelor care le moștenesc.
Actualizați: Nereparat. Echipa de 1 inch spune:
Acei ajutoare pot fi dislocați separat. Ele sunt moștenite doar pentru economii de gaze.
[N06] Ordinea neconsecventă a funcțiilor
De-a lungul bazei de cod, ordonarea funcțiilor urmează în general ordine recomandată în Ghidul de stil Solidity, care este: constructor
, fallback
, external
, public
, internal
, private
.
Cu toate acestea, în OrderMixin
contractul, cel public
checkPredicate
funcția se abate de la ghidul de stil, bisectând external
funcții.
Pentru a îmbunătăți lizibilitatea generală a proiectului, luați în considerare standardizarea ordonării funcțiilor în întreaga bază de cod, așa cum este recomandat de Solidity Style Guide.
Actualizați: Fixat în cerere de tragere #69.
[N07] Flux inconsecvent de umplere a comenzii
OrderMixin
și RFQOrderMixin
ambele contracte se ocupă de completarea comenzilor semnate, dar fluxul general de ordine între cele două contracte este inconsecvent.
OrderMixin
„s fillOrderTo
funcția urmează acest flux general (pseudo-cod):
if ((takingAmount == 0) == (makingAmount == 0))
else if (takingAmount == 0)
else (handle makingAmount == 0) THEN swapTokens
Întrucât RFQOrderMixin
e analog fillOrderRFQTo
funcția urmează acest flux (pseudo-cod):
if (takingAmount == 0 && makingAmount == 0)
else if (takingAmount == 0)
else if (makingAmount == 0)
else revert THEN swapTokens
Nu există informații din documentație cu privire la motivul pentru care primul condiționat din fiecare dintre aceste două funcții diferă sau de ce takingAmount
și makingAmount
nu pot fi ambele zero în această din urmă funcție. De asemenea, cazul în care atât a makingAmount
și takingAmount
sunt furnizate este mult mai ușor de raționat în fillOrderRFQTo
funcție, deoarece este tratată clar în finală else
bloc.
Pentru a clarifica intenția și pentru a crește lizibilitatea generală a codului, luați în considerare fie standardizarea fluxului general de ordine între aceste două contracte, fie documentarea explicită de ce există diferențele.
Actualizați: Nereparat. Echipa de 1 inch spune:
Acest lucru se datorează funcțiilor personalizate de stabilire a prețurilor în comenzile limită. De cand
getMakerAmount
poate diferi substanțial degetTakerAmount
, ne-am gândit că este mai bine să nu facem opțiunea implicită pentru utilizator, deoarece probabil îi va încurca în cazurile în care acești getters vor fi diferiți.
[N08] Mesajele de eroare sunt formatate inconsecvent sau care induc în eroare
De-a lungul bazei de cod, require
și revert
S-a constatat că mesajele de eroare, care sunt menite să informeze utilizatorii cu privire la condițiile particulare care duc la eșecul unei tranzacții, sunt formatate inconsecvent.
De exemplu, fiecare dintre mesajele de eroare de pe linii 85 din OrderMixin.sol
, 16 din ERC721ProxySafe.sol
, și 26 din Permitable.sol
folosește un stil diferit.
În plus, unele mesaje de eroare sunt înșelătoare:
Mesajele de eroare sunt menite să informeze utilizatorii cu privire la condițiile de eșec, astfel încât aceștia ar trebui să furnizeze suficiente informații pentru a putea fi făcute corecțiile corespunzătoare pentru a interacționa cu sistemul. Mesajele de eroare neinformative dăunează foarte mult experienței generale a utilizatorului, scăzând astfel calitatea sistemului. Mai mult, mesajele de eroare formatate inconsecvent pot introduce confuzii inutile. Prin urmare, luați în considerare revizuirea întregii baze de cod pentru a vă asigura că fiecare require
și revert
declarația are un mesaj de eroare care este formatat constant, precis, informativ și ușor de utilizat.
Actualizați: Parțial fixat în cerere de tragere #81.
[N09] Utilizarea inconsecventă a variabilelor de returnare numite
Există o utilizare inconsecventă a variabilelor de returnare numite în OrderMixin
contracta. Unele funcții returnează variabile numite, alții returnează valori explicite, si altii declară o variabilă de returnare numită, dar o suprascrie cu o declarație de returnare explicită.
Luați în considerare adoptarea unei abordări consecvente a valorilor returnate în întreaga bază de cod prin eliminarea tuturor variabilelor returnate numite, declarându-le în mod explicit ca variabile locale și adăugând instrucțiunile return necesare acolo unde este cazul. Acest lucru ar îmbunătăți atât caracterul explicit, cât și lizibilitatea codului și ar putea ajuta, de asemenea, la reducerea regresiilor în timpul refactorărilor de cod viitoare.
Actualizați: Fixat în cerere de tragere #73.
[N10] Calculul hash al comenzii nu este deschis pentru API
external
funcții remaining
, remainingRaw
și remainingsRaw
toți se așteaptă la un hash de comandă pentru o funcționare cu succes.
Cu toate acestea, funcția de ajutor _hash
, care returnează hash-ul unei comenzi, are private
vizibilitate. Aceasta înseamnă că utilizatorii vor trebui să împacheteze manual părți din comenzi și șiruri de domenii pentru a obține hash-ul unei comenzi.
Pentru a evita potențialul de greșeli la calcularea hash-urilor comenzii și pentru a oferi utilizatorilor o metodă de generare a hash-ului respectiv al unei comenzi, luați în considerare extinderea vizibilității _hash
funcție la public
și refactorizarea numelui la hash
pentru a fi în concordanță cu restul codului.
Actualizați: Fixat în cerere de tragere #74.
[N11] Supraîncărcarea semantică a cartografierii
_remaining
cartografiere în OrderMixin
contractul este supraîncărcat semantic pentru a urmări starea comenzilor și a cantității rămase de active disponibile pentru acele comenzi.
Cele trei stări pe care le poate prelua sunt:
0
: Hash-ul de comandă nu a fost încă văzut.1
: Comanda a fost fie anulată, fie complet completată.- Orice
uint
mai mare decat1
: RestulmakerAmount
disponibil pentru a fi completat la comanda plus1
.
Această supraîncărcare semantică necesită împachetarea și desfacerea acestei valori în timpul lookup
, cancellation
, initialization
, și storage
.
Supraîncărcarea semantică și logica necesară pentru activare pot fi predispuse la erori și pot face baza de cod mai greu de înțeles și de raționat, poate deschide, de asemenea, ușa pentru regresii în actualizările viitoare ale codului.
Pentru a îmbunătăți lizibilitatea codului, luați în considerare urmărirea stării de finalizare a comenzilor într-o mapare separată.
Actualizați: Nereparat. Echipa de 1 inch a menționat că o remediere ar crește costurile cu gazul pentru fillOrder
Funcția.
[N12] Comenzile cu permis permit apeluri la contracte arbitrare
OrderMixin
contractul moștenește Permitable
contract pentru a permite completarea ordinului cu o singură tranzacție cu active care acceptă astfel permit
solicită modificarea cotelor.
Cu toate acestea, apeluri la Permitable
contract nu validați dacă ținta este un activ permis și nici dacă este chiar un activ, ceea ce ar putea permite unui utilizator rău intenționat să transmită adresa unui contract arbitrar care ar putea executa un alt apel înainte de finalizarea comenzii.
Deși contractul este protejat împotriva reintrării, se recomandă întotdeauna reducerea suprafeței de atac și prevenirea apelării de contracte externe în timpul execuției. Luați în considerare fie să restricționați activul implicat în permis la activele implicate în comandă, fie la o listă albă de active pentru protocol.
Actualizați: Nereparat. Echipa de 1 inch spune:
OrderMixin
nu are de fapt informații despre jetoanele reale camakerAsset
șitakerAsset
uneori sunt proxy sau alte contracte intermediare, iar informațiile despre token-urile reale sunt stocate în niște octeți arbitrari. Deci nu există o modalitate viabilă de a restricționa ce activpermit
este chemat.
[N13] solhint
nu este niciodată reactivat
De-a lungul bazei de cod, există câteva solhint-disable
declarații, în special cele online 23 si on line 41 of RevertReasonParser.sol
, care nu sunt terminate cu solhint-enable
.
În favoarea explicitității și a fi cât mai restrictiv posibil atunci când dezactivați solhint
, ia în considerare utilizarea solhint-disable-line
or solhint-disable-next-line
în schimb, similar cu linia 16 din același dosar.
Actualizați: Fixat în cerere de tragere #72.
[N14] Greșeli de tipar
Baza de cod conține următoarele greșeli de scriere:
În plus, ale proiectului README
(în afara domeniului acestui audit) conține următoarele greșeli de scriere:
Luați în considerare corectarea acestor greșeli de scriere pentru a îmbunătăți lizibilitatea codului.
Actualizați: Fixat în cerere de tragere #71 și cerere de tragere #77.
[N15] Utilizarea uint
în loc de uint256
Pentru a favoriza claritatea, toate cazurile de uint
ar trebui declarat ca uint256
. În special, cei din for
bucle pe linii 98 și 119 of OrderMixin.sol
și linii 16 și 30 of PredicateHelper.sol
.
Actualizați: Fixat în cerere de tragere #70.
Concluzii
Au fost găsite 3 probleme de mare severitate. Au fost propuse unele modificări pentru a respecta cele mai bune practici și a reduce suprafața potențială de atac.
- &
- 7
- Despre Noi
- acces
- Conform
- Cont
- peste
- act
- acțiuni
- Suplimentar
- adresa
- Avantaj
- TOATE
- Permiterea
- deja
- Cu toate ca
- Sume
- analiză
- api
- abordare
- argumente
- în jurul
- activ
- Bunuri
- de audit
- Back-end
- Început
- fiind
- CEL MAI BUN
- Cele mai bune practici
- Pic
- roboţii
- construi
- apel
- pasă
- cazuri
- Provoca
- Za
- Schimbare
- control
- Verificări
- cod
- complex
- condiție
- confuzie
- construcţie
- conține
- contract
- contracte
- Corectarea
- Cheltuieli
- ar putea
- Cuplu
- creator
- Monedă
- Curent
- de date
- afacere
- Denial of Service
- Implementarea
- Amenajări
- Dezvoltatorii
- Dezvoltare
- FĂCUT
- diferi
- diferit
- domeniu
- dubla
- dinamic
- Devreme
- Margine
- încuraja
- mai ales
- ETH
- eveniment
- evenimente
- tot
- exemplu
- schimb
- de aşteptat
- experienţă
- Exploata
- DESCRIERE
- Domenii
- În cele din urmă
- First
- Repara
- Flexibilitate
- debit
- urma
- găsit
- Complet
- funcţie
- Fondurile
- viitor
- joc
- GAS
- General
- Oferirea
- mare
- ghida
- Manipularea
- hașiș
- hashing
- având în
- ajutor
- Înalt
- extrem de
- Cum
- HTTPS
- Hibrid
- identifica
- Impactul
- punerea în aplicare a
- important
- importatoare
- inclus
- Inclusiv
- Crește
- a crescut
- info
- informații
- Infrastructură
- perspective
- scop
- interes
- interfaţă
- implicat
- probleme de
- IT
- mare
- mai mare
- conduce
- conducere
- Bibliotecă
- Limitat
- Linie
- Lichiditate
- listat
- liste
- local
- uitat
- căutare
- major
- producător
- Efectuarea
- Piață
- MemPool
- oglindă
- model
- cele mai multe
- Cel mai popular
- și anume
- Funcții noi
- nefungibil
- jetoane non-fungibile
- oficial
- deschide
- Operațiuni
- Opțiune
- oracol
- comandă
- comenzilor
- Altele
- proprietar
- Model
- Popular
- prezenta
- prevenirea
- preţ
- de stabilire a prețurilor
- privat
- proces
- proiect
- Proiecte
- protecţie
- protocol
- furniza
- furnizează
- împuternicit
- public
- publica
- cumpărare
- calitate
- ridica
- Realitate
- reduce
- încredere
- raportează
- Rapoarte
- depozit
- Cerinţe
- REST
- REZULTATE
- Returnează
- revizuiască
- Risc
- runde
- Alerga
- sdk
- securitate
- Servicii
- set
- comun
- Acțiuni
- schimbare
- asemănător
- simplu
- mic
- inteligent
- Contracte inteligente
- So
- soliditate
- spam-
- specific
- Cheltuire
- Loc
- Începe
- Stat
- Declarație
- Statele
- Stare
- depozitare
- stil
- prezentat
- succes
- de succes
- Reușit
- a sustine
- Suportat
- Suprafață
- Intrerupator
- sistem
- Ţintă
- test
- Testarea
- teste
- Prin
- de-a lungul
- timp
- împreună
- semn
- indicativele
- urmări
- Urmărire
- tranzacție
- Încredere
- unic
- actualizări
- us
- uzabilitate
- USD
- USDT
- utilizatorii
- utilitate
- valoare
- Vizualizare
- vizibilitate
- aștepta
- Ce
- Listă albă
- în
- fără
- Apartamente
- valoare
- zero