Is it possible to slice variables in Solidity?
1 Answer
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 int
s 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 index0
to the specifiedend
end
is excluded, the returned value will be the sliced array from the specifiedstart
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.
-
-
What is the suggested way to do access slices of memory arrays?– sloretiCommented 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