Ir al contenido principal
BlockchainMar 28, 2026

Deep EVM #5: Einfuehrung in Yul — Soliditys geheime Assemblersprache

OS
Open Soft Team

Engineering Team

Was ist Yul?

Yul ist eine Zwischensprache, die vom Solidity-Team entwickelt wurde und zu EVM-Bytecode kompiliert. Sie liegt zwischen Solidity und rohen Opcodes: Sie erhalten direkten Zugriff auf jeden EVM-Opcode ueber eine lesbare, strukturierte Syntax mit Variablen, Funktionen und Kontrollflusskonstrukten.

Warum Yul verwenden?

  • Gasoptimierung — Soliditys Compiler fuegt Sicherheitspruefungen und Overhead hinzu. In Yul kontrollieren Sie jede Gasausgabe.
  • Direkter Opcode-Zugriff — Opcodes wie MSTORE, SLOAD, CALLDATACOPY sind direkt ansprechbar.
  • Feingranulare Kontrolle — Memory-Layout, Storage-Zugriffsmuster und Aufrufkonventionen liegen vollstaendig in Ihrer Hand.

Yul-Syntax-Grundlagen

Yul verwendet eine einfache, blockorientierte Syntax:

// Variablen deklarieren
let x := 42
let y := add(x, 1)  // y = 43

// Funktionen definieren
function double(val) -> result {
    result := mul(val, 2)
}

// Kontrollfluss
if gt(x, 10) {
    // x > 10
}

for { let i := 0 } lt(i, 10) { i := add(i, 1) } {
    // Schleife 0..9
}

switch x
case 0 { /* x == 0 */ }
case 1 { /* x == 1 */ }
default { /* sonst */ }

Alle arithmetischen Operationen sind EVM-Opcodes: add, sub, mul, div, mod, exp. Vergleiche: lt, gt, eq, iszero. Bitweise: and, or, xor, not, shl, shr.

Inline-Assembly in Solidity

Der haeufigste Einsatz von Yul ist als Inline-Assembly in Solidity-Funktionen:

function getStorageAt(uint256 slot) external view returns (uint256 value) {
    assembly {
        value := sload(slot)
    }
}

function efficientTransfer(address to, uint256 amount) external {
    assembly {
        // ERC-20 Transfer-Event emittieren ohne Soliditys Overhead
        let ptr := mload(0x40)  // Free Memory Pointer
        mstore(ptr, amount)
        log3(
            ptr,
            32,
            0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, // Transfer(address,address,uint256) topic
            caller(),
            to
        )
    }
}

Wann Yul verwenden?

Ja:

  • Hot Paths mit vielen Ausfuehrungen (DEX-Router, MEV-Bots)
  • Kryptographische Operationen (Hashing, Signaturverifikation)
  • Benutzerdefinierte Memory-Layouts fuer komplexe Datenstrukturen
  • Wenn Sie Soliditys Overhead fuer Bounds-Checking umgehen muessen

Nein:

  • Standard-Geschaeftslogik (Soliditys Sicherheitspruefungen sind wertvoll)
  • Wenn Auditierbarkeit wichtiger ist als Gasersparnis
  • Wenn das Team keine EVM-Erfahrung hat

Praktisches Beispiel: Storage-Slot-Lesevorgang

function readPackedSlot(uint256 slot) external view returns (
    uint128 valueA,
    uint128 valueB
) {
    assembly {
        let packed := sload(slot)
        valueA := and(packed, 0xffffffffffffffffffffffffffffffff) // Untere 128 Bit
        valueB := shr(128, packed) // Obere 128 Bit
    }
}

Diese Funktion liest einen einzelnen Storage-Slot und extrahiert zwei gepackte uint128-Werte in einem einzigen SLOAD — halb so teuer wie zwei separate Lesevorgaenge.

Sicherheitsueberlegungen

Yul umgeht Soliditys Sicherheitsnetz:

  • Kein Overflow-Schutz — Sie muessen Ueberlaeufe selbst pruefen
  • Kein Bounds-Checking — Array-Zugriffe werden nicht validiert
  • Kein Typ-System — Alles ist ein 256-Bit-Wort
  • Memory-Korruption — Fehlerhaftes Memory-Management kann Daten ueberschreiben

Jede Zeile Yul-Code erfordert sorgfaeltige Pruefung und umfassende Tests.

Fazit

Yul ist ein maaechtiges Werkzeug im Arsenal des Smart-Contract-Entwicklers. Es bietet direkten Zugriff auf die EVM und ermoeglicht Optimierungen, die in reinem Solidity nicht moeglich sind. Aber mit grosser Macht kommt grosse Verantwortung — Yul-Code erfordert tiefes EVM-Verstaendnis und gruendliche Tests. In den naechsten Artikeln werden wir Yul fuer konkrete Anwendungsfaelle einsetzen: Memory-Management, gaseffiziente Schleifen und schliesslich einen vollstaendigen Token-Swap in reinem Yul.