Desember 16, 2021
Introduksjon
De 1inch teamet ba oss om å gjennomgå og revidere deres Limit Order Protocol v2 smarte kontrakter. Vi så på koden og publiserer nå resultatene våre.
Omfang
Vi reviderte forpliktelse 4d94eea25e4dac6271bfd703096a5c4a4d899b4a
av 1inch/limit-order-protocol
oppbevaringssted. I omfang var følgende kontrakter:
- 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
Alle andre prosjektfiler og kataloger (inkludert tester), sammen med eksterne avhengigheter og prosjekter, spillteori og insentivdesign, ble også ekskludert fra omfanget av denne revisjonen. Ekstern kode og kontraktsavhengigheter ble antatt å fungere som dokumentert, og back-end-tjenester levert av 1inch ble antatt å handle i protokollens beste interesse.
Total helse
Generelt sett fant vi at prosjektets kodebase var lesbar og godt organisert, selv om den kunne ha nytte av mer omfattende dokumentasjon, spesielt rundt blokkene med assembly-kode, kanttilfeller av protokollen, eiendeler/predikater/eksterne ressurser som vil bli brukt, ansvar/begrensninger for back-end-tjenesten som tilbys, og interaksjoner mellom aktører. Prosjektet strekker seg langt for å gjøre handlinger gasseffektive, noen ganger også med fare for å gjøre koden vanskeligere å resonnere rundt; vi tar opp spørsmål knyttet til det nedenfor. Gjennom hele tilsynet var 1-tommers-teamet svært tilgjengelig, responsivt og veldig enkelt å jobbe med.
Systemoversikt
Limit Order Protocol muliggjør ordre makers
å signere bestillinger utenfor kjeden for token-bytte. Protokollen letter deretter utfylling av tidligere signerte bestillinger etter bestilling takers
. Ordrer er svært utvidbare, og kan statisk kalle eksterne kontrakter på flere punkter gjennom hele ordreutfyllingsprosessen. Denne utvidbarheten gir protokollen nytte, men den tilfører både kompleksitet og en større angrepsoverflate for selve ordrene.
Det er viktig å bemerke at det ikke er kjedelagring av ordredetaljer. Fyllingsstatus eller kanselleringsstatus for bestillinger spores kun via bestillings-hasher. Dette nødvendiggjør at bestillinger deles peer-to-peer eller via en sentralisert part. I dette tilfellet har 1inch-teamet til hensikt å fungere som den sentraliserte parten, samle signerte ordrer og bruke disse ordrene som en likviditetskilde for sine andre protokoller. Bestillinger vil bli publisert via deres eget API slik at brukerne kan samhandle med dem.
Denne sentraliseringen gir 1-tommers-teamet ekstrem kontroll over hvilke bestillinger som publiseres og til slutt utføres. Dette gir dem også muligheten til å sensurere bestillinger, noe som kan være nyttig i tilfelle ondsinnede eller villedende bestillinger, men som også kan bli misbrukt og tillate dem å kjøre en hvilken som helst annen bruker i forkant i tilfelle en gunstig bestilling ved ikke å vise den gjennom API.
Privilegerte roller
Selv om kontraktene rollen brukes i var utenfor omfanget, ble det identifisert én privilegert rolle. An immutableOwner
er satt til skaperen av en fullmaktskontrakt på konstruksjonstidspunktet, og brukes til å begrense tilgangen til fullmektigenes external
funksjoner.
Eksterne avhengigheter og tillitsforutsetninger
Utformingen av denne protokollen nødvendiggjør komponenter utenfor kjeden og på kjeden, og denne hybridmodellen kan brukes til å dempe noen angrepsvektorer vi identifiserer i rapporten vår, men kostnaden for denne muligheten er økt avhengighet av 1-tommers teamet og infrastrukturen.
I tillegg gir Limit Order Protocol funksjoner som er ment å hente priser fra Chainlink-orakler. Vi antok at disse oraklene var ærlige, tilgjengelige og fungerende.
I tillegg, på grunn av fleksibiliteten til en ordre, er det flere kontaktpunkter med eksterne kontrakter som ikke er validert. Dette betyr at en ondsinnet bruker kan misbruke slike samtaler og etterligne predikater, eiendeler eller orakler med ondsinnede kontrakter for å utføre handlinger under ordrefylling. Selv om prosjektet er beskyttet i enkelte områder mot gjeninntreden, kan slike vektorer forårsake tjenestenektangrep eller uoppdagede spamordrer. 1-tommers-teamet er klar over at visse problemer kan oppstå ved bruk av ukjente kontrakter for protokollen, og har indikert sin intensjon om at bare store "blue chip"-ressurser vil bli støttet fullt ut av prosjektet. Det bør imidlertid bemerkes at selv med de mest populære eiendelene er det iboende atferd fra hver eiendel som kan forårsake problemer på protokoller som ikke adresserer dem riktig, for eksempel å ha et gebyr under overføringer med USDT eller returnere en feilkode i stedet for en suksess boolesk med cTokens.
Funn
Her presenterer vi funnene våre.
Kritisk alvorlighetsgrad
Ingen.
Høy alvorlighetsgrad
[H01] Inkonsistente data sendt inn _makeCall
på OrderMixin
kontrakt, den _makeCall
funksjonen brukes til å overføre eiendeler fra den som tar til den som lager og deretter fra maker til tar. I sistnevnte overføring er _makeCall
funksjonen er feilaktig bestått ordrens makerAsset
som siste parameter, når den skal være bestillingens makerAssetData
.
Som et resultat vil enhver proxy-funksjonalitet som er avhengig av makerAssetData
argumentet vil bryte.
For å være i samsvar med den tidligere oppfordringen til _makeCall
og for å fullt ut støtte proxy-funksjonalitet, bør du vurdere å oppdatere order.makerAsset
parameter til order.makerAssetData
.
Oppdatering: Fast i trekk forespørsel # 57.
[H02] Delvis utfylte private bestillinger kan fylles av hvem som helst
Protokollen tillater opprettelse av private og offentlige bestillinger. På private bestillinger er det kun allowedSender
adresse, spesifisert av produsenten under opprettelsen av bestillingen, er i stand til å fylle bestillingen.
Imidlertid i OrderMixin
kontrakt, validering for allowedSender
adresse er feil scoped, noe som betyr at den kun evalueres innenfor logikken som håndterer den første fyllingen av en ordre. Hvis en privat ordre er delvis fylt, vil sjekken for allowedSender
adressen er ikke lenger tilgjengelig og bestillingen kan fylles ut av hvem som helst.
For å avklare intensjonen om hvorvidt en bruker skal kunne fylle ut delvis utfylte private bestillinger eller ikke, bør du vurdere enten å dokumentere årsaken til den nåværende oppførselen eller validere allowedSender
adresse utenfor omfanget av den første fyllingen for å sikre at den blir validert hver gang en fylling blir forsøkt.
Oppdatering: Fast i trekk forespørsel # 58.
[H03] Ondsinnet produsent kan dra nytte av delvis fyllinger for å stjele takers eiendeler
Bestillinger fra OrderMixin
kontrakt har muligheten til å bli delvis fylt. For å støtte delvise fyllinger, krever protokollen en måte å beregne begge sider av bytte. Både getMakerAmount
og getTakerAmount
felt er definert av bestilleren for akkurat dette formålet.
Når du fyller en ordre, må mottakerne oppgi enten makingAmount
eller takingAmount
verdier samt a thresholdAmount
verdi. Det er to forskjellige kodestier som kan tas, basert på om makingAmount
eller takingAmount
ble gitt.
Den første er når makingAmount
parameter er definert. Det kunne avkortes de makingAmount
verdi og også beregne takingAmount
verdi for det. I denne situasjonen vil thresholdAmount
sikrer at takingAmount
verdien tatt er ikke uventet stor.
Den andre er når takingAmount
parameter er definert. I så fall vil det beregne makingAmount
verdi, med mulighet for kutte den og omberegning av takingAmount
verdi hvis det skjer. I denne situasjonen vil thresholdAmount
verdi sikrer at makingAmount
verdi returnert er ikke uventet liten.
Det finnes to utnyttelsesmetoder, hver unike for en av de tidligere nevnte kodestiene. Disse utnyttelsesmetodene krever ondsinnet getMakerAmount
og getTakerAmount
funksjoner. En enkel implementering av disse funksjonene ville ha en identisk oppførsel som AmountCalculator
's getMakerAmount
og getTakerAmount
funksjoner, men med en hardkodet bryter som vil tvinge dem til å returnere en angriperkontrollert verdi ved behov.
Det første, mindre alvorlige utnyttelsesmønsteret involverer den første kodebanen der makingAmount
verdien er spesifisert i en fyllingsrekkefølge. En ondsinnet produsent ville vente på en fyllordre som spesifiserer makingAmount
å dukke opp i mempoolen for å frontkjøre den. De ville tappe hele verdien unntatt 1 fra produsentens side og deretter tvinge _callGetTakerAmount
for å returnere beløpet som er spesifisert i brukerens thresholdAmount
verdi (eller godtgjørelsen hvis den er mindre). Når brukerens transaksjon endelig går gjennom, vil de bytte sin fulle thresholdAmount
verdt takerAsset
for en enkelt enhet på makerAsset
. Denne utnyttelsen er begrenset av beløpet gitt av thresholdAmount
verdi eller mengden av takerAsset
brukeren tillatt på LimitOrderProtocol
kontrakt.
Det andre, mer alvorlige utnyttelsesmønsteret involverer den andre kodebanen der takingAmount
verdien er spesifisert. Den ondsinnede produsenten ville på samme måte vente på en fyllordre som spesifiserte en takingAmount
verdi for å vises i mempoolen. De ville kjøre transaksjonen i forkant og tvinge frem makingAmount
verdi returnert av _callGetMakerAmount
funksjon til å være høyere enn begge remainingMakerAmount
og thresholdAmount
. De ville også sette takingAmount
returnerte verdi av _callGetTakerAmount
å være mengden av takerAsset
eiendel tillatt på LimitOrderProtocol
av mottakeren. Når mottakerens transaksjon går gjennom, vil den gjøre det avkorte makingAmount
verdi og deretter beregne på nytt takingAmount
verdi. Denne omberegningen er imidlertid ikke garantert lavere, og vil i dette tilfellet tappe takeren for alle takerAsset
som de tillot på kontrakten. I denne kodestien er thresholdAmount
verdien er å sikre at makingAmount
er ikke for lav, så tar alle takers takerAsset
eiendelen er ukontrollert. De tapte midlene er begrenset av beløpet takerAsset
ressurs brukeren har tillatt på LimitOrderProtocol
kontrakt.
Disse utnyttelsene er ikke mulige uten delordre og, mer spesifikt, delordre med ondsinnet getMakerAmount
og getTakerAmount
implementeringer.
Hovedutgaven av thresholdAmount
verdisjekken er at den bare dekker den ene siden av byttet, men den andre siden kan manipuleres via frontrunning. Det er ingen forsikringer om at verdien den opprinnelig foreslo forblir uendret. Vurder å fjerne makingAmount
trunkering fra begge kodebaner og tilbakestilling hvis ordren ikke kan støtte en så stor fylling som forespurt. Ved å gjøre dette vil thresholdAmount
kan brukes til å begrense den andre siden av byttet tilstrekkelig og unngå uventet oppførsel, selv i ondsinnede bestillinger.
Oppdatering: Fast i trekk forespørsel # 83.
Middels alvorlighetsgrad
[M01] Statiske argumenter sendt etter dynamiske argumenter
på OrderMixin
kontrakt, den getTakerAmount
og getMakerAmount
bytes-felt brukes som argumenter for _callGetTakerAmount
og _callGetMakerAmount
funksjoner. Disse samtalene gir en måte å beregne den ene siden av byttet basert på den andre siden, og de lar brukere delvis fylle bestillinger.
De getTakerAmount
/getMakerAmount
felt er dynamiske variabler og er pakket foran takerAmount
og makerAmount
verdier i _callGetTakerAmount
og _callGetMakerAmount
funksjoner. Det er mulig for en ondsinnet produsent å gi mer data enn forventet i getTakerAmount
oggetMakerAmount
felt for å skyve takerAmount
og makerAmount
bytes forbi der de antas å være når de dekodes i neste funksjon. Dette gjør det mulig for produsenten å flytte inntakeren eller produsentbeløpet med en full byte til høyre og til og med erstatte dem fullstendig hvis det gis ytterligere 32 byte med data.
Brukere må allerede gjennomgå manuelt getTakerAmount
og getMakerAmount
felt i rekkefølgen, men denne teknikken er ganske vanskelig å få øye på. Også verdt å merke seg, dette angrepet gjelder til og med internt pålitelige getMakerAmount
og getTakerAmount
funksjoner. For de fleste angrep vil det å gi et rimelig terskelbeløp forhindre tap av midler.
For å forhindre dette bør du vurdere å kode de statiske argumentene før de dynamiske argumentene for å unngå å gi de dynamiske argumentene en metode for å kontrollere de statiske argumentene.
Oppdatering: Ikke fikset. 1-tommers teamet uttalte:
Vi vil være ekstra forsiktige med getters-validering. Vi vil prøve å implementere fornuftsvalidering av gettere i vår sdk som vil hjelpe med å filtrere potensielt ondsinnede bestillinger.
[M02] ERC721-ordrer kan manipuleres
Det er mulig å bytte mer enn bare ERC20s via OrderMixin
ved å distribuere en kontrakt som deler samme funksjonsvelger som IERC20s transferFrom
, og gir den kontrakten som makerAsset
eller takerAsset
i en ordre.
Fullmakter utenfor virkeområdet, nemlig ERC721Proxy
, ERC721ProxySafe
og ERC1155Proxy
kontrakter følger dette mønsteret for å gi støtte til ERC721
og ERC1155
tokens. Siden proxyene må kalles med samme mønster som en IERC20 transferFrom
ring, må signaturen starte med address from
, address to
og uint256 amount
. Alt annet som fullmaktene krever kan sendes inn etter, og defineres i rekkefølgen som makerAssetData
og takerAssetData
.
ERC1155s kan naturlig overføre flere av de samme id-tokenene samtidig, noe som betyr ERC1155Proxy
kontrakten gjør bruk av amount
felt. På den andre siden, ERC721
s har ikke en åpenbar bruk for amount
felt. Siden de representerer ikke-fungible tokens, vil en spesifikk tokenId bare ha en i eksistens, noe som gjengir amount
feltet ubrukelig. På grunn av dette, implementeringen for begge ERC721Proxy
og ERC721ProxySafe
kontrakter bruker de nødvendige amount
feltet som tokenId
i stedet.
Denne overbelastningen av amount
parameter skaper mulighet for delvis fylling ERC721
bestillinger for å kjøpe separat oppførte tokens til rabatterte priser. For eksempel kan det være et tilfelle der en enkelt bruker har flere ERC721
s av samme kontrakt tillatt å bli overført av ERC721Proxy
kontrakt og viser dem i separate grenseordre.
Hvis grenseordrene også gir getMakerAmount
og getTakerAmount
felt, vil det være mulig å delvis fylle ut disse ERC721
bestillinger. Siden bestillingen amount
feltet tilsvarer faktisk tokenId
, kan en ondsinnet bruker plassere en delvis fylling på ERC721
med den høyere tokenId, noe som resulterer i en makingAmount
/takingAmount
av en ERC721
som kan tilsvare en lavere tokenId
. Resultatet er ERC721
med det nedre tokenId
ville bli overført til prisen av (higher tokenId price) * (lower tokenId's id) / (higher tokenId's id)
.
Denne utnyttelsen har noen krav:
- multiple
ERC721
s fra samme kontrakt som skal tillates på entenERC721
fullmakt fra en enkelt eier. - Åpen ordre for en av
ERC721
s det er ikke det lavestetokenId
av de tillatte. - Delvis fyllinger tillatt på bestillingen.
For å helt fjerne muligheten for delvis ERC721
fyller, vurder å skille amount
og tokenId
argumenter. Enten argumentene er atskilt eller ikke, vurder også å dokumentere dette for å varsle brukere om denne atferden og for å unngå dette mønsteret i fremtiden.
Oppdatering: Fast i trekk forespørsel # 59.
[M03] Udokumenterte desimalforutsetninger
De LimitOrderProtocol
kontrakten arver ChainlinkCalculator
kontrakt gjennom OrderMixin
kontrakt. Denne kontrakten avslører to funksjoner for å muliggjøre bruk av Chainlink-orakler under predikater sjekke og oppslaget av produsentbeløp/taker beløp.
Kontrakten gjør imidlertid udokumenterte forutsetninger om antall desimaler som Chainlink-oraklene skal rapportere i, samt antall desimaler som funksjonsparametrene skal inneholde. I visse scenarier kan dette føre til uventet oppførsel, inkludert feilprising av eiendeler og utilsiktet tap av midler.
Mer spesifikt, gjennom hele kontrakten er den implisitte antagelsen at Chainlink-oraklene vil rapportere med 18 desimaler presisjon. Men ikke alle Chainlink orakler rapporter med dette antallet desimaler. Faktisk, hvis oraklet rapporterer et token-par som er i form av en valuta (for eksempel USD), vil det bare ha 8 desimaler med presisjon. Siden det ikke er noen begrensninger på hvilken orakler kan brukes, implisitte antakelser bør ikke gjøres om antall desimaler de vil rapportere med.
Relativt er det en implisitt antakelse om at amount
parameter for ChainlinkCalculator
funksjoner vil bruke 18 desimaler, sammen med den misvisende eksplisitte erklæringen om at singlePrice
funksjon Calculates price of token relative to ETH scaled by 1e18
. I virkeligheten, selv med et orakel som gjør rapport med 18 desimaler, returverdien av singlePrice
funksjonen vil bli skalert med antall desimaler i amount
parameter, som ikke nødvendigvis er 18 desimaler.
På samme måte, doublePrice
funksjonen antar at to Chainlink-orakler vil rapportere med samme antall desimaler, noe som fører til at resultatet av funksjonen avviker fra forventningene.
Vurder å eksplisitt dokumentere forutsetninger om antall desimaler som parametere og returverdier skal være i forhold til. Vurder dessuten enten å begrense beregninger som er avhengige av orakler som bryter disse forutsetningene, eller å la de relevante beregningene ta det faktiske antallet desimaler i betraktning.
Oppdatering: Fast i trekk forespørsel # 75.
Lav alvorlighetsgrad
[L01] Konstanter er ikke deklarert eksplisitt
Det er noen få forekomster av bokstavelige verdier som brukes med uforklarlig betydning i kodebasen. For eksempel:
- på
OrderMixin
kontrakt, den_remaining
kartlegging er semantisk overbelastet (som forklart i problemet Semantisk overbelastning av kartlegging) for å spore mengden aktiva som gjenstår for en delvis fylt ordre i tillegg til hvis en ordre er fullstendig fylt. Nærmere bestemt,0
betyr at ingen fyllinger knyttet til en bestilling er utført,1
betyr at en ordre ikke lenger kan fylles, og noe større enn1
betyr at det er et gjenstående beløp knyttet til bestillingen som potensielt kan fylles. - på
ChainlinkCalculator
kontrakt, den bokstavelige verdien1e18
brukes isinglePrice
funksjon.
For å forbedre kodens lesbarhet og lette refaktorisering, vurder å definere en konstant for hvert magiske tall, og gi det et klart og selvforklarende navn. For komplekse verdier bør du vurdere å legge til en innebygd kommentar som forklarer hvordan de ble beregnet eller hvorfor de ble valgt.
Oppdatering: Fast i trekk forespørsel # 75 og trekk forespørsel # 76.
[L02] Ondsinnede parter kan forhindre utførelse av tillatte ordre
De OrderMixin
kontrakt lar maker brukere sende inn tillatte bestillinger slik at de kan utføres i én transaksjon, i stedet for å måtte ha en separat transaksjon for godkjenning. Også ordremottakere kan sende inn egen tillatelse under utfyllingen av bestillingen for samme formål.
Imidlertid, fordi produsenttillatelsen er inneholdt i rekkefølge, vil både produsentens og mottakerens tillatelser være tilgjengelige mens ordreutfyllingstransaksjonen er i mempoolen. Dette vil gjøre det mulig for enhver ondsinnet bruker å ta disse tillatelsene og utføre dem på de respektive aktivakontraktene mens de kjører utfyllingstransaksjonen på forhånd. Fordi disse tillatelsene har en nonce
for å forhindre et dobbeltforbruksangrep, ville ordrens utfyllingstransaksjon mislykkes som et resultat av forsøk på å bruke samme tillatelse som nettopp ble brukt under frontrun.
Selv om det ikke er noen sikkerhetsrisiko, og produsenten kan opprette en ny ordre og forhåndsgodkjenne transaksjonen, kan dette angrepet absolutt påvirke brukervennligheten til tillatte bestillinger. Faktisk kan en motivert angriper blokkere alle tillatte ordre med dette angrepet. Vurder å validere om tillatelsen allerede er sendt inn, eller om godtgjørelsen er nok, under bestillingen. Vurder også å informere brukerne om dette mulige angrepet under bestillingssammensetningen.
Oppdatering: Ikke fikset. 1-tommers teamet sier:
Vi hadde godkjenningssjekker før, men bestemte oss for å forenkle tillatelsesflyten for å bare gå tilbake på mislykkede godkjenninger. Vi vil tenke på måtene å varsle produsenter om problemet.
[L03] Duplisert kode
Det er forekomster av duplisert kode i kodebasen. Duplisering av kode kan føre til problemer senere i utviklingens livssyklus og gjør prosjektet mer utsatt for introduksjon av feil. Slike feil kan utilsiktet introduseres når funksjonalitetsendringer ikke replikeres på tvers av alle forekomster av kode som skal være identiske. Eksempler på duplisert kode inkluderer:
I stedet for å duplisere kode, bør du vurdere å ha bare én kontrakt eller et bibliotek som inneholder den dupliserte koden og bruke den når den dupliserte funksjonaliteten er nødvendig.
Oppdatering: Delvis fast i trekk forespørsel # 60.
[L04] Feilaktig eller misvisende testpakke
Det er tilfeller i testpakken hvor testene avviker fra forventet oppførsel. For eksempel:
- De
ChainlinkCalculator
kontrakten er arvet avOrderMixin
kontrakt. Imidlertid, under testeneAmountCalculator.arbitraryStaticCall
funksjonen brukes til å kalleChainlinkCalculator
kontrakt som en ekstern, uavhengig kontrakt. Selv om resultatet er det som forventes, bør testen gjenspeile atferden med gjeldende design av systemet og forventet bruk ved å ringeChainlinkCalculator
fungerer direkte uten å bruke det vilkårlige statiske anropet. - Selv om fullmaktskontraktene var utenfor omfanget, la vi merke til at når vi testet protokollen med ERC721-eiendeler,
ERC721Proxy
kontrakten brukes ikke til å bytte eiendeler i sin testsuite.
Siden selve testpakken er utenfor omfanget av denne revisjonen, bør du vurdere å gjennomgå testpakken grundig for å sikre at alle tester kjører vellykket i henhold til spesifikasjonene til protokollen.
Oppdatering: Fast i trekk forespørsel # 57, trekk forespørsel # 59og trekk forespørsel # 61.
[L05] Feil og utelatelser i arrangementer
Gjennom hele kodebasen sendes det vanligvis ut hendelser når det gjøres sensitive endringer i kontraktene. Imidlertid mangler mange hendelser indekserte parametere og/eller mangler viktige parametere. For eksempel:
Det er også sensitive handlinger som mangler hendelser, for eksempel:
Vurder å mer fullstendig indeksere eksisterende hendelser og legge til nye parametere der de mangler. Vurder også å sende ut alle hendelser på en så fullstendig måte at de kan brukes til å gjenoppbygge kontraktens tilstand av tjenester utenfor kjeden.
Oppdatering: Ikke fikset. Imidlertid la 1-tommers-laget til en orderRemaining
parameter til OrderCanceled
hendelse i trekk forespørsel # 62.
1-tommers teamet sier:
Vi fant at bare et begrenset delsett av data er nødvendig for å tilfredsstille frontend-behov. Ved omfattende analyser er alle de foreslåtte feltene tilgjengelige via sporing. Til
OrderRFQMixin
vi forventer at markedsmakere bygger sin egen sofistikerte måte å spore hvilke bestillinger som er kansellert.
[L06] Lagring endres under hendelsesutslipp
på NonceManager
kontrakt, når NonceIncreased
hendelsen sendes ut, avsenderens nonce økes også.
Å utføre flere operasjoner samtidig kan gjøre kodebasen vanskeligere å resonnere rundt, mer utsatt for feil, og kan føre til at operasjoner blir oversett eller misforstått.
For å forbedre den generelle intensjonaliteten, lesbarheten og klarheten til koden, bør du vurdere å øke nonce-verdien før du sender ut hendelsen.
Oppdatering: Fast i trekk forespørsel # 63.
[L07] Inkonsekvente dekodingsmetoder kan forårsake utfallsavvik
For å støtte all dens utvidbarhet og fleksibilitet, må Limit Order Protocol rutinemessig håndtere dynamiske bytedata og vilkårlige returverdier fra eksterne kontrakter. Som et resultat inkluderer protokollen en ArgumentsDecoder
bibliotek for mer effektivt å konvertere dynamiske byte-verdier til grunnleggende datatyper. Dette biblioteket brukes imidlertid ikke utelukkende, og i noen tilfeller abi.decode
brukes i stedet. I tillegg bruker noen kontrakter abi coder v1
mens andre bruker abi coder v2
. Førstnevnte opptrer mer likt ArgumentsDecoder
bibliotek, mens sistnevnte utfører ytterligere kontroller ved dekoding.
Den inkonsekvente bruken av disse forskjellige dekodingsmetodene kan resultere i subtile avvik mellom intensjonen og den faktiske oppførselen til kodebasen.
For eksempel, simulateCalls
funksjonen bruker bare ArgumentsDecoder.decodeBool
funksjon. Hvis den simulateCalls
funksjonen brukes til å sjekke anrop som vil bli gjort i predikatdelen av en ordre, så kan resultatene avvike fra det som faktisk skjer når predikatbetingelsene evalueres, fordi forskjellige dekodingsmetoder brukes.
Så, for eksempel, hvis et predikat utgjør et eksternt staticcall
til en funksjon som returnerer en uint256
verdi større enn én i stedet for forventet bool
, så går det anropet tilbake, fordi returverdien er dekodet med abi coder v2
's abi.decode
som ikke vil akseptere slike verdier som bool
. Imidlertid, hvis nøyaktig samme samtale gjøres med simulateCalls
, da det vil ganske enkelt bli merket som true
, fordi decodeBool
behandler enhver verdi større enn null som true
.
For å gjøre simulateCalls
funksjonen speiler fullstendig oppførselen til faktiske predikatanrop, vurder å endre den til bruk abi.decode
.
Oppdatering: Fast i trekk forespørsel # 82.
[L08] Mangel på inndatavalidering
De fillOrderToWithPermit
og fillOrderTo
funksjoner av OrderMixin
kontrakt, samt fillOrderRFQToWithPermit
og fillOrderRFQTo
funksjoner av OrderRFQMixin
kontrakt, ikke valider target
adresseparameter.
Dette gjør det mulig for en bruker utilsiktet å sende inn nulladressen og som et resultat låse opp eiendelene de er ment å motta etter å ha fullført en ordre.
For å sikre at brukere ikke ved et uhell låser opp pengene sine, bør du vurdere å validere at target
adresse er ikke lik nulladressen i de siterte funksjonene.
Oppdatering: Fast i trekk forespørsel # 78.
[L09] Lav enhetstestdekning
Enhetstestdekningen for hele prosjektet er på rundt 75 %, hvor noen av kontraktene har spesielt lav dekning.
Tatt i betraktning viktigheten av enhetstester for å validere kode og forhindre regresjoner ved refaktorisering og utvikling av nye funksjoner, oppfordrer vi til en betydelig økning av enhetstestdekningen til minst 95 %, og inkluderer kanttilfeller som dekker selv usannsynlige situasjoner.
Oppdatering: Ikke fikset.
[L10] Villedende eller ufullstendig innebygd dokumentasjon
Gjennom hele kodebasen ble noen få tilfeller av villedende og/eller ufullstendig innebygd dokumentasjon identifisert og bør fikses.
Følgende er tilfeller av villedende innebygd dokumentasjon:
- på
ChainlinkCalculator
kontrakt, densinglePrice
funksjoner NatSpec@notice
stikkord sier at detCalculates price of token relative to ETH scaled by 1e18
, men faktisk er resultatet det verdi ofamount
tokens skalert etter1e18
, der oraklet kanskje ikke rapporterer i form av ETH (for eksempel for et par som ikke inkluderer ETH). - på
OrderRFQMixin
kontrakt, deninvalidatorForOrderRFQ
funksjoner NatSpec@return
stikkord er misvisende, fordi tilbudet kanskje ikke er fylt ut for at den respektive invalidatorbiten skal ha blitt satt. Bestillingen kan også ha blitt kansellert. - På linjer 147, 165og 188 of
OrderMixin.sol
, NatSpec@param
kodene er ugrammatiske. - På nett 20 of
ERC1155Proxy.sol
den@notice
taggen sier at den beregnede hashen er et resultat av hashing avfunc_733NCGU
funksjon, hvor den skal værefunc_301JL5R
funksjon i stedet.
Følgende er tilfeller av ufullstendig innebygd dokumentasjon:
- Funksjoner i
AmountCalculator
kontrakten beskriver ikke noen av parameterne. - på
ChainlinkCalculator
kontrakt, densinglePrice
ogdoublePrice
funksjoner beskriver ikke alle parameterne. - på
ImmutableOwner
kontrakt, den offentlige variabelen og modifikatoren har ingen NatSpec. - på
InteractiveNotificationReceiver
kontrakt, dennotifyFillOrder
funksjonen beskriver ikke noen av parameterne. - på
LimitOrderProtocol
kontrakt, denDOMAIN_SEPARATOR
funksjonen har ingen NatSpec. - Hendelser og kartlegginger i
NonceManager
har ingen NatSpec. - på
OrderRFQMixin
kontrakt,cancelOrderRFQ*
funksjoner beskriver ikke returverdiene. - på
OrderMixin
kontrakt, flere funksjoner mangler fullstendig NatSpec. - På nett 168 of
OrderMixin.sol
og på nett 71 ofOrderRFQMixin.sol
, mangler den@dev
tag. - Funksjoner i
PredicateHelper
kontrakten beskriver ikke alle parameterne.
Tydelig inline-dokumentasjon er grunnleggende for å skissere intensjonene med koden. Uoverensstemmelser mellom inline-dokumentasjonen og implementeringen kan føre til alvorlige misoppfatninger om hvordan systemet forventes å oppføre seg. Vurder å fikse disse feilene for å unngå forvirring for utviklere, brukere og revisorer.
Oppdatering: Delvis fikset. Villedende dokumentasjon adressert i trekk forespørsel # 75 og trekk forespørsel # 77.
1-tommers teamet sier:
Vi har rettet opp villedende dokumenter. Fullføring av dokumentene vil bli gjort senere.
[L11] DoS-bestillinger mulig ved bruk av kroker
De OrderMixin
kontrakt implementerer funksjonalitet for å fylle generiske off-chain-bytteordrer som kan ha betingelser for suksess. Under ordrefylling kan ordren sjekk de forhåndsdefinerte "predikat"-betingelsene før du fortsetter med utførelse.
Men fordi disse predikatbetingelsene kan være rettet mot logikken til enhver vilkårlig kontrakt, kan en ondsinnet produsent lure mottakere til å tro at en ordre oppfører seg riktig og at den er gyldig når den sjekkes utenfor kjeden, men deretter mislykkes når han prøver å fylle den samme ordren. på kjeden. Denne endringen i predikatoppførselen kan enten gjøres ved å kjøre en eller annen variabel tilstand som predikatene er avhengig av, ved å undersøke gassen som sendes eller til og med hvilke adresser som er involvert i samtalen, eller ved en annen logikk.
Videre, hvis produsenten definerte en interaksjon under byttetden interactionTarget
kontrakt kan gå tilbake eller tilbakekalle godtgjørelsen for å forhindre en vellykket ordrefylling, noe som i hovedsak fører til samme resultat som ondsinnede predikater.
Selv om eiendeler ikke vil være i fare, vil brukere eller roboter som finner en gunstig bestilling ha den økte byrden med å prøve å identifisere denne typen spam-bestillinger som kan virke legitime på overflaten. I tilfelle de ikke klarer å identifisere denne typen bestillinger, vil de pådra seg bortkastede gasskostnader. For å redusere mengden spam-bestillinger bør du vurdere å begrense tilgjengelige mål for disse krokene. Vurder også å advare brukere om denne muligheten før de prøver å fylle bestillinger.
Oppdatering: Ikke fikset. 1-tommers teamet sier:
Vi håndterer det på vår backend, og vi vil tenke på måtene å varsle mulige mottakere om problemet.
[L12] Avrunding kan være ugunstig for taker
på OrderMixin
og OrderRFQMixin
kontrakter, når en ordre blir fylt og mottakeren gir kun en makingAmount
or takingAmount
beløp, prøver protokollen å beregne motpartsbeløpet for byttet.
Det er to problemer med disse beregningene, den første er at det ikke er noen dokumentasjon eller logikk som begrenser antall desimaler som beløpsparameterne skal bruke, noe vi tok for oss i Udokumenterte desimalforutsetninger utgave.
Det andre problemet er at protokollen i løpet av disse beregningene avrundes til fordel for produsenten. Avrundingsproblemet kan bli kraftig forverret når de implisitte desimalforutsetningene brytes, men selv når alt er i de forventede vilkårene, vil avrunding skje med små, odde beløp.
Vurder å la brukeren spesifisere et minimumsbeløp på makerAsset
eiendel som de er villige til å motta sammen med et maksimumsbeløp på takerAsset
eiendel de er villige til å bytte, slik at aksepten av enhver avrunding er mer eksplisitt.
Oppdatering: Ikke fikset. 1-tommers teamet sier:
Terskelbeløpet bør være nok for mottakerens beskyttelse.
[L13] Motstridende ordrehåndtering ved manglende parametere
på OrderMixin
kontrakt, den fillOrderTo
funksjonen foretar interne anrop til _callGetMakerAmount
og _callGetTakerAmount
fungerer når en fylling er forsøkt, og enten makingAmount
eller takingAmount
parametere er henholdsvis null, eller hvis makingAmount
verdien er større enn remainingMakerAmount
verdi.
De _callGetMakerAmount
og _callGetTakerAmount
anrop vil føre til tilbakeføringer hvis bestillingen ikke ble opprettet med getMakerAmount
or getTakerAmount
parametere, henholdsvis, og en delvis fylling blir utført.
An innebygd kommentar ved siden av _callGetMakerAmount
og en innebygd kommentar ved siden av _callGetTakerAmount
hevder at "bare hele fyllinger er tillatt" hvis bestillingen ikke ble opprettet med getMakerAmount
or getTakerAmount
parametre.
Imidlertid er det kodestier som dette ikke gjelder, fordi disse banene ikke sjekker length
s av begge getMakerAmount
og getTakerAmount
parametre.
Nærmere bestemt, når en taker
spesifiserer a takerAmount
verdi for en ordre som bare har en getMakerAmount
, med mindre det ringer til getMakerAmount
returnerer et beløp større enn remainingMakerAmount
, kan en delvis fylling utføres i motsetning til inline-dokumentasjonen.
Dette gjør intensjonen til disse kodebanene uklare. Hvis dette er den forventede oppførselen, bør du vurdere å endre den innebygde dokumentasjonen slik at den blir mer eksplisitt. Hvis dette er utilsiktet oppførsel, bør du vurdere å alltid sjekke lengden på begge getMakerAmount
og getTakerAmount
parametere samtidig slik at implementeringen forsterker atferden beskrevet av inline-dokumentasjonen.
Oppdatering: Fast i trekk forespørsel # 79.
[L14] Bruker utdaterte Chainlink-anrop
De ChainlinkCalculator
kontrakten er ment å brukes til å spørre etter Chainlink-orakler. Det gjør det ved å ringe til deres latestTimestamp
og latestAnswer
metoder, som begge er avviklet. Faktisk er metodene ikke lenger til stede i API-en til Chainlink-aggregatorer fra versjon tre.
For å unngå potensiell fremtidig inkompatibilitet med Chainlink-orakler, bør du vurdere å bruke latestRoundData
metode i stedet.
Oppdatering: Fast i trekk forespørsel # 67.
Merknader og tilleggsinformasjon
[N01] Importerer ikke grensesnitt
De AggregatorInterface
grensesnitt ser ut til å være en undergruppe av kode kopiert fra ChainLink
sitt offentlige kodelager. Hele grensesnittet er inkludert i ChainLink
sin kontrakt npm-pakke.
Når det er mulig, for å redusere potensialet for grensesnittfeil og resulterende problemer, i stedet for å redefinere og/eller omskrive et annet prosjekts grensesnitt, bør du vurdere å bruke grensesnitt installert via deres offisielle npm-pakker i stedet.
Oppdatering: Fast i trekk forespørsel # 66.
[N02] Utdaterte prosjektavhengigheter
Under installasjonen av prosjektets avhengigheter, advarer NPM at en av pakkene som er installert, Highlight
, "vil ikke lenger støttes eller motta sikkerhetsoppdateringer i fremtiden".
Selv om det er usannsynlig at denne pakken kan forårsake en sikkerhetsrisiko, bør du vurdere å oppgradere avhengigheten som bruker denne pakken til en vedlikeholdt versjon.
Oppdatering: Fast i trekk forespørsel # 64.
[N03] Eksterne anrop for å vise metoder er ikke statiske anrop
Gjennom det meste av kodebasen foretar protokollen eksplisitt eksterne anrop via OpenZeppelin's functionStaticCall
metode for å begrense muligheten for tilstandsendringer når de enten ikke er forventet eller ikke ønskelig. Imidlertid, i ChainlinkCalculator
kontrakt, til tross for intensjonen om å foreta eksterne samtaler kun til view
metoder på Chainlink orakler, de eksterne samtalene i singlePrice
og doublePrice
funksjoner er ikke laget via eksplisitt staticcall
s.
Selv om vi ikke identifiserte noen umiddelbare sikkerhetsproblemer som stammer fra dette, bør du vurdere å bruke eksplisitt for å redusere angrepsoverflaten, forbedre konsistensen og klargjøre intensjonen. staticcall
s, for alle eksterne samtaler til view
funksjoner i ChainlinkCalculator
kontrakt.
Oppdatering: Ikke fikset. 1-tommers teamet sier:
Vi tror at syntakskomplikasjon opphever forbedringer i konsistens.
[N04] Ikke feil tidlig med ugyldige bestillinger
på OrderMixin
kontrakt, den fillOrderTo
funksjonen håndterer den spesielle tilstanden når en ordre ikke tidligere er sendt (remainingMakerAmount == 0
), men den håndterer ikke eksplisitt tilstanden når bestillingen ikke lenger er gyldig (remainingMakerAmount == 1
).
I sistnevnte scenario vil funksjonen til slutt gå tilbake, men først etter brenning av ikke-trivielle mengder gass. For å klargjøre intensjonen, øke lesbarheten og redusere gassbruken, bør du vurdere eksplisitt å håndtere scenariet for ugyldig rekkefølge mot begynnelsen av funksjonen.
Oppdatering: Fast i trekk forespørsel # 68.
[N05] Hjelpekontrakter er ikke merket som abstrakt
I Solidity, nøkkelordet abstract
brukes for kontrakter som enten ikke er funksjonelle kontrakter i seg selv, eller som ikke er ment å brukes som sådan. I stedet, abstract
kontrakter arves av andre kontrakter i systemet for å lage frittstående funksjonskontrakter.
Gjennom hele kodebasen er det eksempler på hjelpekontrakter som ikke er merket som abstrakte, til tross for at de ikke er ment å utplasseres på egen hånd. For eksempel AmountCalculator
, ChainlinkCalculator
, ImmutableOwner
, NonceManager
og PredicateHelper
Kontrakter består alle av et basissett med funksjoner som er ment å brukes av arvende kontrakter.
Vurder å merke hjelpekontrakter som abstract
for å tydelig markere at de er utformet utelukkende for å legge til funksjonalitet til kontrakter som arver dem.
Oppdatering: Ikke fikset. 1-tommers teamet sier:
Disse hjelperne kan utplasseres separat. De arves kun for å spare gass.
[N06] Inkonsekvent funksjonsbestilling
Gjennom hele kodebasen følger funksjonsrekkefølgen vanligvis anbefalt rekkefølge i Solidity Style Guide, som er: constructor
, fallback
, external
, public
, internal
, private
.
Imidlertid, i OrderMixin
kontrakt, den public
checkPredicate
funksjonen avviker fra stilguiden, og halverer external
funksjoner.
For å forbedre prosjektets generelle lesbarhet, vurder å standardisere funksjonsrekkefølgen gjennom kodebasen, som anbefalt av Solidity Style Guide.
Oppdatering: Fast i trekk forespørsel # 69.
[N07] Inkonsekvent ordrefyllingsflyt
De OrderMixin
og RFQOrderMixin
kontrakter håndterer begge utfylling av signerte ordre, men den generelle ordreflyten mellom de to kontraktene er inkonsekvent.
OrderMixin
's fillOrderTo
funksjonen følger denne generelle flyten (pseudo-kode):
if ((takingAmount == 0) == (makingAmount == 0))
else if (takingAmount == 0)
else (handle makingAmount == 0) THEN swapTokens
mens RFQOrderMixin
er analogt fillOrderRFQTo
funksjonen følger denne flyten (pseudo-kode):
if (takingAmount == 0 && makingAmount == 0)
else if (takingAmount == 0)
else if (makingAmount == 0)
else revert THEN swapTokens
Det er ingen innsikt fra dokumentasjonen om hvorfor den første betingelsen i hver av disse to funksjonene er forskjellig, eller hvorfor takingAmount
og makingAmount
kan ikke begge være null i sistnevnte funksjon. Også tilfellet hvor både en makingAmount
og en takingAmount
er gitt er mye lettere å resonnere om i fillOrderRFQTo
funksjon, siden den håndteres tydelig i finalen else
blokkere.
For å tydeliggjøre intensjonen og øke den generelle lesbarheten til koden, vurder enten å standardisere den generelle ordreflyten på tvers av disse to kontraktene, eller eksplisitt dokumentere hvorfor forskjellene eksisterer.
Oppdatering: Ikke fikset. 1-tommers teamet sier:
Dette skyldes tilpassede prisfunksjoner i begrensede bestillinger. Siden
getMakerAmount
kan potensielt avvike vesentlig fragetTakerAmount
, vi tenkte at det er bedre å ikke lage standardalternativer for brukeren, da det sannsynligvis vil forvirre dem i tilfeller der disse blir forskjellige.
[N08] Feilmeldinger er inkonsekvent formatert eller villedende
Gjennom hele kodebasen er require
og revert
feilmeldinger, som er ment å varsle brukere om de spesielle forholdene som fører til at en transaksjon mislyktes, ble funnet å være inkonsekvent formatert.
For eksempel, hver av feilmeldingene på linjer 85 av OrderMixin.sol
, 16 av ERC721ProxySafe.sol
og 26 av Permitable.sol
bruke en annen stil.
I tillegg er noen feilmeldinger villedende:
Feilmeldinger er ment å varsle brukere om sviktende forhold, så de bør gi nok informasjon slik at passende rettelser kan gjøres for å samhandle med systemet. Uinformative feilmeldinger skader i stor grad den generelle brukeropplevelsen, og reduserer dermed systemets kvalitet. Dessuten kan inkonsekvent formaterte feilmeldinger føre til unødvendig forvirring. Vurder derfor å gjennomgå hele kodebasen for å sikre at alle require
og revert
setningen har en feilmelding som er konsekvent formatert, nøyaktig, informativ og brukervennlig.
Oppdatering: Delvis fast i trekk forespørsel # 81.
[N09] Inkonsekvent bruk av navngitte returvariabler
Det er en inkonsekvent bruk av navngitte returvariabler i OrderMixin
kontrakt. Noen funksjoner returnere navngitte variabler, andre returnere eksplisitte verdier, og andre erklære en navngitt returvariabel, men overstyr den med en eksplisitt returerklæring.
Vurder å ta i bruk en konsistent tilnærming til returverdier gjennom hele kodebasen ved å fjerne alle navngitte returvariabler, eksplisitt erklære dem som lokale variabler og legge til nødvendige retursetninger der det er aktuelt. Dette vil forbedre både eksplisittheten og lesbarheten til koden, og det kan også bidra til å redusere regresjoner under fremtidige koderefaktorer.
Oppdatering: Fast i trekk forespørsel # 73.
[N10] Ordrens hash-beregning er ikke åpen for API
De external
funksjoner remaining
, remainingRaw
og remainingsRaw
alle forventer en ordrehash for vellykket drift.
Men hjelpefunksjonen _hash
, som returnerer hashen til en ordre, har private
synlighet. Dette betyr at brukere må pakke deler av bestillingene og domenestrengene manuelt for å få hashen til en bestilling.
For å unngå potensialet for feil ved beregning av ordrehasher og for å gi brukerne en metode for å generere en ordres respektive hash, bør du vurdere å utvide synligheten til _hash
funksjon til public
og refaktorerer navnet til hash
for å være i samsvar med resten av koden.
Oppdatering: Fast i trekk forespørsel # 74.
[N11] Semantisk overbelastning av kartlegging
De _remaining
kartlegging i OrderMixin
kontrakten er semantisk overbelastet for å spore statusen til bestillinger og gjenværende mengde aktiva som er tilgjengelig for disse bestillingene.
De tre statene den kan ta på seg er:
0
: Ordrehashen er ikke sett ennå.1
: Bestillingen er enten kansellert eller fullstendig fylt.- Noen
uint
større enn1
: Det gjenværendemakerAmount
tilgjengelig for å fylles på bestillingen pluss1
.
Denne semantiske overbelastningen krever innpakning og utpakking av denne verdien under lookup
, cancellation
, initialization
og storage
.
Semantisk overbelastning og nødvendig logikk for å aktivere det kan være utsatt for feil og kan gjøre kodebasen vanskeligere å forstå og resonnere rundt, det kan også åpne døren for regresjoner i fremtidige oppdateringer av koden.
For å forbedre kodens lesbarhet bør du vurdere å spore fullføringstilstanden for bestillinger i en egen kartlegging.
Oppdatering: Ikke fikset. 1-tommers teamet siterte at en løsning ville øke gasskostnadene for fillOrder
funksjon.
[N12] Bestillinger med tillatelse tillater innkalling til vilkårlige kontrakter
De OrderMixin
kontrakten arver Permitable
kontrakt for å tillate utfylling av enkelttransaksjonsordre med eiendeler som aksepterer slike permit
oppfordringer til å endre kvoter.
Imidlertid ringer til Permitable
kontrakt ikke valider om målet er et tillatt aktivum eller om det til og med er et aktivum, som kan tillate en ondsinnet bruker å sende adressen til en vilkårlig kontrakt som kan utføre et nytt anrop før bestillingen fullføres.
Selv om kontrakten er beskyttet mot gjeninntreden, å redusere angrepsflaten og forhindre innkalling av eksterne kontrakter under utførelse anbefales alltid. Vurder enten å begrense eiendelen som er involvert i tillatelsen til eiendelene som er involvert i bestillingen eller til en hviteliste for eiendeler for protokollen.
Oppdatering: Ikke fikset. 1-tommers teamet sier:
OrderMixin
har faktisk ikke informasjon om faktiske tokens sommakerAsset
ogtakerAsset
noen ganger er proxyer eller andre mellomkontrakter og informasjon om faktiske tokens lagres i noen vilkårlige byte. Så det er ingen levedyktig måte å begrense hvilken eiendelpermit
blir kalt på.
[N13] solhint
blir aldri aktivert på nytt
Gjennom hele kodebasen er det et par solhint-disable
uttalelser, spesielt de på nettet 23 og på nett 41 of RevertReasonParser.sol
, som ikke avsluttes med solhint-enable
.
Til fordel for eksplisitthet og å være så restriktiv som mulig ved deaktivering solhint
, vurdere å bruke solhint-disable-line
or solhint-disable-next-line
i stedet lik linje 16 av samme fil.
Oppdatering: Fast i trekk forespørsel # 72.
[N14] Skrivefeil
Kodebasen inneholder følgende skrivefeil:
I tillegg prosjektets README
(utenfor omfanget for denne revisjonen) inneholder følgende skrivefeil:
Vurder å rette disse skrivefeilene for å forbedre kodelesbarheten.
Oppdatering: Fast i trekk forespørsel # 71 og trekk forespørsel # 77.
[N15] Bruk av uint
istedenfor uint256
For å favorisere eksplisitt, alle forekomster av uint
skal erklæres som uint256
. Spesielt de i for
løkker på linjer 98 og 119 of OrderMixin.sol
og linjer 16 og 30 of PredicateHelper.sol
.
Oppdatering: Fast i trekk forespørsel # 70.
Konklusjoner
Det ble funnet 3 alvorlige problemer. Noen endringer ble foreslått for å følge beste praksis og redusere den potensielle angrepsoverflaten.
- &
- 7
- Om oss
- adgang
- Ifølge
- Logg inn
- tvers
- Handling
- handlinger
- Ytterligere
- adresse
- Fordel
- Alle
- tillate
- allerede
- Selv
- beløp
- analyse
- api
- tilnærming
- argumenter
- rundt
- eiendel
- Eiendeler
- revisjon
- Back-end
- Begynnelsen
- være
- BEST
- beste praksis
- Bit
- roboter
- bygge
- ring
- hvilken
- saker
- Årsak
- lenke
- endring
- kontroll
- Sjekker
- kode
- komplekse
- tilstand
- forvirring
- konstruksjon
- inneholder
- kontrakt
- kontrakter
- Korreksjoner
- Kostnader
- kunne
- Par
- skaperen
- valuta
- Gjeldende
- dato
- avtale
- Denial of Service
- utplasserings
- utforming
- utviklere
- Utvikling
- gJORDE
- avvike
- forskjellig
- domene
- dobbelt
- dynamisk
- Tidlig
- Edge
- oppmuntre
- spesielt
- ETH
- Event
- hendelser
- alt
- eksempel
- utveksling
- forventet
- erfaring
- Exploit
- Egenskaper
- Felt
- Endelig
- Først
- Fix
- fleksibilitet
- flyten
- følge
- funnet
- fullt
- funksjon
- midler
- framtid
- spill
- GAS
- general
- Giving
- flott
- veilede
- Håndtering
- hash
- hashing
- å ha
- hjelpe
- Høy
- svært
- Hvordan
- HTTPS
- Hybrid
- identifisere
- Påvirkning
- iverksette
- viktig
- importere
- inkludert
- Inkludert
- Øke
- økt
- info
- informasjon
- Infrastruktur
- innsikt
- hensikt
- interesse
- Interface
- involvert
- saker
- IT
- stor
- større
- føre
- ledende
- Bibliotek
- Begrenset
- linje
- Likviditet
- oppført
- lister
- lokal
- så
- oppslag
- større
- maker
- Making
- marked
- Mempool
- speil
- modell
- mest
- Mest populær
- nemlig
- Nye funksjoner
- ikke-fungible
- ikke-fungible symboler
- offisiell
- åpen
- Drift
- Alternativ
- orakel
- rekkefølge
- ordrer
- Annen
- eieren
- Mønster
- Populær
- presentere
- hindre
- pris
- prising
- privat
- prosess
- prosjekt
- prosjekter
- beskyttelse
- protokollen
- gi
- gir
- proxy
- offentlig
- publisere
- Kjøp
- kvalitet
- heve
- Reality
- redusere
- avhengighet
- rapporterer
- Rapporter
- Repository
- Krav
- REST
- Resultater
- avkastning
- anmeldelse
- Risiko
- runder
- Kjør
- SDK
- sikkerhet
- Tjenester
- sett
- delt
- Aksjer
- skift
- lignende
- Enkelt
- liten
- Smart
- Smarte kontrakter
- So
- soliditet
- spam
- spesielt
- utgifter
- Spot
- Begynn
- Tilstand
- Uttalelse
- Stater
- status
- lagring
- stil
- innsendt
- suksess
- vellykket
- vellykket
- støtte
- Støttes
- overflaten
- Bytte om
- system
- Target
- test
- Testing
- tester
- Gjennom
- hele
- tid
- sammen
- token
- tokens
- spor
- Sporing
- Transaksjonen
- Stol
- unik
- oppdateringer
- us
- brukervennlighet
- USD
- USDT
- Brukere
- verktøyet
- verdi
- Se
- synlighet
- vente
- Hva
- hviteliste
- innenfor
- uten
- Arbeid
- verdt
- null