tl;dr, the size of uint256 - 1
(the largest uint256, and therefore the number you'd have to reach to overflow) is so large that if we design a uint that starts at 0 and has to be incremented by 1 at a time on the blockchain, you can't get there even if you write an infinite loop powered by a supernova running at maximum efficiency.
Therefore, overflow checks on a +1 incrementing uint256 value are effectively a waste of gas.
more detail:
If you look at the history of this particular unchecked block being added, this was to bring the 0.8 code in line with the 0.7 code. We can see this comment in the 0.7 version of the code, explaining why they didn't use safemath for incrementing back then:
/**
* @title Counters
* @author Matt Condon (@shrugs)
* @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number
* of elements in a mapping, issuing ERC721 ids, or counting request ids.
*
* Include with `using Counters for Counters.Counter;`
* Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}
* overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never
* directly accessed.
*/
see the old version of the file for this comment yourself: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/90ed1af972299070f51bf4665a85da56ac4d355e/contracts/utils/Counters.sol
Using an unchecked block there matches the previous code where safemath wasn't used there. Overflows on a uint256 aren't a thing, is basically it, and it's cheaper to do unchecked math.
(sadly, they removed this explanatory note, it's a reasonable question one would naturally have looking at this file.)
Why is it not possible to overflow if incrementing by one? More OZ: https://forum.openzeppelin.com/t/counters-sol-increment-does-not-need-overflow-protection/1375
It is not possible to overflow a 256 bit integer with increments of one because of the following:
Paraphrasing > https://security.stackexchange.com/a/82412: 15 overflowing 256-bit counters will be impossible until computers are built from something other than matter and occupy something other than space.
(I highly recommend clicking through to that link, btw, it's as entertaining as it is educational.)
Fixed length arrays (e.g. uint[2] memory
) and dynamic length arrays (e.g. uint[] memory
) are stored in memory differently, as the dynamic length array has to also store the length.
From the docs:
The length of a dynamic array is stored at the first slot of the array and followed by the array elements.
Due to this difference it is not possible to convert them automatically. More info is available in the Solidity docs on the internals:
Edit:
An alternative for your example would be the usage of a tuple as the return type:
function length() public view returns(uint fixedLength, uint dynamicLength) {
return (fixedArr.length, dynamicArr.length);
}
Best Answer
Looking at the documentation for Solidity 0.8.0 it doesn't seem so like the
unchecked
block inbar
disables the safety checks infoo
..https://docs.soliditylang.org/en/v0.8.0/control-structures.html#checked-or-unchecked-arithmetic