Is it possible to slice variables in Solidity?
1 Answers
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:
startis excluded, the returned value will be the sliced array from index0to the specifiedendendis excluded, the returned value will be the sliced array from the specifiedstartindex 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.
- 18,036
- 20
- 54
- 82
-
What will be its gas cost? @shane – alper Jan 08 '20 at 22:00
-
What is the suggested way to do access slices of memory arrays? – sloreti Nov 20 '20 at 03:58
-
What if I wanted to slice [-3:-1]? Since such values get refused. – questionto42 Jan 06 '22 at 18:39