Uniswap-Gift-Pool-Falle: 131.888 Dollar in 29 Stunden

BlockbeatsBlockbeats

Originaltitel: „0 % angezeigt, 12,8 % ausgeführt: Analyse der dynamischen Gebührenfalle eines Uniswap-v4-‚Gift-Pools‘“

Originalautor: Wang Zihao, BitsLab

 

Vom 22. bis 23. August 2026 zeigte ein dynamischer Gebührenpool für USDC/WBNB auf Uniswap v4 auf der BNB Chain in den Aggregator-Preisangeboten eine Gebühr von 0 % an, während den Nutzern bei der tatsächlichen Ausführung eine LP-Gebühr von 12,8 % berechnet wurde. In rund 29 Stunden wickelte dieser Pool 21.086 Transaktionen ab und kassierte Gebühren in Höhe von 131.888 US-Dollar, bevor er geschlossen wurde. Alle betroffenen Transaktionen waren erfolgreich: Der Vertrag wurde nicht gehackt, die Ausgabe lag über dem vom Nutzer gesetzten Mindestbetrag, und es gab keine ungewöhnlichen Signale – die Differenz wurde stillschweigend zur Gebühr.

 

Dieser Artikel nimmt eine Beispieltransaktion als Ausgangspunkt:

(0x7615dec2ce80506ec461a47739eb8533ac2bc7c605ca56c255964481b76363d0: Der Nutzer setzte 5.926,90 USDT ein und erhielt 757,43 USDT weniger als erwartet.) Er zerlegt, wie dieser Pool „0 % angezeigt, 12,8 % ausgeführt“ erreichte: die dreistufige Logik der Gebührenfunktion, den umgangenen Slippage-Schutz und die Whitelist, die andere LP aussperrt. Alle Schlussfolgerungen basieren auf On-Chain-Daten und lokalen kontrollierten Tests.

 

01 Der Weg vom Preisangebot zur Ausführung

Nachdem ein Nutzer einen Swap im Aggregator-Frontend initiiert, verläuft die gesamte Kette wie folgt:

 

 

Auf dieser Kette gibt es zwei Hintergrundfakten, auf denen jede spätere Prüfung aufbaut.

Zunächst die v4-Seite: Sie erlaubt Hooks, die Gebühr pro Transaktion zu überschreiben. PoolKey.fee = 0x800000 deklariert einen dynamischen Gebührenpool; der Hook liefert im dritten Rückgabewert von beforeSwap 0x400000 | fee. Der Code in v4-core, der diesen Rückgabewert entgegennimmt (Pool.sol:303-305):

isOverride() prüft das Override-Flag, removeOverrideFlagAndValidate() entfernt 0x400000 und validiert, dass die Gebühr MAX_LP_FEE = 1.000.000 (100 %) nicht überschreitet. Anschließend wird der Swap mit dieser Gebühr ausgeführt und im Swap-Event protokolliert. Das heißt: Was der Hook zurückgibt, zahlt der Nutzer – solange die Ausgabe über amountOutMin liegt. Dies ist eine offizielle Funktion; die Anpassung der Gebühr an Volatilität oder Bestand ist ein legitimer Anwendungsfall.

Nun zum Hook selbst: Er deklariert nur zwei Berechtigungen. v4 kodiert Berechtigungen in den unteren 14 Bits der Vertragsadresse (Hooks.sol:29-47), validiert sie bei der Bereitstellung und macht sie unveränderlich. Die Flag-Definitionen auf v4-core-Seite und die Adressdekodierung im Vergleich:

 

Der On-Chain-Test von getHookPermissions() liefert genau diese beiden Bits als wahr.

Der Hook hat keinen Quellcode. Dieser Artikel dekompiliert die Gebührenfunktion vollständig aus dem Bytecode – im Folgenden die Verhaltensanalyse dieser bereits on-chain ausgeführten Logik:

Nun zur schichtweisen Betrachtung. Die ersten beiden Ebenen beantworten die Frage „Ist dies eine Simulation?“, die dritte bestimmt, wie viel eine echte Transaktion zahlt.

 

02 Die dreistufige Logik der Gebührenfunktion

Prüfung 1: Aufrufer unterscheiden

Nach dem Aufruf der Gebührenfunktion wird zunächst tx.origin verglichen: Entspricht er einer von drei konstanten Adressen, wird direkt die Fallback-Stufe zurückgegeben. Die Fallback-Stufe ist derzeit auf 0 % konfiguriert.

