From 7f5b1b3f1f84ac85eb11c46bdbf372322d17529d Mon Sep 17 00:00:00 2001 From: CodeSandwich Date: Mon, 5 Feb 2024 23:11:42 +0100 Subject: [PATCH 1/9] Make Math.log2 branchless --- .changeset/nervous-pans-grow.md | 5 +++ contracts/utils/math/Math.sol | 67 ++++++++++++++++++++------------- 2 files changed, 46 insertions(+), 26 deletions(-) create mode 100644 .changeset/nervous-pans-grow.md diff --git a/.changeset/nervous-pans-grow.md b/.changeset/nervous-pans-grow.md new file mode 100644 index 00000000000..c535fa3a52a --- /dev/null +++ b/.changeset/nervous-pans-grow.md @@ -0,0 +1,5 @@ +--- +'openzeppelin-solidity': patch +--- + +Make Math.log2 branchless diff --git a/contracts/utils/math/Math.sol b/contracts/utils/math/Math.sol index c2d419eb92c..46d1db6f61f 100644 --- a/contracts/utils/math/Math.sol +++ b/contracts/utils/math/Math.sol @@ -391,42 +391,57 @@ library Math { * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ - function log2(uint256 value) internal pure returns (uint256) { - uint256 result = 0; + function log2(uint256 value) internal pure returns (uint256 result) { unchecked { - if (value >> 128 > 0) { - value >>= 128; - result += 128; + uint256 isGt; + + assembly { + isGt := gt(value, 0xffffffffffffffffffffffffffffffff) } - if (value >> 64 > 0) { - value >>= 64; - result += 64; + value >>= isGt * 128; + result += isGt * 128; + + assembly { + isGt := gt(value, 0xffffffffffffffff) } - if (value >> 32 > 0) { - value >>= 32; - result += 32; + value >>= isGt * 64; + result += isGt * 64; + + assembly { + isGt := gt(value, 0xffffffff) } - if (value >> 16 > 0) { - value >>= 16; - result += 16; + value >>= isGt * 32; + result += isGt * 32; + + assembly { + isGt := gt(value, 0xffff) } - if (value >> 8 > 0) { - value >>= 8; - result += 8; + value >>= isGt * 16; + result += isGt * 16; + + assembly { + isGt := gt(value, 0xff) } - if (value >> 4 > 0) { - value >>= 4; - result += 4; + value >>= isGt * 8; + result += isGt * 8; + + assembly { + isGt := gt(value, 0xf) } - if (value >> 2 > 0) { - value >>= 2; - result += 2; + value >>= isGt * 4; + result += isGt * 4; + + assembly { + isGt := gt(value, 0x3) } - if (value >> 1 > 0) { - result += 1; + value >>= isGt * 2; + result += isGt * 2; + + assembly { + isGt := gt(value, 0x1) } + result += isGt; } - return result; } /** From 752399528f586c85373acc815ae6768373ac5b8a Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Tue, 6 Feb 2024 18:27:49 +0100 Subject: [PATCH 2/9] add Math.boolToUint --- contracts/utils/math/Math.sol | 87 +++++++++++++++++------------------ test/utils/math/Math.test.js | 10 ++++ 2 files changed, 51 insertions(+), 46 deletions(-) diff --git a/contracts/utils/math/Math.sol b/contracts/utils/math/Math.sol index 46d1db6f61f..371b21bebb1 100644 --- a/contracts/utils/math/Math.sol +++ b/contracts/utils/math/Math.sol @@ -391,57 +391,42 @@ library Math { * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ - function log2(uint256 value) internal pure returns (uint256 result) { + function log2(uint256 value) internal pure returns (uint256) { + uint256 result = 0; + uint256 isGt; unchecked { - uint256 isGt; - - assembly { - isGt := gt(value, 0xffffffffffffffffffffffffffffffff) - } + isGt = boolToUint(value > 0xffffffffffffffffffffffffffffffff); value >>= isGt * 128; result += isGt * 128; - assembly { - isGt := gt(value, 0xffffffffffffffff) - } + isGt = boolToUint(value > 0xffffffffffffffff); value >>= isGt * 64; result += isGt * 64; - assembly { - isGt := gt(value, 0xffffffff) - } + isGt = boolToUint(value > 0xffffffff); value >>= isGt * 32; result += isGt * 32; - assembly { - isGt := gt(value, 0xffff) - } + isGt = boolToUint(value > 0xffff); value >>= isGt * 16; result += isGt * 16; - assembly { - isGt := gt(value, 0xff) - } + isGt = boolToUint(value > 0xff); value >>= isGt * 8; result += isGt * 8; - assembly { - isGt := gt(value, 0xf) - } + isGt = boolToUint(value > 0xf); value >>= isGt * 4; result += isGt * 4; - assembly { - isGt := gt(value, 0x3) - } + isGt = boolToUint(value > 0x3); value >>= isGt * 2; result += isGt * 2; - assembly { - isGt := gt(value, 0x1) - } + isGt = boolToUint(value > 0x1); result += isGt; } + return result; } /** @@ -512,26 +497,26 @@ library Math { */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; + uint256 isGt; unchecked { - if (value >> 128 > 0) { - value >>= 128; - result += 16; - } - if (value >> 64 > 0) { - value >>= 64; - result += 8; - } - if (value >> 32 > 0) { - value >>= 32; - result += 4; - } - if (value >> 16 > 0) { - value >>= 16; - result += 2; - } - if (value >> 8 > 0) { - result += 1; - } + isGt = boolToUint(value > 0xffffffffffffffffffffffffffffffff); + value >>= isGt * 128; + result += isGt * 16; + + isGt = boolToUint(value > 0xffffffffffffffff); + value >>= isGt * 64; + result += isGt * 8; + + isGt = boolToUint(value > 0xffffffff); + value >>= isGt * 32; + result += isGt * 4; + + isGt = boolToUint(value > 0xffff); + value >>= isGt * 16; + result += isGt * 2; + + isGt = boolToUint(value > 0xff); + result += isGt; } return result; } @@ -553,4 +538,14 @@ library Math { function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } + + /** + * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump. + */ + function boolToUint(bool b) internal pure returns (uint256 u) { + /// @solidity memory-safe-assembly + assembly { + u := b + } + } } diff --git a/test/utils/math/Math.test.js b/test/utils/math/Math.test.js index 2762fcc5732..bb565e8ae98 100644 --- a/test/utils/math/Math.test.js +++ b/test/utils/math/Math.test.js @@ -512,4 +512,14 @@ describe('Math', function () { }); }); }); + + describe('boolToUint', function () { + it('boolToUint(false) should be 0', async function () { + expect(await this.mock.$boolToUint(false)).to.equal(0n); + }); + + it('boolToUint(true) should be 1', async function () { + expect(await this.mock.$boolToUint(true)).to.equal(1n); + }); + }); }); From 45bbe87e054fec4348143775c18a2552c4baef8d Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Tue, 6 Feb 2024 18:33:16 +0100 Subject: [PATCH 3/9] branchless rounding --- contracts/utils/math/Math.sol | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/contracts/utils/math/Math.sol b/contracts/utils/math/Math.sol index 371b21bebb1..b1037cf57e5 100644 --- a/contracts/utils/math/Math.sol +++ b/contracts/utils/math/Math.sol @@ -210,11 +210,7 @@ library Math { * @dev Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { - uint256 result = mulDiv(x, y, denominator); - if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { - result += 1; - } - return result; + return mulDiv(x, y, denominator) + boolToUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0); } /** @@ -383,7 +379,7 @@ library Math { function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); - return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); + return result + boolToUint(unsignedRoundsUp(rounding) && result * result < a); } } @@ -436,7 +432,7 @@ library Math { function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); - return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); + return result + boolToUint(unsignedRoundsUp(rounding) && 1 << result < value); } } @@ -485,7 +481,7 @@ library Math { function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); - return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); + return result + boolToUint(unsignedRoundsUp(rounding) && 10 ** result < value); } } @@ -528,7 +524,7 @@ library Math { function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); - return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); + return result + boolToUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value); } } From c8e9e3c2300639e24b4292133f7d532c152ac345 Mon Sep 17 00:00:00 2001 From: CodeSandwich Date: Tue, 6 Feb 2024 20:40:46 +0100 Subject: [PATCH 4/9] Make boolToUint clean the upper bits --- contracts/utils/math/Math.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/utils/math/Math.sol b/contracts/utils/math/Math.sol index b1037cf57e5..11bb041a6b7 100644 --- a/contracts/utils/math/Math.sol +++ b/contracts/utils/math/Math.sol @@ -541,7 +541,7 @@ library Math { function boolToUint(bool b) internal pure returns (uint256 u) { /// @solidity memory-safe-assembly assembly { - u := b + u := iszero(iszero(b)) } } } From 32b3d97859a7a36795d720fe91f8dbdbbdc2bb54 Mon Sep 17 00:00:00 2001 From: CodeSandwich Date: Tue, 6 Feb 2024 20:48:50 +0100 Subject: [PATCH 5/9] Make log2 more readable --- contracts/utils/math/Math.sol | 58 +++++++++++++++++------------------ 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/contracts/utils/math/Math.sol b/contracts/utils/math/Math.sol index 11bb041a6b7..4e8e7b2c095 100644 --- a/contracts/utils/math/Math.sol +++ b/contracts/utils/math/Math.sol @@ -389,38 +389,37 @@ library Math { */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; - uint256 isGt; + uint256 exp; unchecked { - isGt = boolToUint(value > 0xffffffffffffffffffffffffffffffff); - value >>= isGt * 128; - result += isGt * 128; + exp = 128 * boolToUint(value > (1 << 128) - 1); + value >>= exp; + result += exp; - isGt = boolToUint(value > 0xffffffffffffffff); - value >>= isGt * 64; - result += isGt * 64; + exp = 64 * boolToUint(value > (1 << 64) - 1); + value >>= exp; + result += exp; - isGt = boolToUint(value > 0xffffffff); - value >>= isGt * 32; - result += isGt * 32; + exp = 32 * boolToUint(value > (1 << 32) - 1); + value >>= exp; + result += exp; - isGt = boolToUint(value > 0xffff); - value >>= isGt * 16; - result += isGt * 16; + exp = 16 * boolToUint(value > (1 << 16) - 1); + value >>= exp; + result += exp; - isGt = boolToUint(value > 0xff); - value >>= isGt * 8; - result += isGt * 8; + exp = 8 * boolToUint(value > (1 << 8) - 1); + value >>= exp; + result += exp; - isGt = boolToUint(value > 0xf); - value >>= isGt * 4; - result += isGt * 4; + exp = 4 * boolToUint(value > (1 << 4) - 1); + value >>= exp; + result += exp; - isGt = boolToUint(value > 0x3); - value >>= isGt * 2; - result += isGt * 2; + exp = 2 * boolToUint(value > (1 << 2) - 1); + value >>= exp; + result += exp; - isGt = boolToUint(value > 0x1); - result += isGt; + result += boolToUint(value > 1); } return result; } @@ -495,24 +494,23 @@ library Math { uint256 result = 0; uint256 isGt; unchecked { - isGt = boolToUint(value > 0xffffffffffffffffffffffffffffffff); + isGt = boolToUint(value > (1 << 128) - 1); value >>= isGt * 128; result += isGt * 16; - isGt = boolToUint(value > 0xffffffffffffffff); + isGt = boolToUint(value > (1 << 64) - 1); value >>= isGt * 64; result += isGt * 8; - isGt = boolToUint(value > 0xffffffff); + isGt = boolToUint(value > (1 << 32) - 1); value >>= isGt * 32; result += isGt * 4; - isGt = boolToUint(value > 0xffff); + isGt = boolToUint(value > (1 << 16) - 1); value >>= isGt * 16; result += isGt * 2; - isGt = boolToUint(value > 0xff); - result += isGt; + result += boolToUint(value > (1 << 8) - 1); } return result; } From 8417107604f584fb2aa1acb15cb6e36bf196198d Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Tue, 6 Feb 2024 21:11:37 +0100 Subject: [PATCH 6/9] Update .changeset/nervous-pans-grow.md --- .changeset/nervous-pans-grow.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/nervous-pans-grow.md b/.changeset/nervous-pans-grow.md index c535fa3a52a..7239c580ced 100644 --- a/.changeset/nervous-pans-grow.md +++ b/.changeset/nervous-pans-grow.md @@ -2,4 +2,4 @@ 'openzeppelin-solidity': patch --- -Make Math.log2 branchless +`Math`: Add `boolToUint` for branchless math. From 3ae1b4a4910d7207013e419294a52ef8eeb9e9bd Mon Sep 17 00:00:00 2001 From: ernestognw Date: Tue, 6 Feb 2024 14:52:40 -0600 Subject: [PATCH 7/9] Move `boolToUint` to `SafeCast` --- contracts/utils/math/Math.sol | 47 +++++++++++--------------- contracts/utils/math/SafeCast.sol | 10 ++++++ scripts/generate/templates/SafeCast.js | 16 +++++++-- test/utils/math/Math.test.js | 10 ------ test/utils/math/SafeCast.test.js | 10 ++++++ 5 files changed, 53 insertions(+), 40 deletions(-) diff --git a/contracts/utils/math/Math.sol b/contracts/utils/math/Math.sol index 4e8e7b2c095..be05506ec53 100644 --- a/contracts/utils/math/Math.sol +++ b/contracts/utils/math/Math.sol @@ -5,6 +5,7 @@ pragma solidity ^0.8.20; import {Address} from "../Address.sol"; import {Panic} from "../Panic.sol"; +import {SafeCast} from "./SafeCast.sol"; /** * @dev Standard math utilities missing in the Solidity language. @@ -210,7 +211,7 @@ library Math { * @dev Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { - return mulDiv(x, y, denominator) + boolToUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0); + return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0); } /** @@ -379,7 +380,7 @@ library Math { function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); - return result + boolToUint(unsignedRoundsUp(rounding) && result * result < a); + return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a); } } @@ -391,35 +392,35 @@ library Math { uint256 result = 0; uint256 exp; unchecked { - exp = 128 * boolToUint(value > (1 << 128) - 1); + exp = 128 * SafeCast.toUint(value > (1 << 128) - 1); value >>= exp; result += exp; - exp = 64 * boolToUint(value > (1 << 64) - 1); + exp = 64 * SafeCast.toUint(value > (1 << 64) - 1); value >>= exp; result += exp; - exp = 32 * boolToUint(value > (1 << 32) - 1); + exp = 32 * SafeCast.toUint(value > (1 << 32) - 1); value >>= exp; result += exp; - exp = 16 * boolToUint(value > (1 << 16) - 1); + exp = 16 * SafeCast.toUint(value > (1 << 16) - 1); value >>= exp; result += exp; - exp = 8 * boolToUint(value > (1 << 8) - 1); + exp = 8 * SafeCast.toUint(value > (1 << 8) - 1); value >>= exp; result += exp; - exp = 4 * boolToUint(value > (1 << 4) - 1); + exp = 4 * SafeCast.toUint(value > (1 << 4) - 1); value >>= exp; result += exp; - exp = 2 * boolToUint(value > (1 << 2) - 1); + exp = 2 * SafeCast.toUint(value > (1 << 2) - 1); value >>= exp; result += exp; - result += boolToUint(value > 1); + result += SafeCast.toUint(value > 1); } return result; } @@ -431,7 +432,7 @@ library Math { function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); - return result + boolToUint(unsignedRoundsUp(rounding) && 1 << result < value); + return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value); } } @@ -480,7 +481,7 @@ library Math { function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); - return result + boolToUint(unsignedRoundsUp(rounding) && 10 ** result < value); + return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value); } } @@ -494,23 +495,23 @@ library Math { uint256 result = 0; uint256 isGt; unchecked { - isGt = boolToUint(value > (1 << 128) - 1); + isGt = SafeCast.toUint(value > (1 << 128) - 1); value >>= isGt * 128; result += isGt * 16; - isGt = boolToUint(value > (1 << 64) - 1); + isGt = SafeCast.toUint(value > (1 << 64) - 1); value >>= isGt * 64; result += isGt * 8; - isGt = boolToUint(value > (1 << 32) - 1); + isGt = SafeCast.toUint(value > (1 << 32) - 1); value >>= isGt * 32; result += isGt * 4; - isGt = boolToUint(value > (1 << 16) - 1); + isGt = SafeCast.toUint(value > (1 << 16) - 1); value >>= isGt * 16; result += isGt * 2; - result += boolToUint(value > (1 << 8) - 1); + result += SafeCast.toUint(value > (1 << 8) - 1); } return result; } @@ -522,7 +523,7 @@ library Math { function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); - return result + boolToUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value); + return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value); } } @@ -532,14 +533,4 @@ library Math { function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } - - /** - * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump. - */ - function boolToUint(bool b) internal pure returns (uint256 u) { - /// @solidity memory-safe-assembly - assembly { - u := iszero(iszero(b)) - } - } } diff --git a/contracts/utils/math/SafeCast.sol b/contracts/utils/math/SafeCast.sol index 0ed458b43c2..3063e80de69 100644 --- a/contracts/utils/math/SafeCast.sol +++ b/contracts/utils/math/SafeCast.sol @@ -1150,4 +1150,14 @@ library SafeCast { } return int256(value); } + + /** + * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump. + */ + function toUint(bool b) internal pure returns (uint256 u) { + /// @solidity memory-safe-assembly + assembly { + u := iszero(iszero(b)) + } + } } diff --git a/scripts/generate/templates/SafeCast.js b/scripts/generate/templates/SafeCast.js index f1954a7533f..a10ee75c975 100644 --- a/scripts/generate/templates/SafeCast.js +++ b/scripts/generate/templates/SafeCast.js @@ -7,7 +7,7 @@ const header = `\ pragma solidity ^0.8.20; /** - * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow + * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can @@ -116,11 +116,23 @@ function toUint${length}(int${length} value) internal pure returns (uint${length } `; +const boolToUint = ` + /** + * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump. + */ + function toUint(bool b) internal pure returns (uint256 u) { + /// @solidity memory-safe-assembly + assembly { + u := iszero(iszero(b)) + } + } +`; + // GENERATE module.exports = format( header.trimEnd(), 'library SafeCast {', errors, - [...LENGTHS.map(toUintDownCast), toUint(256), ...LENGTHS.map(toIntDownCast), toInt(256)], + [...LENGTHS.map(toUintDownCast), toUint(256), ...LENGTHS.map(toIntDownCast), toInt(256), boolToUint], '}', ); diff --git a/test/utils/math/Math.test.js b/test/utils/math/Math.test.js index bb565e8ae98..2762fcc5732 100644 --- a/test/utils/math/Math.test.js +++ b/test/utils/math/Math.test.js @@ -512,14 +512,4 @@ describe('Math', function () { }); }); }); - - describe('boolToUint', function () { - it('boolToUint(false) should be 0', async function () { - expect(await this.mock.$boolToUint(false)).to.equal(0n); - }); - - it('boolToUint(true) should be 1', async function () { - expect(await this.mock.$boolToUint(true)).to.equal(1n); - }); - }); }); diff --git a/test/utils/math/SafeCast.test.js b/test/utils/math/SafeCast.test.js index ecf55dc35a2..aa609faf0ac 100644 --- a/test/utils/math/SafeCast.test.js +++ b/test/utils/math/SafeCast.test.js @@ -146,4 +146,14 @@ describe('SafeCast', function () { .withArgs(ethers.MaxUint256); }); }); + + describe('toUint (bool)', function () { + it('toUint(false) should be 0', async function () { + expect(await this.mock.$toUint(false)).to.equal(0n); + }); + + it('toUint(true) should be 1', async function () { + expect(await this.mock.$toUint(true)).to.equal(1n); + }); + }); }); From f8cb79296b569cb76df09df71bd6272d8afc9610 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ernesto=20Garc=C3=ADa?= Date: Tue, 6 Feb 2024 14:54:56 -0600 Subject: [PATCH 8/9] Update .changeset/nervous-pans-grow.md --- .changeset/nervous-pans-grow.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/nervous-pans-grow.md b/.changeset/nervous-pans-grow.md index 7239c580ced..b86a075c678 100644 --- a/.changeset/nervous-pans-grow.md +++ b/.changeset/nervous-pans-grow.md @@ -2,4 +2,4 @@ 'openzeppelin-solidity': patch --- -`Math`: Add `boolToUint` for branchless math. +`SafeCast`: Add `toUint(bool)` for operating on `bool` values as `uint256`. From a371515012d13905837958e92682a4cbb6cc32a4 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Tue, 6 Feb 2024 22:04:51 +0100 Subject: [PATCH 9/9] fix generation --- contracts/utils/math/SafeCast.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/utils/math/SafeCast.sol b/contracts/utils/math/SafeCast.sol index 3063e80de69..d8de2e17c49 100644 --- a/contracts/utils/math/SafeCast.sol +++ b/contracts/utils/math/SafeCast.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.20; /** - * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow + * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can