Ledelsesoversigt
Dusa kontaktede Sayfer for at udføre en sikkerhedsrevision af deres smarte kontrakter.
Denne rapport dokumenterer forskningen udført af Sayfer rettet mod de udvalgte ressourcer, der er defineret under forskningsomfanget. Denne rapport viser især gennemgangen af sikkerhedsstilling for Dusas smarte kontrakter.
I løbet af undersøgelsesperioden på 4 uger opdagede vi 17 sårbarheder i kontrakten.
Alt i alt er Dusa en velbygget protokol. Det faktum, at det er afledt og oversat fra TraderJoe, gør det til en meget solid protokol med en ret almindelig arkitektur, men som anses for optimal. Vi har dog nogle få anbefalinger, som vi mener kan forbedre kvaliteten og sikkerheden af protokollen. Disse anbefalinger er beskrevet i afsnittet "Arkitekturgennemgang".
Som konklusion bør flere rettelser implementeres efter rapporten, men systemets sikkerhedsposition er kompetent.
Efter en gennemgang fra Sayfer-teamet bekræfter vi, at alle sikkerhedsproblemerne nævnt i denne rapport er blevet behandlet eller anerkendt af Dusa-teamet.
Risikometodologi
Hos Sayfer er vi forpligtet til at levere smart kontraktrevision af højeste kvalitet til vores kunder. Det er derfor, vi har implementeret en omfattende risikovurderingsmodel for at evaluere alvoren af vores resultater og give vores kunder de bedst mulige anbefalinger til afbødning.
Vores risikovurderingsmodel er baseret på to nøglefaktorer: IMPACT og SANDSYNLIGHED. Påvirkning refererer til den potentielle skade, der kan følge af et problem, såsom økonomisk tab, skade på omdømme eller et ikke-operativt system. Sandsynlighed refererer til sandsynligheden for, at et problem vil opstå under hensyntagen til faktorer som kontraktens kompleksitet og antallet af potentielle angribere.
Ved at kombinere disse to faktorer kan vi skabe en omfattende forståelse af den risiko, et bestemt problem udgør, og give vores kunder en klar og handlekraftig vurdering af problemets alvor. Denne tilgang giver os mulighed for at prioritere vores anbefalinger og sikre, at vores kunder får den bedst mulige rådgivning om, hvordan de beskytter deres smarte kontrakter.
Risiko er defineret som følger:

