[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-deep-evm-11-huff-sprungtabellen-funktionsdispatch":3},{"article":4,"author":59},{"id":5,"category_id":6,"title":7,"slug":8,"excerpt":9,"content_md":10,"content_html":11,"locale":12,"author_id":13,"published":14,"published_at":15,"meta_title":16,"meta_description":17,"focus_keyword":18,"og_image":19,"canonical_url":19,"robots_meta":20,"created_at":15,"updated_at":15,"tags":21,"category_name":39,"related_articles":40},"d7000000-0000-0000-0000-000000000111","a0000000-0000-0000-0000-000000000072","Deep EVM #11: Huff-Sprungtabellen — O(1)-Funktionsdispatch ohne Solidity-Overhead","deep-evm-11-huff-sprungtabellen-funktionsdispatch","Einen O(1)-Funktionsdispatcher in Huff mit gepackten Sprungtabellen bauen. Soliditys if-else-Kette mit einer handgefertigten Sprungtabelle vergleichen, die Tausende Gas spart.","## Soliditys linearer Dispatch ist O(N)\n\nWenn Sie einen Solidity-Contract aufrufen, fuehrt die EVM als Erstes den Funktionsdispatcher aus — eine lineare if-else-Kette, die den Calldata-Selektor mit jeder bekannten Funktion vergleicht. Fuer einen Contract mit N Funktionen ist das O(N). Eine Sprungtabelle ersetzt das durch O(1) berechnete Spruenge und spart Tausende Gas ueber Millionen von Aufrufen.\n\n## Wie funktioniert eine Sprungtabelle?\n\nEine Sprungtabelle ist ein Array von Sprungadressen. Statt jeden Selektor einzeln zu vergleichen, berechnen Sie einen Index aus dem Selektor und springen direkt zur entsprechenden Adresse:\n\n```\n\u002F\u002F Linearer Dispatch (O(N)):\n\u002F\u002F if selector == 0xa9059cbb: jump to transfer\n\u002F\u002F if selector == 0x70a08231: jump to balanceOf\n\u002F\u002F if selector == 0x095ea7b3: jump to approve\n\u002F\u002F ... N Vergleiche\n\n\u002F\u002F Sprungtabelle (O(1)):\n\u002F\u002F index = hash(selector) % table_size\n\u002F\u002F jump to table[index]\n```\n\n## Sprungtabelle in Huff implementieren\n\n```huff\n\u002F\u002F Sprungtabelle mit 4 Eintraegen\n#define jumptable DISPATCH_TABLE {\n    transfer_entry    \u002F\u002F Index 0\n    balanceOf_entry   \u002F\u002F Index 1\n    approve_entry     \u002F\u002F Index 2\n    totalSupply_entry \u002F\u002F Index 3\n}\n\n#define macro MAIN() = takes(0) returns(0) {\n    \u002F\u002F Selektor aus Calldata laden\n    0x00 calldataload 0xe0 shr  \u002F\u002F [selector]\n    \n    \u002F\u002F Index berechnen (Selektor mod Tabellengroesse)\n    0x04 mod                     \u002F\u002F [index]\n    \n    \u002F\u002F Sprungadresse aus Tabelle laden\n    0x02 mul                     \u002F\u002F [byte_offset] (2 Bytes pro Eintrag)\n    __tablestart(DISPATCH_TABLE) add  \u002F\u002F [table_addr + offset]\n    \n    \u002F\u002F Adresse laden und springen\n    0x00 0x00 codecopy           \u002F\u002F Adresse in Memory kopieren\n    0x00 mload shr(240)          \u002F\u002F Obere 2 Bytes extrahieren\n    jump                         \u002F\u002F Springen!\n}\n```\n\n## Gasvergleich\n\n| Funktionen | Solidity (if-else) | Huff (Sprungtabelle) | Ersparnis |\n|------------|-------------------|---------------------|----------|\n| 5 | ~200 Gas | ~80 Gas | 60% |\n| 10 | ~400 Gas | ~80 Gas | 80% |\n| 20 | ~800 Gas | ~80 Gas | 90% |\n| 50 | ~2.000 Gas | ~80 Gas | 96% |\n\nDie Sprungtabelle hat konstante Kosten unabhaengig von der Anzahl der Funktionen. Bei MEV-Bots mit 50+ Funktionen spart das erheblich.\n\n## Kollisionsbehandlung\n\nWenn zwei Selektoren denselben Index berechnen (Kollision), benoetigen Sie eine Fallback-Strategie:\n\n1. **Perfekte Hash-Funktion** — Waehlen Sie eine Tabellengroesse und Modulo-Operation, die keine Kollisionen erzeugt\n2. **Vanity-Selektoren** — Waehlen Sie Funktionsnamen, deren Selektoren keine Kollisionen erzeugen\n3. **Sekundaerer Vergleich** — Bei Kollision den vollen Selektor vergleichen\n\n### Vanity-Selektor-Mining\nSie koennen Funktionsnamen so waehlen, dass ihre Selektoren perfekt in Ihre Sprungtabelle passen:\n\n```python\nimport hashlib\n\ndef selector(name):\n    return hashlib.sha3_256(name.encode()).hexdigest()[:8]\n\n# Verschiedene Suffixe durchprobieren:\n# transfer_v1(address,uint256) -> 0x...\n# transfer_v2(address,uint256) -> 0x...\n# Bis der Selektor mod table_size den gewuenschten Index ergibt\n```\n\n## Gepackte vs. Nicht-gepackte Tabellen\n\n### Nicht-gepackt (32 Bytes pro Eintrag)\nEinfacher zu implementieren, aber verschwendet Memory:\n```huff\n#define jumptable__packed PACKED_TABLE {\n    entry1 entry2 entry3 entry4\n}\n```\n\n### Gepackt (2 Bytes pro Eintrag)\nKompakter, da Sprungadressen in Smart Contracts selten 65.535 ueberschreiten:\n```huff\n#define jumptable__packed PACKED_TABLE {\n    entry1 entry2 entry3 entry4\n}\n```\n\nDie gepackte Variante spart ~30 Bytes pro Eintrag im Bytecode — bei 50 Funktionen sind das 1.500 Bytes weniger Bereitstellungskosten.\n\n## Produktionsbeispiel\n\nEin typischer MEV-Bot-Dispatcher mit Sprungtabelle:\n\n```huff\n#define macro MAIN() = takes(0) returns(0) {\n    \u002F\u002F Keine Calldata = receive()\n    calldatasize iszero receive_eth jumpi\n    \n    \u002F\u002F Selektor laden\n    0x00 calldataload 0xe0 shr\n    \n    \u002F\u002F 8-Eintrag-Tabelle (8 = 2^3, effizientes Modulo mit AND)\n    0x07 and  \u002F\u002F index = selector & 7\n    \n    \u002F\u002F Jeder Eintrag ist 2 Bytes\n    0x02 mul\n    __tablestart(DISPATCH) add\n    \n    codecopy_and_jump:\n        \u002F\u002F Sprungadresse laden und springen\n        0x1e byte\n        jump\n    \n    receive_eth:\n        stop\n}\n```\n\n## Fazit\n\nSprungtabellen sind die effizienteste Methode fuer Funktionsdispatch in der EVM. Fuer Contracts mit vielen Funktionen — insbesondere MEV-Bots — ist die O(1)-Lookup-Zeit ein erheblicher Vorteil gegenueber Soliditys linearem Dispatch. Die Implementierung erfordert sorgfaeltige Planung der Tabellengroesse und Kollisionsvermeidung, aber der Gasgewinn ist es wert.","\u003Ch2 id=\"soliditys-linearer-dispatch-ist-o-n\">Soliditys linearer Dispatch ist O(N)\u003C\u002Fh2>\n\u003Cp>Wenn Sie einen Solidity-Contract aufrufen, fuehrt die EVM als Erstes den Funktionsdispatcher aus — eine lineare if-else-Kette, die den Calldata-Selektor mit jeder bekannten Funktion vergleicht. Fuer einen Contract mit N Funktionen ist das O(N). Eine Sprungtabelle ersetzt das durch O(1) berechnete Spruenge und spart Tausende Gas ueber Millionen von Aufrufen.\u003C\u002Fp>\n\u003Ch2 id=\"wie-funktioniert-eine-sprungtabelle\">Wie funktioniert eine Sprungtabelle?\u003C\u002Fh2>\n\u003Cp>Eine Sprungtabelle ist ein Array von Sprungadressen. Statt jeden Selektor einzeln zu vergleichen, berechnen Sie einen Index aus dem Selektor und springen direkt zur entsprechenden Adresse:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>\u002F\u002F Linearer Dispatch (O(N)):\n\u002F\u002F if selector == 0xa9059cbb: jump to transfer\n\u002F\u002F if selector == 0x70a08231: jump to balanceOf\n\u002F\u002F if selector == 0x095ea7b3: jump to approve\n\u002F\u002F ... N Vergleiche\n\n\u002F\u002F Sprungtabelle (O(1)):\n\u002F\u002F index = hash(selector) % table_size\n\u002F\u002F jump to table[index]\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"sprungtabelle-in-huff-implementieren\">Sprungtabelle in Huff implementieren\u003C\u002Fh2>\n\u003Cpre>\u003Ccode class=\"language-huff\">\u002F\u002F Sprungtabelle mit 4 Eintraegen\n#define jumptable DISPATCH_TABLE {\n    transfer_entry    \u002F\u002F Index 0\n    balanceOf_entry   \u002F\u002F Index 1\n    approve_entry     \u002F\u002F Index 2\n    totalSupply_entry \u002F\u002F Index 3\n}\n\n#define macro MAIN() = takes(0) returns(0) {\n    \u002F\u002F Selektor aus Calldata laden\n    0x00 calldataload 0xe0 shr  \u002F\u002F [selector]\n    \n    \u002F\u002F Index berechnen (Selektor mod Tabellengroesse)\n    0x04 mod                     \u002F\u002F [index]\n    \n    \u002F\u002F Sprungadresse aus Tabelle laden\n    0x02 mul                     \u002F\u002F [byte_offset] (2 Bytes pro Eintrag)\n    __tablestart(DISPATCH_TABLE) add  \u002F\u002F [table_addr + offset]\n    \n    \u002F\u002F Adresse laden und springen\n    0x00 0x00 codecopy           \u002F\u002F Adresse in Memory kopieren\n    0x00 mload shr(240)          \u002F\u002F Obere 2 Bytes extrahieren\n    jump                         \u002F\u002F Springen!\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"gasvergleich\">Gasvergleich\u003C\u002Fh2>\n\u003Ctable>\u003Cthead>\u003Ctr>\u003Cth>Funktionen\u003C\u002Fth>\u003Cth>Solidity (if-else)\u003C\u002Fth>\u003Cth>Huff (Sprungtabelle)\u003C\u002Fth>\u003Cth>Ersparnis\u003C\u002Fth>\u003C\u002Ftr>\u003C\u002Fthead>\u003Ctbody>\n\u003Ctr>\u003Ctd>5\u003C\u002Ftd>\u003Ctd>~200 Gas\u003C\u002Ftd>\u003Ctd>~80 Gas\u003C\u002Ftd>\u003Ctd>60%\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>10\u003C\u002Ftd>\u003Ctd>~400 Gas\u003C\u002Ftd>\u003Ctd>~80 Gas\u003C\u002Ftd>\u003Ctd>80%\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>20\u003C\u002Ftd>\u003Ctd>~800 Gas\u003C\u002Ftd>\u003Ctd>~80 Gas\u003C\u002Ftd>\u003Ctd>90%\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>50\u003C\u002Ftd>\u003Ctd>~2.000 Gas\u003C\u002Ftd>\u003Ctd>~80 Gas\u003C\u002Ftd>\u003Ctd>96%\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\n\u003Cp>Die Sprungtabelle hat konstante Kosten unabhaengig von der Anzahl der Funktionen. Bei MEV-Bots mit 50+ Funktionen spart das erheblich.\u003C\u002Fp>\n\u003Ch2 id=\"kollisionsbehandlung\">Kollisionsbehandlung\u003C\u002Fh2>\n\u003Cp>Wenn zwei Selektoren denselben Index berechnen (Kollision), benoetigen Sie eine Fallback-Strategie:\u003C\u002Fp>\n\u003Col>\n\u003Cli>\u003Cstrong>Perfekte Hash-Funktion\u003C\u002Fstrong> — Waehlen Sie eine Tabellengroesse und Modulo-Operation, die keine Kollisionen erzeugt\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Vanity-Selektoren\u003C\u002Fstrong> — Waehlen Sie Funktionsnamen, deren Selektoren keine Kollisionen erzeugen\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Sekundaerer Vergleich\u003C\u002Fstrong> — Bei Kollision den vollen Selektor vergleichen\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch3>Vanity-Selektor-Mining\u003C\u002Fh3>\n\u003Cp>Sie koennen Funktionsnamen so waehlen, dass ihre Selektoren perfekt in Ihre Sprungtabelle passen:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-python\">import hashlib\n\ndef selector(name):\n    return hashlib.sha3_256(name.encode()).hexdigest()[:8]\n\n# Verschiedene Suffixe durchprobieren:\n# transfer_v1(address,uint256) -&gt; 0x...\n# transfer_v2(address,uint256) -&gt; 0x...\n# Bis der Selektor mod table_size den gewuenschten Index ergibt\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"gepackte-vs-nicht-gepackte-tabellen\">Gepackte vs. Nicht-gepackte Tabellen\u003C\u002Fh2>\n\u003Ch3>Nicht-gepackt (32 Bytes pro Eintrag)\u003C\u002Fh3>\n\u003Cp>Einfacher zu implementieren, aber verschwendet Memory:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-huff\">#define jumptable__packed PACKED_TABLE {\n    entry1 entry2 entry3 entry4\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>Gepackt (2 Bytes pro Eintrag)\u003C\u002Fh3>\n\u003Cp>Kompakter, da Sprungadressen in Smart Contracts selten 65.535 ueberschreiten:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-huff\">#define jumptable__packed PACKED_TABLE {\n    entry1 entry2 entry3 entry4\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Die gepackte Variante spart ~30 Bytes pro Eintrag im Bytecode — bei 50 Funktionen sind das 1.500 Bytes weniger Bereitstellungskosten.\u003C\u002Fp>\n\u003Ch2 id=\"produktionsbeispiel\">Produktionsbeispiel\u003C\u002Fh2>\n\u003Cp>Ein typischer MEV-Bot-Dispatcher mit Sprungtabelle:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-huff\">#define macro MAIN() = takes(0) returns(0) {\n    \u002F\u002F Keine Calldata = receive()\n    calldatasize iszero receive_eth jumpi\n    \n    \u002F\u002F Selektor laden\n    0x00 calldataload 0xe0 shr\n    \n    \u002F\u002F 8-Eintrag-Tabelle (8 = 2^3, effizientes Modulo mit AND)\n    0x07 and  \u002F\u002F index = selector &amp; 7\n    \n    \u002F\u002F Jeder Eintrag ist 2 Bytes\n    0x02 mul\n    __tablestart(DISPATCH) add\n    \n    codecopy_and_jump:\n        \u002F\u002F Sprungadresse laden und springen\n        0x1e byte\n        jump\n    \n    receive_eth:\n        stop\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"fazit\">Fazit\u003C\u002Fh2>\n\u003Cp>Sprungtabellen sind die effizienteste Methode fuer Funktionsdispatch in der EVM. Fuer Contracts mit vielen Funktionen — insbesondere MEV-Bots — ist die O(1)-Lookup-Zeit ein erheblicher Vorteil gegenueber Soliditys linearem Dispatch. Die Implementierung erfordert sorgfaeltige Planung der Tabellengroesse und Kollisionsvermeidung, aber der Gasgewinn ist es wert.\u003C\u002Fp>\n","de","b0000000-0000-0000-0000-000000000001",true,"2026-03-28T10:44:30.140519Z","Deep EVM #11: Huff-Sprungtabellen — O(1)-Funktionsdispatch","O(1)-Funktionsdispatcher in Huff mit gepackten Sprungtabellen bauen. Gaskosten mit Solidity-Dispatch vergleichen und Vanity-Selektor-Mining lernen.","Huff Sprungtabelle Funktionsdispatch",null,"index, follow",[22,27,31,35],{"id":23,"name":24,"slug":25,"created_at":26},"c0000000-0000-0000-0000-000000000016","EVM","evm","2026-03-28T10:44:21.513630Z",{"id":28,"name":29,"slug":30,"created_at":26},"c0000000-0000-0000-0000-000000000020","Gas Optimization","gas-optimization",{"id":32,"name":33,"slug":34,"created_at":26},"c0000000-0000-0000-0000-000000000017","Huff","huff",{"id":36,"name":37,"slug":38,"created_at":26},"c0000000-0000-0000-0000-000000000018","Yul","yul","Blockchain",[41,47,53],{"id":42,"title":43,"slug":44,"excerpt":45,"locale":12,"category_name":39,"published_at":46},"d0000000-0000-0000-0000-000000000611","Die Ethereum-Interoperabilitaetsschicht: Wie 55+ L2s zu einer Chain werden","ethereum-interoperabilitaetsschicht-55-l2s-eine-chain","Ethereum hat 55+ Layer-2-Rollups, die Liquiditaet und Nutzererfahrung fragmentieren. Die Ethereum-Interoperabilitaetsschicht — bestehend aus Cross-Rollup-Messaging, Shared Sequencern und Based Rollups — zielt darauf ab, sie zu einem einzigen komponierbaren Netzwerk zu vereinen.","2026-03-28T10:44:45.264352Z",{"id":48,"title":49,"slug":50,"excerpt":51,"locale":12,"category_name":39,"published_at":52},"d0000000-0000-0000-0000-000000000610","ZK-Beweise jenseits von Rollups: Verifizierbare KI-Inferenz auf Ethereum","zk-beweise-jenseits-von-rollups-verifizierbare-ki-inferenz-ethereum","Zero-Knowledge-Beweise sind nicht mehr nur ein Skalierungswerkzeug. Im Jahr 2026 ermoeglicht zkML verifizierbare KI-Inferenz on-chain, ZK-Coprozessoren verlagern schwere Berechnungen off-chain mit On-Chain-Verifizierung, und neue Beweissysteme wie SP1 und Jolt machen es praktikabel.","2026-03-28T10:44:45.257775Z",{"id":54,"title":55,"slug":56,"excerpt":57,"locale":12,"category_name":39,"published_at":58},"d0000000-0000-0000-0000-000000000587","EIP-7702 in der Praxis: Smart-Account-Flows nach Pectra erstellen","eip-7702-in-der-praxis-smart-account-flows-nach-pectra-erstellen","EIP-7702 ermoeglicht jedem Ethereum-EOA, innerhalb einer einzelnen Transaktion voruebergehend als Smart Contract zu agieren. So implementieren Sie Batch-Transaktionen, Gas-Sponsoring und Social Recovery mit dem neuen Account-Abstraction-Primitiv.","2026-03-28T10:44:43.781201Z",{"id":13,"name":60,"slug":61,"bio":62,"photo_url":19,"linkedin":19,"role":63,"created_at":64,"updated_at":64},"Open Soft Team","open-soft-team","The engineering team at Open Soft, building premium software solutions from Bali, Indonesia.","Engineering Team","2026-03-28T08:31:22.226811Z"]