Solidity: Constant variables in inline assemby

Created on 23 Mar 2018  路  8Comments  路  Source: ethereum/solidity

TypeError: Constant variables not supported by inline assembly.

Is there a reason for this error? You could evaluate the constant and then copy value to assembly in compile time, right?

feature language design

All 8 comments

This is a missing feature, let's see if we can support it for 0.5.0.

This might cause problems unless the constant values are known at compile time (for some, we only copy the expression). Also, it could get messy for strings and byte arrays (because inline assembly only receives the address).

compile time (for some, we only copy the expression)

Which I think is a bad idea. See #3157.

If we'd split constant into constant and constexpr, then inline assembly could support constant and if someone wants to use an expression, it must be assigned (and evaluated) to a constant first.

Ah right, splitting constants sounds like a good idea.

I would like to see this feature done. When working with custom data format it is useful to define couple of constants for the format. They can't be accessed in assembly resulting in more complicated patterns.

Following code illustrates the problem when decoding custom data format.

pragma solidity ^0.5.0;
contract Example {

    uint256 constant sizeWord = 32; // byte size of number
    uint256 constant sizeUint256 = sizeWord; // byte size of number
    uint256 constant sizeAddress = 20; // byte size of address
    uint256 constant sizeBytesLength = sizeWord; // byte size of encoded `length` of `bytes`

    function decodeMyFormat(bytes memory serializedCommand) public pure returns (address from, address to, uint256 amount) {
        uint256 diffAddress = sizeWord - sizeAddress;
        uint256 shiftFrom = sizeBytesLength - diffAddress;
        uint256 shiftTo = sizeBytesLength + sizeAddress - diffAddress;
        uint256 shiftAmount = sizeBytesLength + sizeAddress - diffAddress + sizeWord;
        assembly {
            from := mload(add(serializedCommand, shiftFrom))
            to := mload(add(serializedCommand, shiftTo))
            amount := mload(add(serializedCommand, shiftAmount))
        }
    }

    /*
    function decodeMyFormat(bytes memory serializedCommand) public pure returns (address from, address to, uint256 amount) {

        // this throws Solidity error "Constant variables not supported by inline assembly"
        assembly {
            assembly {
            let start := add(serializedCommand, sizeBytesLength)
            let tmp := sub(start, sub(sizeWord, sizeAddress))

            from := mload(tmp)
            tmp := add(tmp, sizeAddress)

            to := mload(tmp)
            tmp := add(tmp, sizeAddress)

            amount := mload(tmp)
        }
    }
    */
}

Assume input for decodeMyFormat is


then result is tuple

0xca35b7d915458ef540ade6068dfe2f44e8fa733c
0000000000000000000000000000000000000000000000000000000000000010

We might be able to at least support a subset.

Only implemented a subset for now.

What does not yet work from the above is uint256 constant sizeUint256 = sizeWord;, i.e. referencing another constant. What does work, though are simple pure constant expressions like 2**20.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

chriseth picture chriseth  路  3Comments

walter-weinmann picture walter-weinmann  路  4Comments

chriseth picture chriseth  路  3Comments

chriseth picture chriseth  路  3Comments

chriseth picture chriseth  路  3Comments