Sårbarheder efter risiko
Høj – Direkte trussel mod vigtige forretningsprocesser.
Medium – Indirekte trussel mod vigtige forretningsprocesser eller delvis trussel mod forretningsprocesser.
Lav - Der er ingen direkte trussel. Sårbarheden kan udnyttes ved hjælp af andre sårbarheder.
Informational – Denne konstatering indikerer ikke sårbarhed, men angiver en kommentar, der giver besked om designfejl og ukorrekt implementering, der kan forårsage et problem i det lange løb.
Tilgang
Protokoloversigt
Protokol introduktion
Dusa er en banebrydende decentraliseret finansprotokol (DeFi), der introducerer en fuldt decentraliseret og avanceret automatiseret market maker (AMM) oplevelse. Bygget på Massa blockchain, lægger Dusa vægt på nøgleprincipper såsom fuld decentralisering, tilgængelighed for alle brugerprofiler, interoperabilitet med fremtidige decentraliserede applikationer (DApps) og et stærkt engagement i sikkerhed og censurmodstand. Dens køreplan skitserer en trinvis tilgang, herunder forskning og udvikling, testning, incitamentbaserede quests og implementering af en decentraliseret udveksling (DEX). Dusas unikke funktioner inkluderer koncentreret likviditet, variable gebyrer, autonom likviditet og komplekse handelsordrer, alt sammen designet til at forbedre brugeroplevelsen og maksimere afkastet. Med et dedikeret team, strategiske investorer og rådgivere sigter Dusa efter at være pioner inden for vedtagelse af autonome smarte kontrakter og udvide sine decentraliserede løsninger til andre økosystemer.
Arkitektur gennemgang
Idet vi anerkender, at Dusa er et afledt af en veletableret løsning, TraderJoe, og stemmer overens med et anerkendt arkitektonisk mønster, bemærker vi begrænsede yderligere anbefalinger til den nuværende arkitektur. Vores evaluering af Dusa-protokolarkitekturen har imidlertid ført til et omfattende overblik, der kombinerer værdifuld indsigt med gennemtænkte anbefalinger til forbedringer:
- Fra et synspunkt om bedste praksis anbefaler vi at overveje implementeringen af en multisig-tegnebog til styring af privilegerede roller i fremtiden. Mens vi anerkender den nylige udgivelse af Massa multisig-koden (https://github.com/massalabs/massa-standards/tree/feature/multisig-sc/smart-contracts/assembly/contracts/multisig), råder vi til forsigtighed og betragter brugen af en standard privat nøgle også som en levedygtig mulighed for nuværende.
- En anden indsigtsfuld anbefaling foreslår at vedtage en samlet likviditetsmodel, der forestiller sig en global Vault/PoolManager i stedet for individuelle kontrakter pr. pulje. Dette strategiske skift, inspireret af de seneste fremskridt inden for AMM'er som Uniswap V4 og Balancer, lover betydelige fordele. Disse omfatter omkostningseffektive multihop-swaps og forbedret flashlånskapacitet, som tilskrives strømlinet adgang til hele likviditetspuljen.
Sikkerhedsvurdering
Dusa-specifikke tests
Da Dusa er i en unik situation med at være en afspejling af TraderJoe i et andet programmeringssprog, udførte vi flere yderligere test ud over vores sædvanlige for at sikre, at der ikke mangler dele. Her er en liste over test udført specifikt til Dusa-protokollen:
Sikkerhedskontrol
- Overløbs-/underløbstjek, især på grund af ændringen i kodebasen fra et sprog med standardtjek til et sprog, hvor der kræves eksplicit kontrol.
- Brug af sikre biblioteker (markeret_*).
- Overensstemmelse mellem kontrakter vedrørende strømmen af midler og opkald.
- Synlighed af funktioner for at sikre, at korrekte funktioner eksporteres.
- Implementering af adgangskontrol og beskyttelse af følsomme funktioner.
- Byt beskyttelse for at sikre interaktioner med likviditet mod glidning.
Godkendelse og godkendelse
- Revision af hele godkendelsesprocessen, ejerrettigheder og individuelle offentlige adgangspunkters godkendelsesskema.
- Identifikation af potentielle sårbarheder, der fører til ondsindede tilladelser for angribere.
Matematik og variabel håndtering
- Beregningsrelaterede problemer, især med flere typer variabler, casting og styring af flydende tal.
- Decimalfejl relateret til det unikke aspekt af MASSA med 9 decimaler.
- Håndtering af overløbs-/underløbsmuligheder.
Flash lån og likviditetsstyring
- Undersøgelse af typiske fejl i forbindelse med flashlån, herunder fejlberegninger og fondsblokering.
- Problemer relateret til fabriks- og pardannelse, såsom oprettelse af farlige puljer og likviditetsstyring.
- Verifikation af beregninger af likviditetsfjernelse under hensyntagen til gebyrer opnået under likviditetstilførsel.
Funktionalitet og implementering
- Implementering af swaps sammenlignet med andre DEX'er, med fokus på gebyrstyring og forskelle i tokentyper.
- Mulighed for DoS-angreb, når du opererer på usikre typer som vektorer eller arrays.
- Verifikation af centraliseringsproblemer, såsom potentiel indflydelse på priser, overførsler af brugertokener og konfigurationsændringer.
Kontekstdatahåndtering
- Tjek for at videregive de korrekte kontekstdata til funktioner for at undgå sårbarheder.
Generiske tests
Følgende testcases var retningslinjen under revisionen af systemet. Denne tjekliste er en ændret version af SCSVS v1.2, med forbedret grammatik, klarhed, kortfattethed og yderligere kriterier. Hvor der er et hul i nummereringen, blev et oprindeligt kriterium fjernet. Kriterier, der er markeret med en stjerne, er tilføjet af os.
Arkitektur, design og trusselsmodellering
| Arkitektur, design og trusselsmodellering | Testnavn |
| G1.2 | Hver introduceret designændring er forudgået af trusselsmodellering. |
| G1.3 | Dokumentationen definerer klart og præcist alle tillidsgrænser i kontrakten (tillidsforhold til andre kontrakter og væsentlige datastrømme). |
| G1.4 | SCSVS, sikkerhedskrav eller politik er tilgængelig for alle udviklere og testere. |
| G1.5 | Begivenhederne for de (statsændrende/afgørende for erhvervslivet) operationer er defineret. |
| G1.6 | Projektet omfatter en mekanisme, der midlertidigt kan stoppe følsomme funktionaliteter i tilfælde af et angreb. Denne mekanisme bør ikke blokere brugernes adgang til deres aktiver (f.eks. tokens). |
| G1.7 | Mængden af ubrugte kryptovalutaer, der opbevares på kontrakten, er kontrolleret og på det mindst acceptable niveau for ikke at blive et potentielt mål for et angreb. |
| G1.8 | Hvis fallback-funktionen kan kaldes af alle, er den inkluderet i trusselsmodellen. |
| G1.9 | Forretningslogikken er konsekvent. Vigtige ændringer i logikken bør anvendes i alle kontrakter. |
| G1.10 | Automatiske kodeanalyseværktøjer bruges til at opdage sårbarheder. |
| G1.11 | Den seneste større udgivelse af Solidity er brugt. |
| G1.12 | Ved brug af en ekstern implementering af en kontrakt anvendes den seneste version. |
| G1.13 | Når funktioner tilsidesættes for at udvide funktionaliteten, bruges supernøgleordet til at opretholde tidligere funktionalitet. |
| G1.14 | Arverækkefølgen er nøje specificeret. |
| G1.15 | Der er en komponent, der overvåger kontraktaktivitet ved hjælp af hændelser. |
| G1.16 | Trusselsmodellen omfatter hvaltransaktioner. |
| G1.17 | Lækage af én privat nøgle kompromitterer ikke sikkerheden for hele projektet. |
Politikker og procedurer
| Politikker og procedurer | Testnavn |
| G2.2 | Systemets sikkerhed er under konstant overvågning (f.eks. det forventede niveau af midler). |
| G2.3 | Der er en politik for at spore nye sikkerhedssårbarheder og at opdatere biblioteker til den seneste sikre version. |
| G2.4 | Sikkerhedsafdelingen kan kontaktes offentligt, og at proceduren for håndtering af rapporterede fejl (f.eks. grundig bug bounty) er veldefineret. |
| G2.5 | Processen med at tilføje nye komponenter til systemet er veldefineret. |
| G2.6 | Processen med større systemændringer involverer trusselsmodellering af en ekstern virksomhed. |
| G2.7 | Processen med at tilføje og opdatere komponenter til systemet omfatter en sikkerhedsrevision af en ekstern virksomhed. |
| G2.8 | I tilfælde af et hack er der en klar og velkendt afhjælpningsprocedure på plads. |
| G2.9 | Proceduren i tilfælde af et hack definerer klart, hvilke personer der skal udføre de påkrævede handlinger. |
| G2.10 | Proceduren omfatter alarmering af andre projekter om hacket gennem betroede kanaler. |
| G2.11 | Der er defineret en procedure for lækage af privat nøgle. |
opgradering
| opgradering | Testnavn |
| G3.2 | Før opgradering laves en emulering i en fork af hovednetværket, og alt fungerer som forventet på den lokale kopi. |
| G3.3 | Opgraderingsprocessen udføres af en multisig kontrakt, hvor mere end én person skal godkende operationen. |
| G3.4 | Timelocks bruges til vigtige operationer, så brugerne har tid til at observere kommende ændringer (bemærk venligst, at det kan være vanskeligere at fjerne potentielle sårbarheder i dette tilfælde). |
| G3.5 | initialisere() kan kun kaldes én gang. |
| G3.6 | initialisere() kan kun kaldes af en autoriseret rolle gennem passende modifikatorer (f initializer, eneste ejer). |
| G3.7 | Opdateringsprocessen udføres i en enkelt transaktion, så ingen kan køre den foran. |
| G3.8 | Opgraderbare kontrakter har reserveret hul på slots for at forhindre overskrivning. |
| G3.9 | Antallet af reserverede (som et mellemrum) slots er blevet reduceret passende, hvis nye variable er blevet tilføjet. |
| G3.10 | Der er ingen ændringer i den rækkefølge, som kontrakttilstandsvariablerne er deklareret i, eller deres typer. |
| G3.11 | Nye værdier returneret af funktionerne er de samme som i tidligere versioner af kontrakten (f ejer(), balanceOf(adresse)). |
| G3.12 | Implementeringen er initialiseret. |
| G3.13 | Implementeringen kan ikke ødelægges. |
Forretningslogik
| Forretningslogik | Testnavn |
| G4.2 | Implementeringen af kontraktlogikken og protokolparametrene svarer til dokumentationen. |
| G4.3 | Forretningslogikken fortsætter i en sekventiel trinrækkefølge, og det er ikke muligt at springe trin over eller at gøre det i en anden rækkefølge end designet. |
| G4.4 | Kontrakten har korrekt håndhævet forretningsgrænser. |
| G4.5 | Forretningslogikken er ikke afhængig af de værdier, der hentes fra upålidelige kontrakter (især når der er flere opkald til den samme kontrakt i et enkelt flow). |
| G4.6 | Forretningslogikken er ikke afhængig af kontraktens balance (f.eks. balance == 0). |
| G4.7 | Følsomme operationer afhænger ikke af blokdata (f.eks. bloker hash, tidsstempel). |
| G4.8 | Kontrakten bruger mekanismer, der afbøder transaktionsbestilling (front-running) angreb (f.eks. pre-commit-ordninger). |
| G4.9 | Kontrakten sender ikke penge automatisk, men lader brugere hæve penge i separate transaktioner i stedet. |
Adgangskontrol
| Adgangskontrol | Testnavn |
| G5.2 | Princippet om mindste privilegium opretholdes. Andre kontrakter bør kun have adgang til funktioner og data, som de har specifik autorisation til. |
| G5.3 | Nye kontrakter med adgang til den reviderede kontrakt overholder princippet om minimumsrettigheder som standard. Kontrakter bør have minimale eller ingen tilladelser, indtil der er eksplicit givet adgang til de nye funktioner. |
| G5.4 | Ophavsmanden af kontrakten overholder princippet om mindste privilegium, og deres rettigheder følger nøje dem, der er beskrevet i dokumentationen. |
| G5.5 | Kontrakten håndhæver adgangskontrolreglerne angivet i en betroet kontrakt, især hvis dApp-adgangskontrol på klientsiden er til stede og kan omgås. |
| G5.6 | Opkald til eksterne kontrakter er kun tilladt, hvis det er nødvendigt. |
| G5.7 | Modifikationskoden er klar og enkel. Logikken bør ikke indeholde eksterne opkald til upålidelige kontrakter. |
| G5.8 | Alle bruger- og dataattributter, der bruges af adgangskontrol, opbevares i betroede kontrakter og kan ikke manipuleres af andre kontrakter, medmindre det er specifikt godkendt. |
| G5.9 | Adgangskontrollerne fejler sikkert, også når der sker en tilbagevenden. |
| G5.10 | Hvis inputtet (funktionsparametre) er valideret, anvendes den positive valideringstilgang (hvidliste) hvor det er muligt. |
Kommunikation
| Kommunikation | Testnavn |
| G6.2 | Biblioteker, der ikke er en del af applikationen (men den smarte kontrakt er afhængig af at fungere), identificeres. |
| G6.3 | Delegeret opkald bruges ikke med upålidelige kontrakter. |
| G6.4 | Tredjepartskontrakter skygger ikke for særlige funktioner (f.eks. tilbagevenden). |
| G6.5 | Kontrakten kontrollerer ikke, om adressen er en kontrakt, der bruger extcodesize opcode. |
| G6.6 | Re-entrancy-angreb afbødes ved at blokere rekursive opkald fra andre kontrakter og følge mønsteret Check-Effects-Interactions. Brug ikke send-funktionen, medmindre det er et must. |
| G6.7 | Resultatet af funktionskald på lavt niveau (f sende, delegere opkald, ringe) fra andre kontrakter kontrolleres. |
| G6.8 | Kontrakten er afhængig af data leveret af den rigtige afsender og er ikke afhængig af tx.origin værdi. |
Aritmetik
| Aritmetik | Testnavn |
| G7.2 | Værdierne og matematiske operationer er modstandsdygtige over for heltalsoverløb. Brug SafeMath-biblioteket til aritmetiske operationer før solidity 0.8.*. |
| G7.3 | De umarkerede kodestykker fra Solidity ≥ 0.8.* introducerer ikke heltal under/overløb. |
| G7.4 | Ekstreme værdier (f.eks. maksimum- og minimumværdier af variabeltypen) tages i betragtning og ændrer ikke kontraktens logiske flow |
| G7.5 | Ikke-streng ulighed bruges til balance lighed. |
| G7.6 | Der anvendes korrekte størrelsesordener i beregningerne. |
| G7.7 | Ved beregninger udføres multiplikation før division for nøjagtighed. |
| G7.8 | Kontrakten forudsætter ikke fastpunktspræcision og bruger en multiplikator eller gemmer både tæller og nævner. |
Denial of Service
| Denial of Service | Testnavn |
| G8.2 | Kontrakten itererer ikke over ubundne sløjfer. |
| G8.3 | Selvdestruktionsfunktionalitet bruges kun hvis det er nødvendigt. Hvis det er inkluderet i kontrakten, skal det tydeligt beskrives i dokumentationen. |
| G8.4 | Forretningslogikken blokeres ikke, hvis en aktør (f.eks. kontrakt, konto, orakel) er fraværende. |
| G8.5 | Forretningslogikken afskrækker ikke brugerne til at bruge kontrakter (f.eks. er transaktionsomkostningerne højere end fortjenesten). |
| G8.6 | Udtryk af funktioner hævder eller kræver har en bestået variant. |
| G8.7 | Hvis reservefunktionen ikke kan kaldes af nogen, blokerer den ikke kontraktfunktioner. |
| G8.8 | Der er ingen dyre operationer i en løkke. |
| G8.9 | Der er ingen opkald til upålidelige kontrakter i en løkke. |
| G8.10 | Hvis der er mulighed for at indstille driften af kontrakten, er det også muligt at genoptage den. |
| G8.11 | Hvis der bruges hvidlister og sortlister, forstyrrer de ikke normal drift af systemet. |
| G8.12 | Der er ingen DoS forårsaget af overløb og underløb. |
Blockchain data
| Blockchain data | Testnavn |
| G9.2 | Eventuelle gemte data i kontrakter betragtes ikke som sikre eller private (selv private variabler). |
| G9.3 | Der gemmes ingen fortrolige data i blockchainen (adgangskoder, personlige data, token osv.). |
| G9.4 | Kontrakter bruger ikke strengliteraler som nøgler til tilknytninger. Globale konstanter bruges i stedet for at forhindre Homoglyph-angreb. |
| G9.5 | Kontrakt genererer ikke trivielt pseudotilfældige tal baseret på informationen fra blockchain (f.eks. seeding med bloknummeret). |
Gasforbrug og begrænsninger
| Gasforbrug og begrænsninger | Testnavn |
| G10.1 | Gasforbrug er forudset, defineret og har klare begrænsninger, som ikke kan overskrides. Både kodestruktur og ondsindet input bør ikke forårsage gasudmattelse. |
| G10.2 | Funktionsudførelse og funktionalitet afhænger ikke af hårdkodede gasgebyrer (de er bundet til at variere). |
Klarhed og læsbarhed
| Klarhed og læsbarhed | Testnavn |
| G11.2 | Logikken er klar og modulopbygget i flere simple kontrakter og funktioner. |
| G11.3 | Hver kontrakt har en kort kommentar på 1-2 sætninger, der forklarer dens formål og funktionalitet. |
| G11.4 | Der anvendes hyldeimplementeringer, dette fremgår tydeligt af kommentaren. Hvis disse implementeringer er blevet ændret, noteres ændringerne i hele kontrakten. |
| G11.5 | Arverækkefølgen tages i betragtning i kontrakter, der anvender flere arve- og skyggefunktioner. |
| G11.6 | Hvor det er muligt, bruger kontrakter eksisterende testet kode (f.eks. token-kontrakter eller mekanismer som f.eks ejerskabelig) i stedet for at implementere deres egne. |
| G11.7 | Konsekvente navnemønstre følges gennem hele projektet. |
| G11.8 | Variabler har karakteristiske navne. |
| G11.9 | Alle lagervariabler initialiseres. |
| G11.10 | Funktioner med specificeret returtype returnerer en værdi af denne type. |
| G11.11 | Alle funktioner og variabler bruges. |
| G11.12 | kræver bruges i stedet for tilbage in if udsagn. |
| G11.13 | hævde funktionen bruges til at teste for interne fejl og kræver funktion bruges til at sikre en gyldig tilstand i input fra brugere og eksterne kontrakter. |
| G11.14 | Montagekode bruges kun hvis det er nødvendigt. |
Test dækning
| Test dækning | Testnavn |
| G12.2 | Misbrugsfortællinger beskrevet i trusselsmodellen er dækket af enhedstests |
| G12.3 | Følsomme funktioner i verificerede kontrakter afdækkes med test i udviklingsfasen. |
| G12.4 | Implementering af verificerede kontrakter er blevet kontrolleret for sikkerhedssårbarheder ved hjælp af både statisk og dynamisk analyse. |
| G12.5 | Kontraktspecifikationen er formelt verificeret |
| G12.6 | Specifikationen og resultaterne af den formelle verifikation er inkluderet i dokumentationen. |
Decentraliseret finansiering
| Decentraliseret finansiering | Testnavn |
| G13.1 | Långiverens kontrakt antager ikke, at dens saldo (brugt til at bekræfte tilbagebetaling af lån) kun ændres med sine egne funktioner. |
| G13.2 | Funktioner, der ændrer långiveres saldo og/eller udlåner kryptovaluta, er ikke-re-entrant, hvis den smarte kontrakt giver mulighed for at låne hovedplatformens kryptovaluta (f.eks. Ethereum). Det blokerer de angreb, der opdaterer låntagers saldo under udførelsen af flashlånet. |
| G13.3 | Flash-lånsfunktioner kan kun kalde foruddefinerede funktioner på den modtagende kontrakt. Hvis det er muligt, skal du definere en betroet undergruppe af kontrakter, der skal kaldes. Normalt er afsenderkontrakten (lånekontrakten) den, der skal ringes tilbage. |
| G13.4 | Hvis det inkluderer potentielt farlige operationer (f.eks. tilbagesendelse af flere ETH/tokens end lånte), kan modtagerens funktion, der håndterer lånt ETH eller tokens, kun kaldes af puljen og inden for en proces, der er initieret af den modtagende kontrakts ejer eller en anden betroet kilde (f.eks. multisig). |
| G13.5 | Beregninger af likviditetspuljeandel udføres med den højest mulige præcision (f.eks. hvis bidraget beregnes for ETH skal det ske med 18-cifret præcision – for Wei, ikke Ether). Udbyttet skal ganges med 10 i potensen af antallet af decimaltal (f.eks. udbytte * 10^18 / divisor). |
| G13.6 | Belønninger kan ikke beregnes og distribueres inden for det samme funktionskald, som indsætter tokens (det bør også defineres som ikke-genindtrædende). Dette beskytter mod kortvarige udsving i aktier. |
| G13.7 | Regeringskontrakter er beskyttet mod flashlånsangreb. En mulig afbødningsteknik er at kræve processen med at deponere governance-tokens og foreslå en ændring, der skal udføres i forskellige transaktioner inkluderet i forskellige blokke. |
| G13.8 | Når du bruger on-chain orakler, er kontrakter i stand til at sætte operationer på pause baseret på oraklernes resultat (i tilfælde af et kompromitteret orakel). |
| G13.9 | Eksterne kontrakter (selv betroede), der har tilladelse til at ændre attributterne for en projektkontrakt (f.eks. symbolsk pris), har følgende begrænsninger implementeret: tærskler for ændringen (f.eks. ikke mere/mindre end 5%) og en grænse for opdateringer (f.eks. én opdatering pr. dag). |
| G13.10 | Kontraktattributter, der kan opdateres af de eksterne kontrakter (selv betroede) overvåges (f.eks. ved hjælp af hændelser), og en hændelsesprocedure implementeres (f.eks. under et igangværende angreb). |
| G13.11 | Komplekse matematiske operationer, der består af både multiplikation og division, udfører først multiplikationer og derefter division. |
| G13.12 | Ved beregning af valutakurser (f.eks. ETH til token eller omvendt), ganges tælleren og nævneren med reserverne (se getInputPrice funktion i UniswapExchange kontrakt). |
Bestil revision hos Sayfer
Revisionsresultater
[H] Frontløbsrisiko ved oprettelse af et nyt par
| ID | SIG-01 |
| Status | Fast |
| Risiko | Høj |
| Forretning Impact | I nogle tilfælde kan brugere miste de midler, de indsatte for at finansiere oprettelsen af par. Enten kan en ondsindet frontløber oprette et par på bekostning af en anden bruger, eller flere brugere kan forsøge at oprette et par på samme tid, lykkes eller fejler tilfældigt. |
| Lokation |
|
Beskrivelse
For at oprette et nyt par, skal brugeren ringe Router::createLBPair(StaticArray ). Under motorhjelmen kalder denne funktion Factory::createLBPair(StaticArray ), som igen kalder Massa's transferCoins (adresse, nummer).
- Factory.ts:264; createLBPair(StaticArray )
transferCoins(_pair._origin, 200 * ONE_COIN);
Ifølge dokumentation, overfører denne funktion simpelthen mønter fra den aktuelle adresse til en given adresse. Det betyder, at disse midler på forhånd skal sendes til Fabrik. På den anden side har brugerne mulighed for at ringe oprette Par fra router, som er standardindgangspunktet for andre operationer. Men hvis de indsættes i en separat transaktion, er der mulighed for, at nogen, forsætligt eller på anden måde, også ringer createLBPair(StaticArray ).
Når en blok med transaktioner er afsluttet, vil de blive lagt ud i en ukendt rækkefølge. Derefter vil den første transaktion inkluderet, få disse midler overført fra fabrikken til et nyt par, mens den anden bruger (sidstnævnte transaktion) vil få deres transaktion tilbageført på grund af mangel på tilgængelige midler.
Mitigation
Finansieringen af paroprettelse skal faktisk finde sted i den samme transaktion for at undgå problemer med genbestilling af transaktioner.
For eksempel kunne en af måderne at opnå det på være en mekanisme, der kontrollerer fabrikssaldoen og puljesaldoen ved slutningen af en funktion og sender overskuddet tilbage, svarende til dette https://github.com/massalabs/coin-vester/blob/master/smart-contract/assembly/contracts/main.ts#L34
Mekanismen vil være på plads i oprette LBPair funktion (af Fabrik), i konstruktør, mynte, brænde, indsamle Gebyrer, øge OracleLængde, sikker Overførsel Fra & sikkerBatchTransferFrom (parret). Dette er de funktioner, der kan bruge Massa til opbevaring, da de kan oprette nye poster i lageret (det koster ikke noget at ændre lageret). Funktioner, der interagerer med disse funktioner, skal også have denne mekanisme.
De kan opdeles i to forskellige slags:
- Funktioner, der interagerer med disse, og som ikke interagerer med WMAS (oprette LBPair fra router og fabrik + tilføje likviditet, fjerne likviditet) vil overføre alle overførte Mønter, gem saldoen på SC i en konstant, og efter SC-opkaldet overføres forskellen mellem den nye saldo og den gemte saldo tilbage til den, der ringer.
- Funktioner, der interagerer med disse, og som interagerer med WMAS (addLiquidityMAS, fjerne LiquidityMAS) skal bruge en parameter mere for at kende antallet af mønter, der skal pakkes ind, vil du sende forskellen mellem overførte Mønter og dette nummer i opkaldet. Resten af mekanismen i disse funktioner vil være den samme som den lige før.
[H] Midler, der er indbetalt til oprettelse af par, kan gå tabt
| ID | SIG-02 |
| Status | Fast |
| Risiko | Høj |
| Virksomhedseffekt | Brugere, der indbetaler penge til routeren for at oprette et par, kan miste deres penge uden at se et resultat. Vi vurderede dette problem som højt (snarere end kritisk), fordi der findes et alternativt arbejdsflow – kaldende factory::createLBPair(StaticArray ) direkte med midlerne. |
| Lokation |
|
Beskrivelse
Dette problem er et resultat af, hvordan paroprettelse er designet. En bruger kan ringe Router::createLBPair(StaticArray ) og da en oprettelse af et par kræver en indbetaling, kan han vedhæfte penge til funktionsopkaldet, hvilket lyder som en intuitiv løsning.
Men hvis brugeren gør det, vil pengene aldrig nå parret og vil gå tabt i kontrakten (selv om det kan reddes af ejeren). Dette skyldes, at de vil sidde fast i Router-kontrakten, mens pardannelsen foregår i Fabrikskontrakten, hvor transferCoins(), som trækker penge fra den nuværende (fabrikkens) adresse, bruges i stedet.
- Factory.ts:264; createLBPair(StaticArray )
transferCoins(_pair._origin, 200 * ONE_COIN);
Da det er implementeret på fabrikken, vil midler, der sendes til routeren, ikke nå frem til fabrikken, som heller ikke har midlerne til at oprette et par og vende tilbage.
Mitigation
En mulighed er at implementere løsningen foreslået i SIG-01.
Omvendt Fabriks.ts kan kaldes direkte for at oprette par og kræve, at brugerne sender enten det nøjagtige påkrævede beløb sammen med funktionsopkaldet, ELLER i det mindste det nødvendige beløb med tilbagebetaling af eventuelle overskydende midler, der er sendt.
[M] Flere par af samme type kan fortynde likviditeten
| ID | SIG-03 |
| Status | Fast |
| Risiko | Medium |
| Virksomhedseffekt | Hvis en AMM-applikation giver mulighed for at oprette flere puljer med de samme parametre, kan likviditeten fortyndes på tværs af disse puljer, i stedet for at være koncentreret i kun én. Dette kan påvirke brugerne negativt og kan resultere i mindre gunstige handler, der er tilgængelige for protokolbrugere.
Derudover vil det forrige par ikke længere blive brugt til routing. Dette kan resultere i likviditet eller kursmanipulation. |
| Lokation |
|
Beskrivelse
Når du opretter et nyt par, er der ingen kontrol, om præcis det samme par allerede eksisterer. Dette kan sprede brugernes likviditet på tværs af flere tilsvarende puljer. Puljer med lav likviditet er mere tilbøjelige til prismanipulationer og tilbyder mindre gunstige handler og bør derfor undgås.
Mitigation
Tjek, om et par af bestemte parametre allerede eksisterer ved oprettelse af par, hvis det er tilfældet, skal du vende tilbage.
[L] Præcis saldokontrol efter et flashlån kan blive misbrugt
| ID | SIG-04 |
| Status | Fast |
| Risiko | Lav |
| Virksomhedseffekt | En flashlånsmodtager udfører muligvis eksterne opkald i tilbagekaldet. Fordi systemet kræver, at saldoen efter flashlånet er nøjagtigt saldoen før plus gebyrerne, kan disse eksterne kontrakter overføre et meget lille beløb til parret under udførelsen for at sikre, at flashlånet mislykkes (hvilket kan være rentabelt for dem i visse situationer). |
| Lokation |
|
Beskrivelse
Efter et flashlån kræver systemet, at saldoen præcis er balancen før flashlånet plus gebyrer.
- flashLoan(StaticArray )
assert(
_balanceAfter == SafeMath256.add(_balanceBefore, _fees.total),
LBPair__FlashLoanInvalidBalance(),
);
Typisk kræves det, at saldoen er større, da det er restriktivt at kræve et nøjagtigt match.
Mitigation
Tjek kun, om saldoen er større end saldoen før flashlånet plus gebyrer. Dette er også den logik, som TraderJoe bruger i deres flashlånsfunktion.
[L] Ignorering af et LB-par udsender ikke en hændelse
| ID | SIG-05 |
| Status | Fast |
| Risiko | Lav |
| Forretning Impact | Off-chain indeksere kan modtage forkerte oplysninger, hvilket fører til forkerte beregninger. |
| Lokation |
|
Beskrivelse
funktionen setLBPairIgnored(StaticArray ) kan bruges til at kontrollere, om et par skal ignoreres til routing eller ej. Enhver ændring i flaget via denne funktion udsender begivenheden SET_LBPAIR_IGNORED. Det er dog også muligt at ændre flaget via setLBPairInformation(StaticArray ), som ikke udsender en begivenhed.
Mitigation
[L] Inkonsekvent gebyropkrævning
| ID | SIG-06 |
| Status | anerkendt |
| Risiko | Lav |
| Forretning Impact | Enhver bruger kan udløse gebyropkrævningen for andre brugere, hvorimod protokolgebyropkrævningen kun kan udløses af ejeren. |
| Lokation |
|
Beskrivelse
Alle kan ringe collectFees(StaticArray ) for enhver adresse for at fordele gebyrerne til denne adresse. Dette kan være uønsket for visse brugere, der ønsker at kontrollere, hvornår gebyrerne fordeles til dem.
Dette er desuden inkonsekvent med collectProtocolFees(StaticArray ), som kun kan ringes op af modtageren.
- collectProtocolFees(StaticArray )
assert(
Context.caller().equals(_feeRecipient),
LBPair__OnlyFeeRecipient(_feeRecipient, Context.caller()),
);
Mitigation
[L] Inkonsekvent brug af SafeMath
| ID | SIG-07 |
| Status | Fast |
| Risiko | Lav |
| Forretning Impact | Overløb eller underløb i koden kan føre til uventede tilbagevendinger og/eller fejlberegninger. |
| Lokation | — |
Beskrivelse
Selvom SafeMath bruges mange steder, efterlades visse funktioner, der anvender regneoperationer, ubeskyttede, hvilket som følge heraf kan føre til overløb eller underløb.
Mitigation
[L] Ineffektiv aktivopregning
| ID | SIG-08 |
| Status | Fast |
| Risiko | Lav |
| Forretning Impact | Nogle fabriksfunktioner vil bruge mere gas end nødvendigt. I værste fald, hvis ejeren registrerer en meget stor mængde aktiver, kan det føre til en DoS. Men dette er usandsynligt. |
| Lokation |
|
Beskrivelse
her er to problemer med denne funktion:
- Sløjfen går ikke i stykker efter at have fundet et aktiv og itererer unødvendigt over resten af arrayet. Altså enhver sag is det værste tilfælde.
- En kortlægning ville være mere effektiv her, da den har et konstant tidsopslag.
- isQuoteAsset(adresse)
for (let i = 0; i < quoteAssets.length; i++) {
if (quoteAssets[i].equals(_token)) {
isQuoteAsset = true;
}
}
Mitigation
Der er to løsninger her:
- Behold den nuværende lineære søgealgoritme og tilføj blot en pause i if blokere efter indstilling isQuoteAsset til sandt.
- En bedre løsning ville være at skifte over til en kortlægning. Når et nyt token tilføjes til systemet, quoteAssets[token] skal indstilles til sand. Fremover kan den tilgås, når det er nødvendigt - det er ikke nødvendigt at søge efter det. Måske kan hele funktionen blot refaktoreres ud.
[L] Maksimalt flashlånsgebyr er ikke angivet efter implementering
| ID | SIG-09 |
| Status | Fast |
| Risiko | Lav |
| Forretning Impact | Det er muligt at have et flashlånsgebyr, der er højere end MAX_FEE. |
| Lokation |
|
Beskrivelse
Når flashlånsgebyret er indstillet ved hjælp af setFlashLoanFee(), er det valideret, at det er mindre end værdien MAX_FEE. Dette tjek udføres dog ikke, når kontrakten initialiseres, og det er muligt at sætte et vilkårligt højt flashlånsgebyr der.
Mitigation
[L] Ufuldstændig glidebeskyttelse – Manglende fristkontrol
| ID | SIG-10 |
| Status | Fast |
| Risiko | Lav |
| Forretning Impact | Der er en øget sandsynlighed for, at brugere vil få mindre gunstige handler, når de bruger AMM. |
| Lokation | Router.ts
|
Beskrivelse
Skridning er et resultat af en volatilitet i AMM-type løsninger, og betyder ganske enkelt, at prisen ved anmodning om en handel/swap/likviditetsændring er anderledes, end når transaktionen udføres. For at beskytte brugere mod enorm udskridning, som kan være naturlig eller et resultat af forsætlige angreb som Sandwiching, er der to generiske typer beskyttelse: minimal mængde, som er til stede, og deadline check, som mangler.
Disse kontroller bør implementeres på enhver swap, likviditetstilførsel og fjernelse, da de alle er genstand for glidning.
Et deadline-tjek tillader simpelthen ikke, at transaktionen inkluderes efter et bestemt tidspunkt, hvilket for eksempel med vilje kan inkluderes senere af en ondsindet blokbygger for stadig at forsøge at udføre transaktionen under mindre gunstige prisforhold. Men da et minimalt tokenbeløb er kontrolleret, er virkningen af dette problem begrænset.
Mitigation
Implement _ensure(deadline) på samme måde er det allerede til stede i alle andre funktioner, der beskæftiger sig med likviditet.
[L] Et-trins ejerskabsoverdragelse
| ID | SIG-11 |
| Status | Fast |
| Risiko | Lav |
| Forretning Impact | Angivelse af en forkert adresse kan føre til uigenkaldeligt tab af kontraktejerskab. |
| Lokation |
|
Beskrivelse
In Fabriks.ts, opnås ejerskifte ved, at den gamle ejer ringer til transferEjerskab([u8]) med den nye ejer. Funktionen ændrer derefter EJER tilstandsvariabel.
- transferEjerskab([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());
}
Mitigation
Vi anbefaler at implementere en to-trins proces for ejerskabsoverdragelse. Dette er i overensstemmelse med bredt anerkendt god praksis og kan forhindre utilsigtede overførsler. For at illustrere vil vi bruge OpenZepplins implementering.
En to-trins ejerskabsoverdragelse kræver først, at den nuværende ejer påbegynder overførslen.
function transferOwnership(address newOwner) public virtual override onlyOwner {
_pendingOwner = newOwner;
emit OwnershipTransferStarted(owner(), newOwner);
}
Men for at fuldføre processen, skal den nye ejer godkende overdragelsen.
function acceptOwnership() public virtual {
address sender = _msgSender();
if (pendingOwner() != sender) {
revert OwnableUnauthorizedAccount(sender);
}
_transferOwnership(sender);
}
Dette sikrer, at den nye ejer er det tilsigtede mål.
[I] Utilstrækkelig hændelsesemission
| ID | SIG-12 |
| Status | Fast |
| Risiko | Informational |
| Forretning Impact | Nedsat sporbarhed og synlighed af historiske nøgletilstandsændringer, der påvirker protokollen. |
| Lokation | Fabriks.ts
|
Beskrivelse
Nogle af nøgletilstandsændringerne i protokollen udsender ikke en tilknyttet hændelse.
Bemærk: transferOwnership(bs: StaticArray ) udsender en begivenhed, men kun for _setFeeRecipient.
Mitigation
[I] Gettere og Settere er blandet sammen med eksterne funktioner
| ID | SIG-13 |
| Status | Fast |
| Risiko | Informational |
| Forretning Impact | Blanding, gettere, sættere, indgangspunkter og interne funktioner gør koden mindre læsbar. |
| Lokation |
|
Beskrivelse
Visse kontrakter har separate sektioner, der indeholder funktioner, der ændrer tilstanden (sættere), læser den (gettere) eller er en del af funktionsopkaldstræet (internt).
I nogle kontrakter er denne rækkefølge dog forstyrret – funktionerne er blandet sammen. Nogle gange blandes eksporterede funktioner (indgangspunkter) også sammen med interne.
Mitigation
[I] Mangel på enhedstests
| ID | SIG-14 |
| Status | anerkendt |
| Risiko | Informational |
| Forretning Impact | Testscenarier og enhedstest hjælper udviklere med at opdage fejl og sårbarheder, som ellers ville glide forbi i en simpel statisk analyse. Dynamisk test er uvurderlig for at sikre kvaliteten af det færdige produkt. |
| Lokation | — |
Beskrivelse
Bortset fra et dusin tests for en række biblioteksfunktioner, havde koden ikke enheds-, funktions- eller integrationstests. Ikke alle fejl kan opdages ved simpel statisk analyse, hvilket efterlader produktet i en usikker position.
Mitigation
Det anses for god praksis at sikre, at kodedækningen for tests er så høj som muligt, og at testscenarier inkluderer både glade og ulykkelige veje.
[I] Unødvendig kode
| ID | SIG-15 |
| Status | Fast |
| Risiko | Informational |
| Forretning Impact | Dette problem har ingen direkte indflydelse på koden eller på protokollen og blev derfor klassificeret som informativt. |
| Lokation | Router.ts:770-772; _getAmountsIn(u64[], Adresse[], IERC20[], u256) |
Beskrivelse
funktionen _getAmountsIn() tager bin-trinene som et argument og udfører følgende kontrol:
- _getAmountsIn(u64[], Adresse[], IERC20[], u256)
if (_binStep == 0) {
// means TraderJoe V1 swap
} else {
...
}
Dette er dog unødvendigt. Systemet understøtter ikke bytte af V1-stil, og resten af funktionen betragter ikke bin-trinene, da den modtager parrene (svarende til bin-trinene) som et ekstra argument.
Mitigation
[I] Ubrugte importvarer
| ID | SIG-16 |
| Status | Fast |
| Risiko | Informational |
| Forretning Impact | Dette problem har ingen direkte indflydelse på koden eller på protokollen og blev derfor klassificeret som informativt. |
| Lokation |
|
Beskrivelse
Den angivne import ser ud til aldrig at blive brugt i deres respektive kontrakter. De kunne fjernes.
Mitigation
[I] Brug af 'Magiske tal'
| ID | SIG-17 |
| Status | anerkendt |
| Risiko | Informational |
| Forretning Impact | Dette kan øge vanskeligheden ved at parse koden for ukendte læsere. |
| Lokation |
|
Beskrivelse
Flere steder anvender kontrakten talværdier, som ikke er veldokumenterede, beskrevet eller kommenteret.
Mitigation
Tilføj kommentarer, der forklarer valget af konstanter.




