13

Is it possible to slice variables in Solidity?

0

1 Answer 1

24

Solidity 0.6.0 and Greater (Updated 2020)

As of Solidity 0.6.0, there is array slice functionality built into Solidity. The syntax is similar to existing languages in that the array takes the following parameters x[start:end]. Here, start and end are ints that represent the starting and ending index to be sliced.

If start is greater than end or if end is greater than the length of the array, an exception is thrown.

As a note, either start or end (or both) can be excluded from the code. start defaults to 0 and end defaults to the length of the array. In the case where:

  • start is excluded, the returned value will be the sliced array from index 0 to the specified end
  • end is excluded, the returned value will be the sliced array from the specified start index to the end of the array
  • both are omitted, the returned array will be identical to input array

Examples

Simplified Example

bytes exampleBytes = '0xabcd'

exampleBytes[2:5];  # 'abc'
exampleBytes[:5];   # '0xabc'
exampleBytes[2:];   # 'abcd'
exampleBytes[:];    # '0xabcd'

Full Example (From Solidity Docs)

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.7.0;

contract Proxy {
    /// @dev Address of the client contract managed by proxy i.e., this contract
    address client;

    constructor(address _client) public {
        client = _client;
    }

    /// Forward call to "setOwner(address)" that is implemented by client
    /// after doing basic validation on the address argument.
    function forward(bytes calldata _payload) external {
        // Since ABI decoding requires padded data, we cannot
        // use abi.decode(_payload[:4], (bytes4)).
        bytes4 sig =
            _payload[0] |
            (bytes4(_payload[1]) >> 8) |
            (bytes4(_payload[2]) >> 16) |
            (bytes4(_payload[3]) >> 24);
        if (sig == bytes4(keccak256("setOwner(address)"))) {
            address owner = abi.decode(_payload[4:], (address));
            require(owner != address(0), "Address of owner cannot be zero.");
        }
        (bool status,) = client.delegatecall(_payload);
        require(status, "Forwarded call failed.");
    }
}

Note: As of Solidity 0.6.0, array slices are only implemented for calldata arrays.



Solidity < 0.6.0

For Solidity versions prior to 0.6.0, there was no slice functionality built into the language. There are, however, ways to perform similar functionality given the available language features at the time.

To slice a string, you can perform the following (from this answer):

pragma solidity 0.4.24;

contract test{

    function getSlice(uint256 begin, uint256 end, string text) public pure returns (string) {
        bytes memory a = new bytes(end-begin+1);
        for(uint i=0;i<=end-begin;i++){
            a[i] = bytes(text)[i+begin-1];
        }
        return string(a);    
    }
}

You can also use the stringutils library by Arachnid (Nick Johnson) to achieve the same goals.

3
  • What will be its gas cost? @shane
    – alper
    Commented Jan 8, 2020 at 22:00
  • What is the suggested way to do access slices of memory arrays?
    – sloreti
    Commented Nov 20, 2020 at 3:58
  • What if I wanted to slice [-3:-1]? Since such values get refused. Commented Jan 6, 2022 at 18:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.