Die drei Adressen sind nicht willkürlich gewählt. Wenn eth_call keinen from-Wert angibt, liegt der Transaktionsursprung auf der Nulladresse – Aggregatoren geben bei Batch-Preisangeboten in der Regel keinen an. Direkte Verifikation im lokalen Fork:

 

Die erste Ebene erkennt nur diese drei Adressen. Die nächste Ebene zeigt, wie der Hook unterscheiden kann, wenn eine normale Adresse angegeben wird.

 

Prüfung 2: Gas prüfen

Setzt man tx.origin auf eine normale Adresse und versucht es erneut, bleibt die Rückgabe 0 % – die erste Ebene wurde umgangen, aber die Gebühr änderte sich nicht. Das zeigt, dass die erste Ebene nicht die einzige Prüfung ist. Die zweite Ebene: gasleft() * 10100 / 10000 >= gate.

Aggregatoren geben bei Preisangeboten gewöhnlich sehr hohes Gas an, um zu verhindern, dass Kandidatenrouten in der Simulation wegen Gasmangels scheitern; bei echten Transaktionen wird das Gas vor dem Hook bereits durch Router, Autorisierung und vorgeschaltete Hops verbraucht. Derselbe Code, drei Gaswerte:

Die Grenze liegt gemessen zwischen 16,85 M und 16,9 M Gas. Der Unterschied zwischen 30 M und 2,59 M ist der Unterschied zwischen „Preisangebot“ und „Ausführung“.

 

Prüfung 3: Transaktionsweiser Pseudozufall

Echte Transaktionen, die die ersten beiden Ebenen bestehen, gelangen in die dritte Ebene: Der Fingerabdruck der Blockumgebung wird gehasht, modulo 10.000 berechnet, und je nach Ergebnisintervall wird die entsprechende Gebührenstufe zurückgegeben. Aktuell sind drei Stufen konfiguriert: 8 % / 10 % / 10 %; fällt das Ergebnis außerhalb, greift die Fallback-Stufe von 0 %.

Diese Ebene hat zwei bemerkenswerte Designentscheidungen. Der Fingerabdruck mischt drei Felder der Calldata ein – die Calldata eines Aggregator-Preisangebots und die einer echten Route unterscheiden sich ohnehin, also unterscheidet sich auch der Fingerabdruck. Zudem sorgt der transaktionsweise Pseudozufall für eine Verteilung der Gebühren; bei wenigen Transaktionen ist ein Muster schwer zu erkennen, und einfache Regel-Enumeration greift nicht.

In allen 21.086 On-Chain-Events treten 19 historische Gebührenstufen auf (6,8 %–28 %), was zeigt, dass die Gebührenstufen von einer Admin-Funktion nach Bedarf neu konfiguriert wurden; zum Zeitpunkt der Beispieltransaktion galten 12,8 %.

 

Das Gesamtbild der drei Ebenen

 

Damit lässt sich ein „Gift-Pool“ definieren – ein v4-Pool, der gleichzeitig drei Bedingungen erfüllt: PoolKey.fee trägt das Dynamik-Flag; die Gebührenentscheidung liest Ausführungsumgebungssignale (Gas, Origin, Blockumgebung) statt öffentlicher Marktdaten; die Gebühr weicht systematisch zwischen Preisangebot-Simulation und On-Chain-Ausführung ab, zum Vorteil des Pool-Deployers. Die Grenze liegt darin, was die Gebühr liest: Wer für jeden Aufrufer dieselbe Gebühr zurückgibt, betreibt programmierbares Marktdesign; wer je nach „wer fragt“ unterschiedliche Gebühren zurückgibt, täuscht das Routingsystem.

Damit ist der Mechanismus der Gebührenabweichung vollständig. Doch warum die Transaktion trotz eingezogener Gebühr noch erfolgreich ist, ist die nächste Frage.

 

03 Warum der Slippage-Schutz nicht griff

Zunächst der vollständige Pfad und die Beträge dieser Transaktion:

 

 

