December 16, 2021
Beskrivning
Smakämnen 1inch teamet bad oss att granska och granska deras Limit Order Protocol v2 smarta kontrakt. Vi tittade på koden och publicerar nu våra resultat.
Omfattning
Vi granskade åtagandet 4d94eea25e4dac6271bfd703096a5c4a4d899b4a
av 1inch/limit-order-protocol
förvaret. I omfattning var följande kontrakt:
- 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
Alla andra projektfiler och kataloger (inklusive tester), tillsammans med externa beroenden och projekt, spelteori och incitamentsdesign, exkluderades också från denna granskning. Externa kod- och kontraktsberoenden antogs fungera som dokumenterade och back-end-tjänster som tillhandahålls av 1inch antogs agera i protokollets bästa intresse.
Total hälsa
Generellt sett fann vi att projektets kodbas var läsbar och välorganiserad, även om den skulle kunna dra nytta av mer omfattande dokumentation, särskilt kring blocken av assemblerkod, protokollets kantfall, tillgångar/predikat/externa resurser som kommer att användas, ansvar/begränsningar för den tillhandahållna back-end-tjänsten och interaktioner mellan aktörer. Projektet går långt för att göra åtgärder gaseffektiva, ibland även med risk för att göra koden svårare att resonera kring; vi tar upp frågor relaterade till det nedan. Under hela revisionen var 1-tumsteamet mycket tillgängligt, lyhört och mycket lätt att arbeta med.
System översikt
Limit Order Protocol möjliggör ordning makers
att signera beställningar utanför kedjan för token-byten. Protokollet underlättar då ifyllandet av tidigare undertecknade order per order takers
. Beställningar är mycket utökningsbara och kan statiskt anropa externa kontrakt på flera punkter under hela orderfyllningsprocessen. Denna utvidgningsmöjlighet genomsyrar protokollet med nytta, men den lägger till både komplexitet och en större attackyta för själva orderna.
Det är viktigt att notera att det inte finns någon kedjelagring av orderdetaljer. Påfyllningsstatus eller annulleringsstatus för beställningar spåras endast via beställningshashar. Detta kräver att beställningar delas peer-to-peer eller via en centraliserad part. I det här fallet avser 1-tumsteamet att agera som den centraliserade parten, samla undertecknade order och använda dessa order som en källa till likviditet för sina andra protokoll. Beställningar kommer att publiceras via deras eget API så att användarna kan interagera med dem.
Denna centralisering ger 1-tumsteamet extrem kontroll över vilka order som publiceras och slutligen exekveras. Detta ger dem också möjligheten att censurera order, vilket kan vara användbart i fallet med skadliga eller vilseledande order, men som också kan missbrukas och tillåta dem att köra alla andra användare i förväg vid en gynnsam order genom att inte visa den via API:et.
Privilegierade roller
Även om kontrakten som rollen används i var utanför omfattningen identifierades en privilegierad roll. En immutableOwner
är inställd på skaparen av ett fullmaktskontrakt vid konstruktionstillfället och används för att begränsa åtkomsten till fullmaktens external
funktioner.
Externa beroenden och förtroendeantaganden
Utformningen av detta protokoll kräver komponenter utanför kedjan och kedjan, och denna hybridmodell kan användas för att mildra vissa attackvektorer som vi identifierar i vår rapport, men kostnaden för den förmågan är ökat beroende av 1-tumsteamet och infrastrukturen.
Dessutom tillhandahåller Limit Order Protocol funktioner som är avsedda att hämta priser från Chainlink-orakel. Vi antog att dessa orakel var ärliga, tillgängliga och fungerande.
Dessutom, på grund av flexibiliteten i en order, finns det flera kontaktpunkter med externa kontrakt som inte är validerade. Detta innebär att en illvillig användare kan missbruka sådana samtal och imitera predikat, tillgångar eller orakel med skadliga kontrakt för att utföra åtgärder under orderfyllningar. Även om projektet är skyddat i vissa områden mot återinträde, kan sådana vektorer orsaka överbelastningsattacker eller oupptäckta spamorder. 1-tumsteamet är medvetet om att vissa problem kan uppstå när man använder okända kontrakt för protokollet och har angett sin avsikt att endast större "blue chip"-tillgångar kommer att stödjas fullt ut av projektet. Det bör dock noteras att även med de mest populära tillgångarna finns det inneboende beteenden från varje tillgång som kan orsaka problem på protokoll som inte adresserar dem på rätt sätt, som att ta en avgift under överföringar med USDT eller returnera en felkod istället för en framgång boolean med cTokens.
Resultat
Här presenterar vi våra resultat.
Kritisk svårighetsgrad
Inga.
Hög svårighetsgrad
[H01] Inkonsekventa data skickas in _makeCall
I OrderMixin
kontraktet _makeCall
funktionen används för att överföra tillgångar från tagaren till tillverkaren och då från tillverkaren till tagaren. I den senare överföringen, den _makeCall
funktionen är felaktigt godkänd beställningens makerAsset
som den sista parametern, när den ska vara orderns makerAssetData
.
Som ett resultat kan alla proxyfunktioner som är beroende av makerAssetData
argumentet kommer att brista.
För att överensstämma med det tidigare samtalet till _makeCall
och för att fullt ut stödja proxyfunktionalitet, överväg att uppdatera order.makerAsset
parametern till order.makerAssetData
.
Uppdatering: Fast i dra begäran # 57.
[H02] Delvis ifyllda privata beställningar kan fyllas av vem som helst
Protokollet tillåter skapandet av privata och offentliga beställningar. På privata beställningar, endast allowedSender
adress, som anges av tillverkaren när beställningen skapades, kan fylla beställningen.
Men i OrderMixin
avtal, validering för allowedSender
adress är felaktigt omfattning, vilket innebär att den endast utvärderas inom logiken som hanterar den första fyllningen av en beställning. Om en privat beställning är delvis fylld, då checken för allowedSender
Adressen är inte längre tillgänglig och beställningen kan fyllas i av vem som helst.
För att klargöra avsikten kring huruvida någon användare ska kunna fylla delvis ifyllda privata beställningar eller inte, överväg att antingen dokumentera orsaken till det aktuella beteendet eller validera allowedSender
adress utanför omfattningen av den första fyllningen för att säkerställa att den kommer att valideras varje gång en fyllning görs.
Uppdatering: Fast i dra begäran # 58.
[H03] Skadlig tillverkare kan dra fördel av partiella fyllningar för att stjäla mottagarens tillgångar
Beställningar från OrderMixin
kontrakt har förmågan att delvis fyllas. För att stödja partiella fyllningar kräver protokollet ett sätt att beräkna båda sidor av byten. Både getMakerAmount
och getTakerAmount
fälten definieras av tillverkaren av beställningen för detta ändamål.
När du fyller en beställning måste mottagarna tillhandahålla antingen makingAmount
eller takingAmount
värden samt a thresholdAmount
värde. Det finns två olika kodvägar som kan tas, baserat på om makingAmount
eller takingAmount
tillhandahölls.
Den första är när makingAmount
parametern är definierad. Det kunde stympa d makingAmount
värde och också beräkna takingAmount
värde för det. I denna situation är thresholdAmount
säkerställer att takingAmount
värde som tas är inte oväntat stor.
Den andra är när takingAmount
parametern är definierad. I så fall kommer det att göra det beräkna makingAmount
värde, med möjlighet till avkorta den och räknar om takingAmount
värde om det händer. I denna situation är thresholdAmount
värde säkerställer att makingAmount
returnerat värde är inte oväntat liten.
Det finns två exploateringsmetoder, var och en unik för en av de tidigare nämnda kodvägarna. Dessa exploateringsmetoder kräver skadlig getMakerAmount
och getTakerAmount
funktioner. En enkel implementering av dessa funktioner skulle ha samma beteende som AmountCalculator
's getMakerAmount
och getTakerAmount
funktioner, men med en hårdkodad switch som tvingar dem att returnera ett angriparkontrollerat värde när det behövs.
Det första, mindre allvarliga exploateringsmönstret involverar den första kodvägen där makingAmount
värde anges i en fyllningsordning. En illvillig tillverkare skulle vänta på en fyllningsorder som specificerar makingAmount
att dyka upp i mempoolen för att köra den i förväg. De skulle tappa hela värdet utom 1 från tillverkarens sida och sedan tvinga _callGetTakerAmount
för att returnera det belopp som anges i användarens thresholdAmount
värde (eller deras bidrag om det är mindre). När användarens transaktion äntligen går igenom kommer de att byta hela sin transaktion thresholdAmount
värde av takerAsset
för en enda enhet av makerAsset
. Detta utnyttjande begränsas av det belopp som ges av thresholdAmount
värde eller mängden av takerAsset
användaren tillåten på LimitOrderProtocol
avtal.
Det andra, mer allvarliga exploateringsmönstret involverar den andra kodvägen där takingAmount
värde anges. Den skadliga skaparen skulle på samma sätt vänta på en fyllningsorder som specificerade en takingAmount
värde för att dyka upp i mempoolen. De skulle köra transaktionen i förväg och tvinga fram makingAmount
värde returneras av _callGetMakerAmount
funktion att vara högre än båda remainingMakerAmount
och thresholdAmount
. De skulle också ställa in takingAmount
returnerat värde av _callGetTakerAmount
vara mängden takerAsset
tillgång tillåten på LimitOrderProtocol
av tagaren. När mottagarens transaktion går igenom kommer den att göra det trunkera makingAmount
värde och sedan räkna om takingAmount
värde. Denna omräkning är dock inte garanterad lägre, och i det här fallet kommer den att tappa alla takerAsset
som de tillät på kontraktet. I den här kodvägen, thresholdAmount
värdet är säkerställa att makingAmount
är inte för låg, så tar alla mottagare takerAsset
tillgången är okontrollerad. De förlorade medlen är begränsade till beloppet av takerAsset
tillgång som användaren tillåts på LimitOrderProtocol
avtal.
Dessa exploateringar är inte möjliga utan delorder och, mer specifikt, delorder med skadlig getMakerAmount
och getTakerAmount
implementeringar.
Huvudfrågan av thresholdAmount
värdekontroll är att den bara täcker ena sidan av bytet, men den andra sidan kan manipuleras via frontrunning. Det finns inga garantier för att det värde som mottagaren ursprungligen föreslog förblir oförändrat. Överväg att ta bort makingAmount
trunkering från båda kodvägarna och återställning om beställningen inte kan stödja en fyllning så stor som begärts. Genom att göra detta, thresholdAmount
kan användas för att tillräckligt begränsa den andra sidan av bytet och undvika oväntat beteende, även i illvilliga order.
Uppdatering: Fast i dra begäran # 83.
Medel svårighetsgrad
[M01] Statiska argument passerade efter dynamiska argument
I OrderMixin
kontraktet getTakerAmount
och getMakerAmount
byte-fält används som argument för _callGetTakerAmount
och _callGetMakerAmount
funktioner. Dessa samtal ger ett sätt att beräkna en sida av bytet baserat på den andra sidan, och de tillåter användare att delvis fylla beställningar.
Smakämnen getTakerAmount
/getMakerAmount
fält är dynamiska variabler och är packade framför takerAmount
och makerAmount
värden i _callGetTakerAmount
och _callGetMakerAmount
funktioner. Det är möjligt för en skadlig tillverkare att tillhandahålla mer data än förväntat i getTakerAmount
ochgetMakerAmount
fält för att trycka på takerAmount
och makerAmount
bytes förbi där de antas vara när de avkodas i nästa funktion. Detta gör det möjligt för tillverkaren att flytta den angivna mottagaren eller tillverkarens mängd med en hel byte åt höger och till och med ersätta dem helt om ytterligare 32 byte med data tillhandahålls.
Användare måste redan manuellt granska getTakerAmount
och getMakerAmount
fält i ordningen, men denna teknik är ganska svår att upptäcka. Också värt att notera, denna attack gäller till och med internt betrodda getMakerAmount
och getTakerAmount
funktioner. För de flesta attacker kommer ett rimligt tröskelbelopp att förhindra förlust av pengar.
För att förhindra detta, överväg att koda de statiska argumenten före de dynamiska argumenten för att undvika att ge de dynamiska argumenten en metod för att styra de statiska argumenten.
Uppdatering: Inte fixad. 1-tumsteamet sa:
Vi kommer att vara extra försiktiga med getters validering. Vi kommer att försöka implementera förnuftsvalidering av getters i vår sdk som kommer att hjälpa till med att filtrera potentiellt skadliga order.
[M02] ERC721-order kan manipuleras
Det är möjligt att byta ut mer än bara ERC20s via OrderMixin
genom att använda ett kontrakt som delar samma funktionsväljare som IERC20:s transferFrom
, och tillhandahåller det kontraktet som makerAsset
eller takerAsset
i en beställning.
Fullmakterna utanför omfattningen, nämligen ERC721Proxy
, ERC721ProxySafe
och ERC1155Proxy
kontrakt följer detta mönster för att ge stöd till ERC721
och ERC1155
polletter. Eftersom proxyerna måste anropas med samma mönster som en IERC20 transferFrom
samtal måste signaturen börja med address from
, address to
och uint256 amount
. Allt annat som fullmakterna kräver kan skickas in efter, och definieras i ordningen som makerAssetData
och takerAssetData
.
ERC1155s kan naturligtvis överföra flera av samma id-tokens på en gång, vilket betyder ERC1155Proxy
kontraktet använder sig av amount
fält. Å andra sidan, ERC721
s har inte en uppenbar användning för amount
fält. Eftersom de representerar icke-fungibla tokens, kommer ett specifikt tokenId bara att ha ett existerande, vilket gör att amount
fält värdelöst. På grund av detta, genomförandet för båda ERC721Proxy
och ERC721ProxySafe
kontrakt använder det som krävs amount
fältet som tokenId
istället.
Denna överbelastning av amount
parameter skapar möjligheten att delvis fylla ERC721
beställningar för att köpa separat listade tokens till rabatterade priser. Till exempel kan det finnas ett fall där en enskild användare har flera ERC721
s i samma kontrakt tillåts överföras av ERC721Proxy
kontrakt och listar dem i separata limitorder.
Om gränsbeställningarna också ger getMakerAmount
och getTakerAmount
fält kommer det att vara möjligt att delvis fylla i dessa ERC721
order. Sedan beställningen amount
fältet motsvarar faktiskt tokenId
, kan en illvillig användare placera en partiell fyllning på ERC721
med det högre tokenId, vilket resulterar i en makingAmount
/takingAmount
av en ERC721
som skulle kunna motsvara en lägre tokenId
. Resultatet är ERC721
med det nedre tokenId
skulle överföras till priset av (higher tokenId price) * (lower tokenId's id) / (higher tokenId's id)
.
Denna exploatering har några krav:
- Flera olika
ERC721
s från samma kontrakt att tillåtas på antingenERC721
fullmakt av en enda ägare. - Öppen beställning för en av
ERC721
det är inte det lägstatokenId
av de tillåtna. - Partiell fyllning tillåts på beställningen.
För att helt ta bort möjligheten till partiell ERC721
fyller, överväg att separera amount
och tokenId
argument. Oavsett om argumenten är åtskilda eller inte, överväg att också dokumentera detta för att varna användare om detta beteende och för att undvika detta mönster i framtiden.
Uppdatering: Fast i dra begäran # 59.
[M03] Odokumenterade decimalantaganden
Smakämnen LimitOrderProtocol
kontrakt ärver ChainlinkCalculator
kontrakt genom OrderMixin
avtal. Detta kontrakt exponerar två funktioner för att möjliggöra användningen av Chainlink-orakel under predikat kontrollera och uppslagningen av tillverkarbelopp/avtagarbelopp.
Kontraktet gör dock odokumenterade antaganden om antalet decimaler som Chainlink-oraklen ska rapportera i, samt antalet decimaler som funktionsparametrarna ska innehålla. I vissa scenarier kan detta leda till oväntade beteenden, inklusive felaktig prissättning av tillgångar och oavsiktlig förlust av medel.
Mer specifikt, genom hela kontraktet är det implicita antagandet att Chainlink-oraklen kommer att rapportera med 18 decimalers precision. Dock inte alla Chainlink orakel rapportera med detta antal decimaler. Faktum är att om oraklet rapporterar ett tokenpar som är i termer av en valuta (till exempel USD), kommer det bara att ha 8 decimaler av precision. Eftersom det inte finns några begränsningar på som orakel kan användas, implicita antaganden bör inte göras om antalet decimaler de kommer att rapportera med.
Relaterat finns det ett implicit antagande att amount
parameter för ChainlinkCalculator
funktioner kommer att använda 18 decimaler, tillsammans med den missvisande explicita deklarationen att singlePrice
fungera Calculates price of token relative to ETH scaled by 1e18
. I verkligheten, även med ett orakel som gör rapport med 18 decimaler, returvärdet av singlePrice
funktion skulle skalas med antalet decimaler i amount
parameter, som inte nödvändigtvis är 18 decimaler.
På samma sätt, doublePrice
funktion förutsätter att två Chainlink-orakel kommer att rapportera med samma antal decimaler, vilket gör att resultatet av funktionen avviker från förväntningarna.
Överväg att explicit dokumentera antaganden om antalet decimaler som parametrar och returvärden bör vara i termer av. Överväg dessutom att antingen begränsa beräkningar som är beroende av orakel som bryter mot dessa antaganden, eller att de relevanta beräkningarna tar hänsyn till det faktiska antalet decimaler.
Uppdatering: Fast i dra begäran # 75.
Låg svårighetsgrad
[L01] Konstanter deklareras inte explicit
Det finns ett fåtal förekomster av bokstavliga värden som används med oförklarlig betydelse i kodbasen. Till exempel:
- I
OrderMixin
kontraktet_remaining
mappning är semantiskt överbelastad (som förklaras i numret Semantisk överbelastning av kartläggning) för att spåra mängden tillgång som återstår för en delvis fylld beställning såväl som om en beställning har fyllts helt. Specifikt,0
betyder att inga fyllningar kopplade till en beställning har gjorts,1
betyder att en beställning inte längre kan fyllas, och något större än1
innebär att det finns ett kvarvarande belopp kopplat till beställningen som potentiellt kan fyllas. - I
ChainlinkCalculator
kontrakt, det bokstavliga värdet1e18
används isinglePrice
funktion.
För att förbättra kodens läsbarhet och underlätta refactoring, överväg att definiera en konstant för varje magiskt tal och ge det ett tydligt och självförklarande namn. För komplexa värden, överväg att lägga till en inlinekommentar som förklarar hur de beräknades eller varför de valdes.
Uppdatering: Fast i dra begäran # 75 och dra begäran # 76.
[L02] Skadliga parter kan förhindra verkställandet av tillåtna order
Smakämnen OrderMixin
kontrakt tillåter tillverkande användare att skicka in tillåtna order så de kan utföras i en transaktion, snarare än att behöva ha en separat transaktion för godkännande. Beställningstagare kan också lämna in eget tillstånd under fyllningen av beställningen för samma ändamål.
Men eftersom tillverkarens tillstånd finns inuti beställa, skulle både tillverkarens och mottagarens tillstånd vara tillgängliga medan orderfyllningstransaktionen är i mempoolen. Detta skulle göra det möjligt för alla illvilliga användare att ta dessa tillstånd och exekvera dem på respektive tillgångskontrakt samtidigt som utfyllnadstransaktionen körs i förväg. Eftersom dessa tillstånd har en nonce
för att förhindra en dubbel utgiftsattack, skulle orderns fyllningstransaktion misslyckas som ett resultat av att man försökte använda samma tillstånd som precis användes under frontrun.
Även om det inte finns någon säkerhetsrisk, och tillverkaren kan skapa en ny order och förhandsgodkänna transaktionen, kan denna attack verkligen påverka användbarheten av tillåtna order. En motiverad angripare kan faktiskt blockera alla tillåtna order med denna attack. Överväg att validera om tillståndet redan lämnats in, eller om ersättningen räcker, under beställningsfyllningarna. Överväg också att informera användarna om denna möjliga attack under ordersammansättningen.
Uppdatering: Inte fixad. 1-tumsteamet säger:
Vi hade godkännandekontroller tidigare men beslutade att förenkla tillståndsflödet för att bara återgå till misslyckade godkännanden. Vi kommer att fundera över sätten att meddela beslutsfattare om problemet.
[L03] Duplicerad kod
Det finns instanser av duplicerad kod i kodbasen. Duplicering av kod kan leda till problem senare i utvecklingens livscykel och gör projektet mer benäget att introducera fel. Sådana fel kan oavsiktligt införas när funktionalitetsändringar inte replikeras över alla instanser av kod som borde vara identiska. Exempel på duplicerad kod inkluderar:
Istället för att duplicera kod kan du överväga att bara ha ett kontrakt eller bibliotek som innehåller den duplicerade koden och använda den när den duplicerade funktionen krävs.
Uppdatering: Delvis fast i dra begäran # 60.
[L04] Felaktig eller vilseledande testsvit
Det finns tillfällen i testsviten där testerna avviker från deras förväntade beteende. Till exempel:
- Smakämnen
ChainlinkCalculator
kontrakt ärvs avOrderMixin
avtal. Men under testernaAmountCalculator.arbitraryStaticCall
funktionen används för att anropaChainlinkCalculator
kontrakt som ett externt, oberoende kontrakt. Även om resultatet är det förväntade, bör testet återspegla beteendet med systemets nuvarande design och förväntade användningsfall genom att anropaChainlinkCalculator
fungerar direkt utan att använda det godtyckliga statiska anropet. - Även om fullmaktskontrakten var utanför räckvidden märkte vi att när vi testade protokollet med ERC721-tillgångar,
ERC721Proxy
kontrakt används inte för att byta tillgångarna i dess test svit.
Eftersom själva testsviten ligger utanför omfattningen av denna granskning, överväg att noggrant granska testsviten för att säkerställa att alla tester körs framgångsrikt enligt specifikationerna i protokollet.
Uppdatering: Fast i dra begäran # 57, dra begäran # 59och dra begäran # 61.
[L05] Fel och utelämnanden i händelser
I hela kodbasen sänds händelser i allmänhet ut när känsliga ändringar görs i kontrakten. Men många händelser saknar indexerade parametrar och/eller saknar viktiga parametrar. Till exempel:
Det finns också känsliga handlingar som saknar händelser, såsom:
Överväg att mer fullständigt indexera befintliga händelser och lägga till nya parametrar där de saknas. Överväg också att sända ut alla händelser på ett så fullständigt sätt att de kan användas för att återuppbygga kontraktets tillstånd med tjänster utanför kedjan.
Uppdatering: Inte fixad. 1-tumsteamet lade dock till en orderRemaining
parameter till OrderCanceled
händelse i dra begäran # 62.
1-tumsteamet säger:
Vi fann att endast en begränsad delmängd av data krävs för att tillfredsställa frontend-behov. Vid omfattande analys är alla föreslagna fält tillgängliga via spårning. För
OrderRFQMixin
vi förväntar oss att marknadsgaranter bygger sitt eget sofistikerade sätt att spåra vilka order som har avbrutits.
[L06] Lagringsändringar under händelseutsläpp
I NonceManager
kontrakt, när NonceIncreased
händelse sänds ut, avsändarens nonce ökar också.
Att utföra flera operationer samtidigt kan göra kodbasen svårare att resonera kring, mer benägen för fel och kan leda till att operationer förbises eller missförstås.
För att förbättra den övergripande avsikten, läsbarheten och tydligheten i koden, överväg att öka nonce-värdet innan du sänder händelsen.
Uppdatering: Fast i dra begäran # 63.
[L07] Inkonsekventa avkodningsmetoder kan orsaka resultatavvikelser
För att stödja all sin utökningsbarhet och flexibilitet måste Limit Order Protocol rutinmässigt hantera dynamiska bytesdata och godtyckliga returvärden från externa kontrakt. Som ett resultat innehåller protokollet en ArgumentsDecoder
bibliotek för att mer effektivt konvertera dynamiska bytevärden till grundläggande datatyper. Detta bibliotek används dock inte uteslutande, och i vissa fall abi.decode
används istället. Dessutom använder vissa kontrakt abi coder v1
medan andra använder abi coder v2
. Den förra uppträder mer på samma sätt som den ArgumentsDecoder
biblioteket, medan det senare utför ytterligare kontroller vid avkodning.
Den inkonsekventa användningen av dessa olika avkodningsmetoder kan resultera i subtila diskrepanser mellan avsikten och det faktiska beteendet hos kodbasen.
Exempelvis simulateCalls
funktionen använder bara ArgumentsDecoder.decodeBool
fungera. Om simulateCalls
funktionen används för att kontrollera anrop som skulle göras i predikatdelen av en order, då kan dess resultat avvika från vad som faktiskt inträffar när predikatvillkoren utvärderas, eftersom olika avkodningsmetoder används.
Så, till exempel, om ett predikat gör ett yttre staticcall
till någon funktion som returnerar en uint256
värde större än ett snarare än det förväntade bool
, då kommer det anropet att återgå, eftersom returvärdet är avkodas med abi coder v2
's abi.decode
som inte kommer att acceptera sådana värderingar som bool
. Men om exakt samma samtal görs med simulateCalls
, sedan det kommer helt enkelt att markeras som true
, därför att decodeBool
behandlar alla värden större än noll som true
.
Att göra simulateCalls
funktionen speglar helt beteendet hos faktiska predikatanrop, överväg att modifiera den för användning abi.decode
.
Uppdatering: Fast i dra begäran # 82.
[L08] Brist på indatavalidering
Smakämnen fillOrderToWithPermit
och fillOrderTo
funktioner för OrderMixin
kontrakt, samt fillOrderRFQToWithPermit
och fillOrderRFQTo
funktioner för OrderRFQMixin
kontrakt, validera inte target
adressparameter.
Detta gör det möjligt för en användare att oavsiktligt skicka in nolladressen och som ett resultat låsa de tillgångar som de är avsedda att ta emot efter att ha fyllt en beställning.
För att säkerställa att användare inte av misstag låser sina pengar, överväg att validera att target
adress är inte lika med nolladressen i de citerade funktionerna.
Uppdatering: Fast i dra begäran # 78.
[L09] Låg enhetstesttäckning
Enhetstesttäckningen för hela projektet är cirka 75 %, där vissa av kontrakten har särskilt låg täckning.
Med tanke på vikten av enhetstester för att validera kod och förhindra regressioner vid refaktorisering och utveckling av nya funktioner, uppmuntrar vi att avsevärt öka enhetstesttäckningen till minst 95 %, och inkluderar kantfall som täcker även osannolika situationer.
Uppdatering: Inte fixad.
[L10] Vilseledande eller ofullständig inline-dokumentation
I hela kodbasen identifierades ett fåtal fall av vilseledande och/eller ofullständig inline-dokumentation och bör åtgärdas.
Följande är fall av vilseledande inline-dokumentation:
- I
ChainlinkCalculator
kontraktetsinglePrice
funktions NatSpec@notice
Taggen säger att detCalculates price of token relative to ETH scaled by 1e18
, men i själva verket är dess resultat värde ofamount
tokens skalas efter1e18
, där oraklet kanske inte rapporterar i termer av ETH (till exempel för ett par som inte inkluderar ETH). - I
OrderRFQMixin
kontraktetinvalidatorForOrderRFQ
funktions NatSpec@return
Taggen är missvisande, eftersom offerten kanske inte har fyllts för att respektive invalidator-bit har ställts in. Beställningen kan också ha annullerats. - På rader 147, 165och 188 of
OrderMixin.sol
, NatSpec@param
taggar är ogrammatiska. - Uppkopplad 20 of
ERC1155Proxy.sol
, den@notice
taggen anger att den beräknade hashen är resultatet av att hashfunc_733NCGU
funktion, där den ska varafunc_301JL5R
fungerar istället.
Följande är fall av ofullständig inline-dokumentation:
- Funktioner i
AmountCalculator
kontraktet beskriver inte någon av parametrarna. - I
ChainlinkCalculator
kontraktetsinglePrice
ochdoublePrice
funktioner beskriver inte alla parametrar. - I
ImmutableOwner
kontrakt, den offentliga variabeln och modifieraren har ingen NatSpec. - I
InteractiveNotificationReceiver
kontraktetnotifyFillOrder
Funktionen beskriver inte någon av parametrarna. - I
LimitOrderProtocol
kontraktetDOMAIN_SEPARATOR
funktion har ingen NatSpec. - Händelser och kartläggningar i
NonceManager
har ingen NatSpec. - I
OrderRFQMixin
avtal,cancelOrderRFQ*
funktioner beskriver inte returvärdena. - I
OrderMixin
kontrakt, flera funktioner saknar komplett NatSpec. - Uppkopplad 168 of
OrderMixin.sol
och på nätet 71 ofOrderRFQMixin.sol
, det saknas@dev
märka. - Funktioner i
PredicateHelper
kontraktet beskriver inte alla parametrar.
Tydlig inline-dokumentation är grundläggande för att beskriva kodens avsikter. Felmatchningar mellan inline-dokumentationen och implementeringen kan leda till allvarliga missuppfattningar om hur systemet förväntas bete sig. Överväg att åtgärda dessa fel för att undvika förvirring för både utvecklare, användare och revisorer.
Uppdatering: Delvis fixerad. Vilseledande dokumentation adresserad i dra begäran # 75 och dra begäran # 77.
1-tumsteamet säger:
Vi har åtgärdat vilseledande dokument. Komplettering av dokumenten kommer att göras senare.
[L11] DoS-beställningar är möjliga vid användning av krokar
Smakämnen OrderMixin
kontrakt implementerar funktionalitet för att fylla generiska off-chain swaporder som kan ha förutsättningar för deras framgång. Under orderfyllningar kan ordern kontrollera de fördefinierade "predikat"-villkoren innan du fortsätter med utförandet.
Men eftersom dessa predikatvillkor kan rikta in sig på logiken i vilket godtyckligt kontrakt som helst, kan en illvillig tillverkare lura mottagare att tro att en beställning fungerar korrekt och att den är giltig när den kontrolleras utanför kedjan, men sedan misslyckas när de försöker fylla samma beställning. på kedjan. Denna förändring i predikatbeteendet skulle antingen kunna göras genom att i förväg köra något variabelt tillstånd som predikaten är beroende av, genom att undersöka den sända gasen eller till och med vilka adresser som är involverade i samtalet, eller genom någon annan logik.
Dessutom, om tillverkaren definierade en interaktion under bytet, den interactionTarget
kontraktet skulle kunna återkalla sig självt eller återkalla tillägget för att förhindra en framgångsrik orderfyllning, vilket i huvudsak leder till samma resultat som skadliga predikat.
Även om tillgångar inte kommer att vara i riskzonen, kommer användare eller bots som hittar en gynnsam ordning att ha den ökade bördan att försöka identifiera den här typen av spambeställningar som kan verka legitima på ytan. Om de misslyckas med att identifiera den här typen av beställningar kommer de att ådra sig slöseri med gaskostnader. För att minska mängden spambeställningar, överväg att begränsa de tillgängliga målen för dessa hooks. Överväg också att varna användare om denna möjlighet innan de försöker fylla beställningar.
Uppdatering: Inte fixad. 1-tumsteamet säger:
Vi hanterar det på vår backend och vi kommer att fundera över sätten att meddela möjliga användare om problemet.
[L12] Avrundning kan vara ogynnsam för taker
I OrderMixin
och OrderRFQMixin
kontrakt, när en order fylls på och mottagaren tillhandahåller endast en makingAmount
or takingAmount
belopp, försöker protokollet beräkna motpartsbeloppet för swappen.
Det finns två problem med dessa beräkningar, den första är att det inte finns någon dokumentation eller logik som begränsar antalet decimaler som mängdparametrarna ska använda, vilket vi tog upp i Odokumenterade decimalantaganden problem.
Den andra frågan är att protokollet under dessa beräkningar avrundar till tillverkarens fördel. Avrundningsproblemet kan förvärras kraftigt när de implicita decimalantagandena bryts, men även när allt är i förväntade termer kommer avrundning att ske med små, udda belopp.
Överväg att tillåta mottagaren att ange ett minimibelopp av makerAsset
tillgång som de är villiga att få tillsammans med ett maximalt belopp på takerAsset
tillgång som de är villiga att byta, så att acceptansen av varje avrundning är mer explicit.
Uppdatering: Inte fixad. 1-tumsteamet säger:
Tröskelbeloppet bör vara tillräckligt för tagarens skydd.
[L13] Motsägelsefull orderhantering när parametrar saknas
I OrderMixin
kontraktet fillOrderTo
funktionen gör interna anrop till _callGetMakerAmount
och _callGetTakerAmount
fungerar när en fyllning görs och antingen makingAmount
eller takingAmount
parametrarna är noll, respektive, eller om makingAmount
värdet är större än remainingMakerAmount
värde.
Smakämnen _callGetMakerAmount
och _callGetTakerAmount
samtal kommer att leda till återgång om beställningen inte skapades med getMakerAmount
or getTakerAmount
parametrar, respektive, och en partiell fyllning exekveras.
An inline kommentar bredvid _callGetMakerAmount
och en inline kommentar bredvid _callGetTakerAmount
hävda att "endast hela fyllningar är tillåtna" om beställningen inte skapades med getMakerAmount
or getTakerAmount
parametrar.
Det finns dock kodsökvägar för vilka detta inte gäller, eftersom dessa sökvägar inte kontrollerar length
s av båda getMakerAmount
och getTakerAmount
parametrar.
Specifikt, när en taker
specificerar a takerAmount
värde för en order som endast har en getMakerAmount
, om inte det ringer till getMakerAmount
returnerar ett belopp som är större än remainingMakerAmount
, kan en partiell fyllning utföras i motsats till inline-dokumentationen.
Detta gör att avsikten med dessa kodvägar är otydlig. Om detta är det förväntade beteendet kan du överväga att ändra inline-dokumentationen så att den blir mer explicit. Om detta är oavsiktligt beteende, överväg att alltid kontrollera längden på båda getMakerAmount
och getTakerAmount
parametrar samtidigt så att implementeringen förstärker beteendet som beskrivs av inline-dokumentationen.
Uppdatering: Fast i dra begäran # 79.
[L14] Använder föråldrade Chainlink-anrop
Smakämnen ChainlinkCalculator
kontraktet är avsett att användas för att fråga Chainlink-orakel. Det gör det genom att ringa till deras latestTimestamp
och latestAnswer
metoder, som båda har fasats ut. Faktum är att metoderna inte längre finns i API för Chainlink-aggregatorer från och med version tre.
För att undvika potentiella framtida inkompatibiliteter med Chainlink-orakel, överväg att använda latestRoundData
metod istället.
Uppdatering: Fast i dra begäran # 67.
Anteckningar och ytterligare information
[N01] Importerar inte gränssnitt
Smakämnen AggregatorInterface
gränssnittet verkar vara en delmängd av kod som kopierats från ChainLink
s offentliga kodförråd. Hela gränssnittet ingår i ChainLink
s kontrakt npm-paket.
När det är möjligt, för att minska risken för gränssnittsfel och resulterande problem, snarare än att omdefiniera och/eller skriva om ett annat projekts gränssnitt, överväg att använda gränssnitt installerade via deras officiella npm-paket istället.
Uppdatering: Fast i dra begäran # 66.
[N02] Utfasade projektberoenden
Under installationen av projektets beroenden, varnar NPM att ett av de installerade paketen, Highlight
, "kommer inte längre att stödjas eller ta emot säkerhetsuppdateringar i framtiden".
Även om det är osannolikt att det här paketet kan orsaka en säkerhetsrisk, överväg att uppgradera beroendet som använder det här paketet till en underhållen version.
Uppdatering: Fast i dra begäran # 64.
[N03] Externa anrop för att visa metoder är inte statiska anrop
Under större delen av kodbasen gör protokollet uttryckligen externa samtal via OpenZeppelins functionStaticCall
metod för att begränsa möjligheten till statliga förändringar när de antingen inte förväntas eller inte är önskvärda. Men i ChainlinkCalculator
kontrakt, trots avsikten att endast ringa externa samtal till view
metoder på Chainlink-orakel, de externa anropen i singlePrice
och doublePrice
funktioner är inte gjorda via explicit staticcall
s.
Även om vi inte identifierade några omedelbara säkerhetsproblem som härrörde från detta, för att minska attackytan, förbättra konsekvensen och förtydliga avsikten, överväg att använda explicit staticcall
s, för alla externa samtal till view
funktioner i ChainlinkCalculator
avtal.
Uppdatering: Inte fixad. 1-tumsteamet säger:
Vi tror att syntaxkomplikation upphäver förbättringar i konsekvens.
[N04] Misslyckas inte tidigt med ogiltiga beställningar
I OrderMixin
kontraktet fillOrderTo
funktion hanterar det speciella villkoret när en beställning inte har skickats tidigare (remainingMakerAmount == 0
), men det hanterar inte uttryckligen villkoret när beställningen inte längre är giltig (remainingMakerAmount == 1
).
I det senare scenariot kommer funktionen så småningom att återgå, men bara efter att ha förbränt icke-triviala mängder gas. För att förtydliga avsikten, öka läsbarheten och minska gasanvändningen, överväg att explicit hantera scenariot med ogiltig ordning mot början av funktionen.
Uppdatering: Fast i dra begäran # 68.
[N05] Hjälparkontrakt inte markerade som abstrakta
I Solidity, nyckelordet abstract
används för kontrakt som antingen inte är funktionella kontrakt i sig eller inte är avsedda att användas som sådana. Istället, abstract
kontrakt ärvs av andra kontrakt i systemet för att skapa fristående funktionskontrakt.
I hela kodbasen finns det exempel på hjälparkontrakt som inte är markerade som abstrakta, trots att de inte är avsedda att distribueras på egen hand. Till exempel AmountCalculator
, ChainlinkCalculator
, ImmutableOwner
, NonceManager
och PredicateHelper
kontrakt består alla av en basuppsättning funktioner som är avsedda att användas genom att ärva kontrakt.
Överväg att markera medhjälparkontrakt som abstract
för att tydligt markera att de är utformade enbart för att lägga till funktionalitet till kontrakt som ärver dem.
Uppdatering: Inte fixad. 1-tumsteamet säger:
Dessa hjälpare kan sättas in separat. De ärvs endast för gasbesparingar.
[N06] Inkonsekvent funktionsordning
Genom hela kodbasen följer funktionsordning i allmänhet rekommenderad ordning i Solidity Style Guide, vilket är: constructor
, fallback
, external
, public
, internal
, private
.
Men i den OrderMixin
kontraktet public
checkPredicate
funktionen avviker från stilguiden och halverar external
funktioner.
För att förbättra projektets övergripande läsbarhet, överväg att standardisera funktionsordning i hela kodbasen, enligt rekommendationerna i Solidity Style Guide.
Uppdatering: Fast i dra begäran # 69.
[N07] Inkonsekvent orderfyllningsflöde
Smakämnen OrderMixin
och RFQOrderMixin
kontrakt hanterar båda fyllandet av signerade order, men det allmänna orderflödet mellan de två kontrakten är inkonsekvent.
OrderMixin
's fillOrderTo
funktionen följer detta allmänna flöde (pseudokod):
if ((takingAmount == 0) == (makingAmount == 0))
else if (takingAmount == 0)
else (handle makingAmount == 0) THEN swapTokens
Av följande skäl: RFQOrderMixin
är analogt fillOrderRFQTo
funktionen följer detta flöde (pseudokod):
if (takingAmount == 0 && makingAmount == 0)
else if (takingAmount == 0)
else if (makingAmount == 0)
else revert THEN swapTokens
Det finns inga insikter från dokumentationen om varför det första villkoret i var och en av dessa två funktioner skiljer sig, eller varför takingAmount
och makingAmount
kan inte båda vara noll i den senare funktionen. Även fallet där både en makingAmount
och en takingAmount
tillhandahålls är mycket lättare att resonera om i fillOrderRFQTo
funktion, eftersom det hanteras tydligt i finalen else
blockera.
För att förtydliga avsikten och öka kodens övergripande läsbarhet, överväg att antingen standardisera det allmänna orderflödet över dessa två kontrakt, eller att explicit dokumentera varför skillnaderna finns.
Uppdatering: Inte fixad. 1-tumsteamet säger:
Detta beror på anpassade prissättningsfunktioner i limiterade beställningar. Eftersom
getMakerAmount
kan potentiellt skilja sig väsentligt frångetTakerAmount
, vi tänkte att det är bättre att inte göra standardalternativ för mottagaren eftersom det förmodligen kommer att förvirra dem i fall då dessa getters kommer att vara annorlunda.
[N08] Felmeddelanden är inkonsekvent formaterade eller vilseledande
I hela kodbasen, require
och revert
felmeddelanden, som är avsedda att meddela användare om de särskilda villkoren som orsakar en transaktion att misslyckas, visade sig vara inkonsekvent formaterade.
Till exempel, vart och ett av felmeddelandena på rader 85 av OrderMixin.sol
, 16 av ERC721ProxySafe.sol
och 26 av Permitable.sol
använda en annan stil.
Dessutom är vissa felmeddelanden vilseledande:
Felmeddelanden är avsedda att meddela användare om bristande tillstånd, så de bör ge tillräckligt med information så att lämpliga korrigeringar kan göras för att interagera med systemet. Oinformativa felmeddelanden skadar i hög grad den övergripande användarupplevelsen, vilket sänker systemets kvalitet. Dessutom kan inkonsekvent formaterade felmeddelanden skapa onödig förvirring. Överväg därför att granska hela kodbasen för att se till att varje require
och revert
uttalandet har ett felmeddelande som är konsekvent formaterat, korrekt, informativt och användarvänligt.
Uppdatering: Delvis fast i dra begäran # 81.
[N09] Inkonsekvent användning av namngivna returvariabler
Det finns en inkonsekvent användning av namngivna returvariabler i OrderMixin
avtal. Vissa funktioner returnera namngivna variabler, andra returnera explicita värden, och andra deklarera en namngiven returvariabel men åsidosätt den med ett uttryckligt returmeddelande.
Överväg att använda ett konsekvent tillvägagångssätt för returvärden i hela kodbasen genom att ta bort alla namngivna returvariabler, uttryckligen deklarera dem som lokala variabler och lägga till nödvändiga retursatser där så är lämpligt. Detta skulle förbättra både explicititeten och läsbarheten av koden, och det kan också bidra till att minska regressioner under framtida kodrefaktorer.
Uppdatering: Fast i dra begäran # 73.
[N10] Orderns hashberäkning är inte öppen för API:et
Smakämnen external
funktioner remaining
, remainingRaw
och remainingsRaw
alla förväntar sig en orderhash för framgångsrik drift.
Däremot hjälparfunktionen _hash
, som returnerar hashen för en beställning, har private
synlighet. Detta innebär att användare måste packa delar av beställningarna och domänsträngarna manuellt för att få hash för en beställning.
För att undvika risken för misstag vid beräkning av orderhashar och för att ge användarna en metod för att generera en orders respektive hash, överväg att utöka synligheten för _hash
funktion till public
och omstrukturera namnet till hash
för att överensstämma med resten av koden.
Uppdatering: Fast i dra begäran # 74.
[N11] Semantisk överbelastning av kartläggning
Smakämnen _remaining
kartläggning i OrderMixin
kontraktet är semantiskt överbelastat för att spåra status för order och den återstående mängden tillgångar som är tillgängliga för dessa order.
De tre tillstånden som den kan ta sig an är:
0
: Beställningshashen har inte setts ännu.1
: Beställningen har antingen annullerats eller helt fylld.- Vilken som helst
uint
större än1
: ResterandemakerAmount
finns att fylla på beställningen plus1
.
Denna semantiska överbelastning kräver inslagning och uppackning av detta värde under lookup
, cancellation
, initialization
och storage
.
Semantisk överbelastning och nödvändig logik för att möjliggöra det kan vara benägna att fel och kan göra kodbasen svårare att förstå och resonera kring, det kan också öppna dörren för regressioner i framtida uppdateringar av koden.
För att förbättra kodens läsbarhet kan du överväga att spåra beställningars slutförandestatus i en separat mappning.
Uppdatering: Inte fixad. 1inch-teamet citerade att en fix skulle öka gaskostnaderna för fillOrder
funktion.
[N12] Order med tillstånd tillåter samtal till godtyckliga kontrakt
Smakämnen OrderMixin
kontrakt ärver Permitable
kontrakt för att möjliggöra en enskild transaktionsorderfyllning med tillgångar som accepterar sådana permit
uppmaningar om att ändra utsläppsrätterna.
Emellertid den samtal till Permitable
kontrakt validera inte om målet är en tillåten tillgång eller om det ens är en tillgång, vilket skulle kunna tillåta en illvillig användare att skicka adressen till ett godtyckligt kontrakt som skulle kunna utföra ett nytt samtal innan orderfyllningen slutförs.
Även om kontraktet är skyddad mot återinträde, att minska attackytan och förhindra att externa kontrakt ringer under utförande rekommenderas alltid. Överväg att antingen begränsa tillgången som är involverad i tillståndet till tillgångarna som ingår i beställningen eller till en vitlista för tillgångar för protokollet.
Uppdatering: Inte fixad. 1-tumsteamet säger:
OrderMixin
har faktiskt inte info om faktiska tokens sommakerAsset
ochtakerAsset
ibland är fullmakter eller andra mellanliggande kontrakt och information om faktiska tokens lagras i några godtyckliga bytes. Så det finns inget hållbart sätt att begränsa vilken tillgångpermit
kallas på.
[N13] solhint
är aldrig återaktiverad
I hela kodbasen finns det ett par solhint-disable
uttalanden, särskilt de på nätet 23 och på nätet 41 of RevertReasonParser.sol
, som inte avslutas med solhint-enable
.
Till förmån för uttrycklighet och att vara så restriktiv som möjligt vid inaktivering solhint
, överväga att använda solhint-disable-line
or solhint-disable-next-line
istället liknar linje 16 av samma fil.
Uppdatering: Fast i dra begäran # 72.
[N14] Skrivfel
Kodbasen innehåller följande stavfel:
Dessutom projektets README
(utanför räckvidden för denna granskning) innehåller följande stavfel:
Överväg att korrigera dessa stavfel för att förbättra kodens läsbarhet.
Uppdatering: Fast i dra begäran # 71 och dra begäran # 77.
[N15] Användning av uint
istället för uint256
För att gynna uttrycklighet, alla instanser av uint
bör förklaras som uint256
. I synnerhet de i for
slingor på linjer 98 och 119 of OrderMixin.sol
och linjer 16 och 30 of PredicateHelper.sol
.
Uppdatering: Fast i dra begäran # 70.
Slutsatser
3 allvarliga problem hittades. Vissa ändringar föreslogs för att följa bästa praxis och minska den potentiella attackytan.
- &
- 7
- Om oss
- tillgång
- Enligt
- Konto
- tvärs
- Agera
- åtgärder
- Annat
- adress
- Fördel
- Alla
- tillåta
- redan
- Även
- mängder
- analys
- api
- tillvägagångssätt
- argument
- runt
- tillgång
- Tillgångar
- revision
- Back-end
- Börjar
- Där vi får lov att vara utan att konstant prestera,
- BÄST
- bästa praxis
- Bit
- botar
- SLUTRESULTAT
- Ring
- vilken
- fall
- Orsak
- Kedjelänk
- byta
- kontroll
- Kontroller
- koda
- komplex
- tillstånd
- förvirring
- konstruktion
- innehåller
- kontrakt
- kontrakt
- Korrigeringar
- Kostar
- kunde
- Par
- skaparen
- Valuta
- Aktuella
- datum
- behandla
- Denial of Service
- utplacera
- Designa
- utvecklare
- Utveckling
- DID
- skilja sig
- olika
- domän
- dubbla
- dynamisk
- Tidig
- kant
- uppmuntra
- speciellt
- ETH
- händelse
- händelser
- allt
- exempel
- utbyta
- förväntat
- erfarenhet
- Exploit
- Funktioner
- Fält
- Slutligen
- Förnamn
- Fast
- Flexibilitet
- flöda
- följer
- hittade
- full
- fungera
- fonder
- framtida
- lek
- GAS
- Allmänt
- Ge
- stor
- styra
- Arbetsmiljö
- hash
- hasch
- har
- hjälpa
- Hög
- höggradigt
- Hur ser din drömresa ut
- HTTPS
- Hybrid
- identifiera
- Inverkan
- genomföra
- med Esport
- importera
- ingår
- Inklusive
- Öka
- ökat
- info
- informationen
- Infrastruktur
- insikter
- uppsåt
- intresse
- Gränssnitt
- involverade
- problem
- IT
- Large
- större
- leda
- ledande
- Bibliotek
- Begränsad
- linje
- Likviditet
- Noterade
- listor
- lokal
- såg
- slå upp
- större
- tillverkare
- Framställning
- marknad
- Mempool
- spegel
- modell
- mest
- Mest populär
- nämligen
- Nya funktioner
- icke-fungible
- icke-svampbara symboler
- tjänsteman
- öppet
- Verksamhet
- Alternativet
- orakel
- beställa
- ordrar
- Övriga
- ägaren
- Mönster
- Populära
- presentera
- förebyggande
- pris
- prissättning
- privat
- process
- projektet
- projekt
- skydd
- protokoll
- ge
- ger
- ombud
- allmän
- publicera
- inköp
- kvalitet
- höja
- Verkligheten
- minska
- tillit
- rapport
- Rapport
- Repository
- Krav
- REST
- Resultat
- återgår
- översyn
- Risk
- omgångar
- Körning
- sDK
- säkerhet
- Tjänster
- in
- delas
- aktier
- skifta
- liknande
- Enkelt
- Small
- smarta
- Smarta kontrakt
- So
- fasthet
- skräppost
- specifikt
- Spendera
- Spot
- starta
- Ange
- .
- Stater
- status
- förvaring
- stil
- lämnats
- framgång
- framgångsrik
- Framgångsrikt
- stödja
- Som stöds
- yta
- Växla
- system
- Målet
- testa
- Testning
- tester
- Genom
- hela
- tid
- tillsammans
- token
- tokens
- spår
- Spårning
- transaktion
- Litar
- unika
- Uppdateringar
- us
- användbarhet
- USD
- USDT
- användare
- verktyg
- värde
- utsikt
- synlighet
- vänta
- Vad
- vitlista
- inom
- utan
- Arbete
- värt
- noll-