diff --git a/Changelog.md b/Changelog.md index 4b997c391..c453ace9b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ ### 0.8.5 (unreleased) Language Features: +* Allowing conversion from ``bytes`` and ``bytes`` slices to ``bytes1``/.../``bytes32``. Compiler Features: diff --git a/docs/types/conversion.rst b/docs/types/conversion.rst index 2e9e02651..38e0ca6f1 100644 --- a/docs/types/conversion.rst +++ b/docs/types/conversion.rst @@ -99,6 +99,27 @@ rules explicit:: uint8 d = uint8(uint16(a)); // d will be 0x34 uint8 e = uint8(bytes1(a)); // e will be 0x12 +``bytes`` arrays and ``bytes`` calldata slices can be converted explicitly to fixed bytes types (``bytes1``/.../``bytes32``). +In case the array is longer than the target fixed bytes type, truncation at the end will happen. +If the array is shorter than the target type, it will be padded with zeros at the end. + +:: + + // SPDX-License-Identifier: GPL-3.0 + pragma solidity ^0.8.5; + + contract C { + bytes s = "abcdefgh"; + function f(bytes calldata c, bytes memory m) public view returns (bytes16, bytes3) { + require(c.length == 16, ""); + bytes16 b = bytes16(m); // if length of m is greater than 16, truncation will happen + b = bytes16(s); // padded on the right, so result is "abcdefgh\0\0\0\0\0\0\0\0" + bytes3 b1 = bytes3(s); // truncated, b1 equals to "abc" + b = bytes16(c[:8]); // also padded with zeros + return (b, b1); + } + } + .. _types-conversion-literals: Conversions between Literals and Elementary Types diff --git a/docs/types/reference-types.rst b/docs/types/reference-types.rst index 540382083..8d21221b4 100644 --- a/docs/types/reference-types.rst +++ b/docs/types/reference-types.rst @@ -492,7 +492,7 @@ Array slices are useful to ABI-decode secondary data passed in function paramete :: // SPDX-License-Identifier: GPL-3.0 - pragma solidity >=0.7.0 <0.9.0; + pragma solidity >0.8.4 <0.9.0; contract Proxy { /// @dev Address of the client contract managed by proxy i.e., this contract address client; @@ -504,13 +504,9 @@ Array slices are useful to ABI-decode secondary data passed in function paramete /// 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); + bytes4 sig = bytes4(_payload[:4]); + // Due to truncating behaviour, bytes4(_payload) performs identically. + // bytes4 sig = bytes4(_payload); if (sig == bytes4(keccak256("setOwner(address)"))) { address owner = abi.decode(_payload[4:], (address)); require(owner != address(0), "Address of owner cannot be zero.");