Das Swap-Event dieses Hops protokolliert die effektive Gebühr im Feld fee: 128000. In v4 entspricht 1.000.000 Einheiten 100 %, also sind 128000 gleich 12,8 %. Der Verlust dieser Transaktion lässt sich aus zwei Blickwinkeln messen: Aus Sicht des Pools wird die Gebühr auf den WBNB-Input erhoben; aus Sicht der gesamten Route beträgt die Differenz zwischen Stablecoin-Eingang und -Ausgang 757,43 USDT, ein Verlust von 12,7794 %, der auch Gebühren vorgeschalteter Hops und Abweichungen vom Peg enthält. Die beiden Zahlen unterscheiden sich nur um 0,02 Prozentpunkte, was zeigt, dass die Hauptquelle des Verlusts die LP-Gebühr dieses Pools ist.

amountOutMin prüft nur die finale Ausgabeuntergrenze, nicht, wie viel Gebühr jeder Zwischen-Hop einbehält:

 

 

Die Gebühr von 12,8 % liegt vollständig innerhalb des Puffers von 20,32 %, die Ausgabe bleibt über der Untergrenze – die Transaktion ist erfolgreich, kein Rollback. Übliche Standardwerte für Stablecoin-Routen liegen bei 0,1 %–1 %; diese Route bot mehr als das 20-Fache an Spielraum. Nutzer halten einen weiten Puffer für „sicherer“, tatsächlich überlässt er jeden Vertrag auf dem Pfad der Selbstdisziplin der Gegenpartei. Als Grafik:

 

 

04 Das Vorgehen des Gift-Pool-Deployers

Whitelist: Andere LP aussperren

Die Whitelist-Logik steckt in beforeAddLiquidity; das Dekompilat:

 

 

Für das Hinzufügen von Liquidität gibt es drei Hürden: zuerst die PoolManager-Aufrufprüfung, die jeder v4-Hook hat, dann der offizielle PositionManager, zuletzt die Whitelist-Prüfung des Positionsinhabers. Adressen, die nicht auf der Liste stehen, werden hier vom Vertrag abgewiesen; andere LP kommen nicht hinein, die Gebühreneinnahmen werden nicht verwässert und fließen vollständig dem Deployer zu. Die Liste selbst wird von einer Admin-Funktion (Selektor 0xc4452e52) adressweise gepflegt.

 

0-%-Stufe und Waschhandel

Betrachtet man alle 21.086 Transaktionen zusammen, zeigt sich ein klares Muster: 6.946 Transaktionen in der 0-%-Stufe mit einem Volumen von 12.947.751 US-Dollar, im Schnitt 1.864 US-Dollar pro Transaktion; 14.140 Transaktionen in Gebührenstufen mit 1.120.106 US-Dollar, im Schnitt 79 US-Dollar. Große Volumina konzentrieren sich in der 0-%-Stufe, Gebühren fallen vor allem bei kleinen Transaktionen an. Die plausibelste Erklärung für große 0-%-Transaktionen ist, dass der Deployer selbst mit hohem Gas handelt: Hohes Gas trifft dieselbe Prüfung wie Aggregator-Preisangebote, und die Gebührenkosten für Eigenhandel liegen nahe null. Das erzeugte Volumen katapultiert den Pool in die Rankings der Marktplätze (Schnappschuss: ca. 10,82 Mio. US-Dollar und 16.671 Transaktionen in 24 h); in den Augen der Aggregatoren ist dies ein Pool mit guter Tiefe und niedrigen Gebühren.

 

Gebührenstufen nach Bedarf neu konfiguriert

Prüfung 3 erwähnte 19 historische Gebührenstufen; sie stammen aus der dekompilierten Gebührenkonfigurationsfunktion (Selektor 0x4d909a45, keine öffentliche Signatur):

 

 

Vier Gebührenstufen und Schwellenwerte werden als Paket in den Speicherslot keccak(poolId, 2) geschrieben. Der On-Chain-Test liest dort 0x0138800186a00186a0, was abschnittsweise dem Packformat der Funktion entspricht. Die Gebührenstufen sind hier jederzeit anpassbare Parameter und nicht bei der Bereitstellung festgeschrieben.

 

Lebenszyklus

Der Pool wurde am 22.08. um 06:57 Uhr erstellt, der erste Swap erfolgte um 07:13 Uhr, um 21:39 Uhr die Beispieltransaktion dieses Artikels; am 23.08. um 12:25 Uhr die letzte Transaktion, danach wurde der Pool geschlossen. Die gesamte aktive Phase dauerte etwa 29 Stunden, das Gesamtvolumen betrug 14.067.857 US-Dollar, die Gebühreneinnahmen 131.888 US-Dollar (ohne Abzug der Deployer-Kosten). Bei der Überprüfung war das Registrierungsflag wieder aktiv – der Pool existiert noch und kann jederzeit reaktiviert werden.

 

