Starting from version 0.6.0, Solidity supports array slices. Array slices are handy when you want to reference a contiguous portion of an array but do not want to perform a full copy of that portion. For now, array slices are only supported for calldata arrays.

How to use Array Slices

The expression x[start:end] references a portion of the calldata array x starting at index start and ending just before index end.

Both start and end are optional. If not provided, start defaults to 0 and end defaults to the length of the respective array.

Please note that no copy from calldata to memory is performed.

You can use the slice syntax on variables, but also with msg.data.

Array slices can be especially useful in combination with abi.decode in the fallback function:

pragma solidity ^0.6.5;

interface OtherContract {
    function changeOwner(address) external;
}

contract Proxy {
    OtherContract implementation;
    address badOwner;
    fallback() external {
        if (msg.sig == OtherContract.changeOwner.selector) {
            // Here, abi.decode directly operates on the calldata array slice.
            address newOwner = abi.decode(msg.data[4:], (address));
            require(newOwner != badOwner);
        }
        (bool success,) = address(implementation).delegatecall(msg.data);
        require(success);
    }
}

How Array Slices Work Internally

Calldata arrays have always been represented by two values: A start pointer and a length value. This is exactly the same representation we use for calldata array slices.

Limitations and Future Plans

Array slices support index access and .length just like arrays, but do not support most copy operations.

As of now, array slices are only implemented for calldata.