solidity icon indicating copy to clipboard operation
solidity copied to clipboard

Yul identifiers inconsistently treat builtins/keywords

Open DaniPopes opened this issue 6 months ago • 1 comments

For example, yul-variable-declaration specifies one or more yul-identifiers on the left hand side; yul-identifier is a separate rule from yul-evm-builtin, so I assume in practice this means that yul-identifier excludes all evm builtins. However, yul-path (part of yul-expression) specifies only yul-identifier as the first segment.

The following code is allowed:

contract C {
    uint number;
    function f() external {
        assembly {
            // whereas declaring 'number' inside is not
            // let number := 0
            sstore(number.slot, 1)
        }
    }
}

I believe the implementation is correct, but the grammar is missing this nuance.

Encountered in Optimism: https://github.com/ethereum-optimism/optimism/blob/5229fa195415136e5589787c5850101d06b15748/packages/contracts-bedrock/src/L2/L1Block.sol#L169-L170

DaniPopes avatar May 16 '25 12:05 DaniPopes

I believe what's going on is that number and number.number are both identifiers, since . in the Yul parser is not treated specially. So the yul-path rules are not implemented in the parser. All of the following are allowed (--stop-after parsing):

contract C {
    uint number;
    function f() external {
        assembly {
            number.slot := 69
            number.slot, number.slot := some_call()

            number.number := 69
            number.number, number.number := some_call()

            sstore(number.slot, 1)

            pop(number())
        }
    }
}

DaniPopes avatar May 26 '25 22:05 DaniPopes