05 Der vollständige Pfad

Die gesamte Angriffskette im Überblick:

 

 

Alle Kausalzusammenhänge der Kette stehen in der Grafik oben; alle drei Bedingungen sind notwendig: Die Simulation trifft die ersten beiden Ebenen, die echte Transaktion die dritte, und der Puffer ist größer als die Gebühr. Fällt eine davon weg, scheitert die Methode.

 

06 Korrekturen und Empfehlungen

Der erste Punkt betrifft die Preisangebot-Methode der Aggregatoren. Die Ursache ist, dass Simulation und Ausführung unterschiedliche Wege gehen: Preisangebote nutzen idealisierte Pool-Abfragen mit Nulladresse und hohem Gas; echte Transaktionen tragen echte Identität und bereits verbrauchtes Gas. Der Hook kann genau diese Unterschiede auslesen, wodurch die Gebühr abweicht. Die Lösung: Simulationen näher an die Ausführung bringen – mit der tatsächlich zu sendenden Router-Calldata, echten from/to-Werten und Gas nahe der On-Chain-Transaktion simulieren; nach der Ausführung das Swap-Event dekodieren und die Gebühr abgleichen; bei Abweichung vom Preisangebot herabstufen oder entfernen.

Der zweite Punkt betrifft die Slippage-Einstellungen der Nutzer. Die Ursache ist ein zu lockerer min_out: Ein Puffer von 20,32 % schluckt eine Gebühr von 12,8 % vollständig, die Transaktion läuft normal durch. Für gängige Stablecoin-Routen reichen 0,1 %–1 % im Alltag; vor dem Absenden einen Blick auf diese Zahl werfen. Wallets und Frontends sollten die Standardwerte enger setzen, um Nutzer vor den meisten Risiken zu schützen.

Der dritte Punkt betrifft die Routing-Zulassung. Die Ursache ist, dass jeder dynamische Gebührenpool direkt am Preisangebot-Wettbewerb teilnehmen kann: Hooks ohne Open Source und ohne Audit-Historie können allein durch erzeugtes Volumen in empfohlene Routen gelangen. Für dynamische Gebührenpools ohne vertrauenswürdiges Profil ist die sicherste Behandlung, sie standardmäßig nicht ins Routing aufzunehmen oder deutlich herabzustufen.

 

Daten und Anmerkungen

· Beispieltransaktion:

https://bscscan.com/tx/0x7615dec2ce80506ec461a47739eb8533ac2bc7c605ca56c255964481b76363d0 (Block 117497524)

· Pool-Initialisierungstransaktion:

https://bscscan.com/tx/0x8fa72ef72d77b61f715dc9ce90548249ab045c6d78716078cd5ab425bbe69a05

· PoolManager:

0x28e2ea090877bf75740558f6bfb36a5ffee9e9df

· Pool-ID:

0x36e5540e9dedc02229fe8a82aa5b10c0bf07d1fa74e4f2ffe0efd00fa1a36aea

· Hook:

0xd111b3ddd92e627f1864520c770e913ec04e0880 (kein Quellcode; Pseudocode unabhängig für diesen Artikel dekompiliert; Admin 0x08b03e1a5444d469f4dc954e74d3f662c94a6b13)

· Volumen und Gebühren: Alle 21.086 Swap-Events des Pools einzeln aufsummiert (eth_getLogs), WBNB zum Ausführungskurs derselben Transaktion umgerechnet; Einnahmen brutto, ohne Abzug der Deployer-Kosten

Dieser Inhalt dient nur zu Informations- und Bildungszwecken und stellt keine Investitionsberatung in Bezug auf BTCC dar. BTCC unternimmt alle Anstrengungen, kann jedoch nicht die Wahrheit, Genauigkeit oder Originalität des oben stehenden Inhalts garantieren.

Empfohlen

Ethereum (ETH) unter Druck, da Rohöl über 105 $ steigt und die Wahrscheinlichkeit einer Fed-Zinserhöhung 62 % erreichtArc-Mainnet steht bevor: Das müssen Sie wissenBitcoin-Wallet-Schlüssel entstehen aus radioaktivem ZerfallFruchtfliegen-Gehirn als Open Source: Fliegen lernen spielen und Krypto handelnEthereum peilt 6. Oktober für Glamsterdam auf Sepolia an