Yul / inline assembly
Yul and inline assembly are a trapdoor beneath Solidity that let you write something very close to raw EVM opcodes. You drop into an assembly block when you need control or gas savings that the high-level language will not give you — forwarding a delegatecall in a proxy, doing tight low-level math, or reaching an opcode Solidity does not expose.
Yul is a low-level intermediate language with a small, readable syntax; inline assembly embeds Yul inside a Solidity function via an assembly { } block. It exposes opcodes almost directly: mload and mstore for memory, sload and sstore for storage, call/delegatecall/staticcall for cross-contract calls, calldatacopy and returndatacopy for data movement, create2 for deterministic deployment, and so on. You also manage memory by hand, respecting the free-memory pointer stored at address 0x40. This is exactly the layer at which proxies forward calls and libraries squeeze out gas.
The danger is that assembly bypasses Solidity's guardrails entirely: no overflow checks, no array-bounds checks, no type safety. A single wrong offset can silently overwrite memory or write to the wrong storage slot, corrupting state with no error. The compiler also reasons less about optimized and warned-about behaviour inside an assembly block. The discipline is to keep assembly minimal, heavily commented, and ideally copied from audited sources (OpenZeppelin, Solady) rather than hand-rolled — the gas you save is rarely worth a memory-corruption bug.
assembly {
let ptr := mload(0x40) // free memory pointer
mstore(ptr, sload(slot)) // raw storage read into memory
// no bounds, no overflow checks: you are on your own
}Maximum control, zero guardrails.
Inside assembly there are no safety nets. The compiler trusts you completely, so a mistyped memory offset or storage slot does not error — it silently corrupts. Use it sparingly and audit it hard.