Ledelsesoversigt
Dimo kontaktede Sayfer for at udføre en sikkerhedsrevision af deres smarte kontrakt.
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 Dimos smarte kontrakt.
I løbet af forskningsperioden på 40 forskningstimer opdagede vi 14 sårbarheder i kontrakten. Ingen af dem er kritiske.
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 løst af Dimo-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
DIMO er en web3 IoT-virksomhed, der giver brugere og udviklere mulighed for at udnytte den rige strøm af data, der genereres af moderne køretøjer. Dens løsning er et brugerejet økosystem, der giver chauffører mulighed for at høste økonomiske fordele af deres data og muliggøre applikationer som parametrisk forsikring, peer-to-peer bildeling og køretøjsmarkedspladser. Den decentraliserede platform giver også udviklere ro i sindet, idet de ved, at deres adgang til dataene ikke er underlagt en centraliseret gatekeepers luner. Denne løsning er bygget på Polygon.
Sikkerhedsvurdering
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] Ændring af Genesis Time kan potentielt forstyrre belønningsfordelingen
| ID | SIG-01 |
| Status | Fast |
| Risiko | Høj |
| Forretning Impact | rewardsGenesisTime er en kritisk variabel, der sporer tidspunktet, hvor belønningerne blev startet og dermed styrer belønningsfordelingen.
Graden af belønninger fortsætter med at falde over tid og langsomt reduceres til 85% af den foregående cyklus på et tidspunkt i fremtiden. Derfor kan nulstilling af genesis-tiden efter påbegyndt belønningsfordeling forstyrre hele ordningen. |
| Lokation | – Reward.sol; resetRewardsGenesisTime() – Reward.sol; manueltSetRewardsGenesisTime(uint256) |
Beskrivelse
Ændring rewardsGenesisTime senere i cyklussen vil senere påvirke de afgørende variabler for nuværende uge og ugegrænse og kan potentielt ødelægge hele belønningsfordelingsordningen og dens forventede tidsplan.
Mitigation
En mulig afbødning er at revidere disse funktioner, således at nulstilling af genesetiden kun er mulig, før belønningsfordelingen er startet:
function resetRewardsGenesisTime() external onlyRole(ADMIN_ROLE) {
require(dimoTotalSentOutByContract==0,"Reward Distribution already started");
rewardsGenesisTime = block.timestamp;
}
Hvis det er nødvendigt at nulstille eller ændre variablen efter kendsgerningen, kan det måske håndteres på en kontrolleret og forudsigelig måde i kæden i stedet for at tillade administratorer vilkårlig kontrol.
[H] Umarkeret administratortilbagetrækning
| ID | SIG-02 |
| Status | Fast |
| Risiko | Høj |
| Virksomhedseffekt | Mens administratorkonti per definition gives en grad af tillid, kan de, hvis de kompromitteres, bruges til at dræne kontrakten for dens midler ved hjælp af denne funktion. |
| Lokation | – Reward.sol; adminWithdraw(adresse, uint256) |
Beskrivelse
funktionen adminWithdraw(address, uint256) tillader administratorer at sende kontraktmidler til brugere uden begrænsning. Ifølge dokumentationen bruges dette, hvis brugere sender DIMO til kontrakten uden at satse. Vi mener dog, at denne funktion kan være udsat for misbrug, som forklaret i afsnittet om forretningspåvirkning.
Mitigation
En tænkelig måde at øge sikkerheden på er at indsende en anmodning på vegne af en bruger, måske ved at bruge en konto med orakelrollen. En administrator skal derefter godkende transaktionen. Dette kræver mindst to konti for at godkende sådanne transaktioner, hvilket giver endnu et lag af sikkerhed.
[H] Administratorer kan nulstille registreringsdatabasen efter behag
| ID | SIG-03 |
| Status | anerkendt |
| Risiko | Høj |
| Virksomhedseffekt | Registry er det sted, hvor brugerdata gemmes og valideringer udføres. Hvis registreringsdatabasen nulstilles, stopper eksisterende brugere med at modtage belønninger, medmindre dataene migreres til den nye registreringsdatabase. |
| Lokation | – Reward.sol; sætRegistryContractAddress(adresse) |
Beskrivelse
setRegistryContractAddress(address) giver administratorer mulighed for at nulstille registreringsdatabasen adresse efter behag.
Mitigation
En løsning er at sikre, at denne funktion vender tilbage, medmindre registreringsdatabasen ikke er indstillet i første omgang.
function setRegistryContractAddress(
address registryContractAddress
) external onlyRole(ADMIN_ROLE) {
require(
registryContractAddress != address(0),
"registryContractAddress is an invalid zero address"
);
require(address(registry)==address(0)),"already set, cannot be set again")
registry = IRegistry(registryContractAddress);
}
En anden løsning er at opsætte en datamigreringsprocedure. Hvis en sådan procedure allerede er på plads, kan denne konstatering med sikkerhed ignoreres.
[I] Deployer har både administrator- og Oracle-roller
| ID | SIG-04 |
| Status | anerkendt |
| Risiko | Informational |
| Virksomhedseffekt | Vi besluttede at vurdere denne konstatering som informativ, fordi den hovedsageligt er en følge af de vigtigste centraliseringsbekymringer beskrevet ovenfor. Med den nuværende måde, systemet er bygget op, er det nødvendigt for nogen at tildele og administrere Oracle- og Admin-rollerne. Det er dog ikke nødvendigt, at den konto selv har disse roller. |
| Lokation | – Belønning.sol:108-111; initialisere (adresse, adresse, adresse) |
Beskrivelse
Under initialiseringen modtager deployeren både admin, standard admin og oracle roller:
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
_setupRole(ORACLE_ROLE, msg.sender);
_setupRole(ADMIN_ROLE, msg.sender);
Mitigation
Overvej kun at give standardadministratorrollen, nedarvet fra OA'er AccessControlUpgradeable, til deployeren, så den kan administrere roller for andre brugere.
[M] Brug AccessControlDefaultAdminRulesUpgradeable
| ID | SIG-05 |
| Status | anerkendt |
| Risiko | Medium |
| Virksomhedseffekt | I betragtning af den iboende centralisering af kontrakten og vigtigheden af administratorroller (og derfor deres styring), besluttede vi at vurdere denne konstatering som middel risiko. |
| Lokation | - |
Beskrivelse
Reward.sol bruger i øjeblikket AccessControlUpgradable til at give og administrere adgang til kritiske funktioner. I OZ's adgangskontrolskema er den konto, der har DEFAULT_ADMIN_ROLE, i stand til at tildele og trække alle andre roller tilbage. I den nuværende tilstand af kontrakten gives den til installatøren ved initialisering.
AccessControlDefaultAdminRulesUpgradeable udvider AccessControlUpgradable med to afgørende sikkerhedsfunktioner:
- Kun én konto kan holde
DEFAULT_ADMIN_ROLE. DEFAULT_ADMIN_ROLEkan kun overføres ved hjælp af en to-trins proces. En konfigurerbar forsinkelse mellem de to trin,changeDefaultAdminDelay, håndhæves.
Mitigation
Skift fra AccessControlUpgradable til AccessControlDefaultAdminRulesUpgradeable.
[L] Utilstrækkelig inputvalidering i manuallySetRewardsGenesisTime(uint256)
| ID | SIG-06 |
| Status | Fast |
| Risiko | Lav |
| Virksomhedseffekt | Vi vurderer dette problem som lavt, da en fejlagtig værdi kunne rettes af administratoren lige så let, som den blev givet. |
| Lokation | – Reward.sol; manueltSetRewardsGenesisTime(uint256) |
Beskrivelse
Udover at udgøre en centraliseringsrisiko, som beskrevet ovenfor, manuallySetRewardsGenesisTime(uint256) heller ikke validere tidsstemplet givet af administratoren. Det ville med glæde acceptere en fremtidig tid, der fører til _getNumberOfWeeksSinceGenesis() at vende tilbage:
function _getNumberOfWeeksSinceGenesis()
private
view
returns (uint256 unixTimeDiff)
{
unixTimeDiff = (block.timestamp - rewardsGenesisTime) / 7 days;
}
Mitigation
Sørg for, at input er lig med eller mindre end det aktuelle tidsstempel.
[L] Utilstrækkelig inputvalidering i setMinimumTimeForRewards(uint256)
| ID | SIG-07 |
| Status | Fast |
| Risiko | Lav |
| Virksomhedseffekt | Ligesom ovenstående fund besluttede vi at vurdere dette fund som lav risiko, fordi det nemt kan rettes ved at kalde funktionen igen. |
| Lokation | – Reward.sol; setMinimumTimeForRewards(uint256) |
Beskrivelse
Dette fund minder i substans meget om det direkte over det. For høj værdi vil gøre brugerne ude af stand til at gøre krav på deres belønninger. Dette i takt med, at belønninger formindskes på ugentlig basis med _limitForWeek(uint256), vil neutralisere fordelen ved tidlig adoption.
Mitigation
Definer et acceptabelt interval af værdier for minimumTimeForRewards og håndhæve det gennem funktionen. På grund af den direkte indflydelse, denne værdi har på platformens hele belønningsstruktur, er det altafgørende at administrere den omhyggeligt.
[L] Ubrugt fejl
| ID | SIG-08 |
| Status | Fast |
| Risiko | Lav |
| Virksomhedseffekt | Vi besluttede at vurdere dette problem som lavt snarere end informativt, denne tilsyneladende utilsigtede udeladelse har en vis indflydelse på kontraktens logik. |
| Lokation | – Belønning.sol:12 |
Beskrivelse
Fejlen InvalidArrayLegnth() er deklareret på linje 12, men aldrig brugt.
Mitigation
Vi antager, at denne fejl skulle være smidt ind batchTransfer(TransferInfo[]) hvis det leverede array ikke har otte medlemmer:
if(transferInfos.length != 8) revert InvalidArrayLength();
[L] Ikke markeret returværdi
| ID | SIG-09 |
| Status | Fast |
| Risiko | Lav |
| Virksomhedseffekt | Overførselsfunktionen i ERC20-tokens returnerer succes eller fiasko for overførslen som en boolesk. Det anses for god praksis at kontrollere denne værdi og kun fortsætte, hvis det lykkes. Men fordi dokumentationen antyder det batchTransfer(TransferInfo[]) kun bruges til at overføre Dimo-tokens, vurderer vi denne konstatering som lav. |
| Lokation | – Belønning.sol:232; batchTransfer(TransferInfo[]) |
Beskrivelse
På den angivne linje foretages en dimoToken-overførsel, men returværdien forbliver umarkeret.
Mitigation
Gå tilbage med en fejl, hvis overførslen mislykkes:
if (!dimoToken.transfer(user, amount)) revert TokenTransferFailed();
[L] Forældet API-kald
| ID | SIG-10 |
| Status | anerkendt |
| Risiko | Lav |
| Virksomhedseffekt | I modsætning til grantRole(bytes32, address), _setupRole(bytes32, address) udfører ingen kontrol på den kaldende konto. Det er derfor blevet forældet. |
| Lokation | – Belønning.sol:108-111; initialisere (adresse, adresse, adresse) |
Beskrivelse
funktionen _setupRole(bytes32, address), brugt på den angivne placering, er blevet forældet i OpenZepplin 5.0. Ringer grantRole(bytes32, address) i stedet anbefales nu.
Mitigation
Erstat opkald til _setupRole(bytes32, address) med grantRole(bytes32, address).
[I] Utilstrækkelig hændelsesemission
| ID | SIG-11 |
| Status | Fast |
| Risiko | Informational |
| Virksomhedseffekt | Mange overvågningsværktøjer, frontends, off-chain-værktøjer og rapporteringstjenester er afhængige af hændelser for at fange kontrakter i realtid. Desuden kan protokoller reagere hurtigt på mistænkelige hændelser. |
| Lokation | – Reward.sol; sætRegistryContractAddress(adresse) – Reward.sol; setMinimumTimeForRewards(uint256) – Reward.sol; sætSyntheticProxyAddress(adresse) – Reward.sol; resetRewardsGenesisTime() – Reward.sol; manuallySetRewardsGenesisTime() – Reward.sol:267-268; batchTransfer(TransferInfo[]) |
Beskrivelse
De førnævnte funktioner udsender ikke hændelser for vigtige tilstandsopdateringer.
Mitigation
Tilføj begivenhedsemissioner.
[I] Soliditetsversionering
| ID | SIG-12 |
| Status | anerkendt |
| Risiko | Informational |
| Virksomhedseffekt | Kontrakten kan kompileres og testes med forskellige compilerversioner under udvikling og gennemgang og en anden anden compilerversion under udrulning til mainnet. Dette kan føre til uventede resultater. |
| Lokation | Belønning.sol:2 |
Beskrivelse
Kontrakten specificerer sin pragma som pragma solidity ^0.8.13;. Dette tillader brug af enhver version af solidity fra 0.8.13. Desuden er 0.8.13 ikke den seneste version.
Mitigation
Beslut dig for en enkelt version af solidity at bruge. Den seneste stabile (og derfor anbefalede) udgivelse er 0.8.19.
[I] Indekser ugeparameteren i TokensTransferredForConnectionStreak()
| ID | SIG-13 |
| Status | Fast |
| Risiko | Informational |
| Virksomhedseffekt | Indeksering er nyttig til at filtrere hændelser i Ethereum-logfiler. Hver indekseret parameter i en hændelse tilføjer et emne til hændelsesloggen, hvilket gør det nemmere at søge efter specifikke hændelser ved hjælp af disse parametre. |
| Lokation | – Belønning.sol:81 |
Beskrivelse
Ugeparameteren repræsenterer den aktuelle uge, hvor luftdråben blev distribueret. Da indeksering gør det nemmere for frontend-applikationer at filtrere specifikke hændelser, vil indeksering af denne parameter gøre det nemt at filtrere efter brugere, der har modtaget airdrops i en given uge.
Mitigation
Overvej at indeksere den angivne parameter.
[I] Overholdelse af Solidity Style Guide
| ID | SIG-14 |
| Status | Fast |
| Risiko | Informational |
| Virksomhedseffekt | Dette spørgsmål er rent informationsmæssigt. Der er ingen indflydelse på kontraktens sikkerhed eller på anden måde. |
| Lokation | – Belønning.sol:36 |
Beskrivelse
TransferInfo[], en struktur, er defineret på linje 36, direkte efter tilstandsvariablerne. Solidity-stilguiden anbefaler at placere struct-deklarationer før.
Mitigation
Flyt erklæringen af strukturen direkte til begyndelsen af kontrakten før tilstandsvariabler.




