From 2cce7754ba2ad5fbdce68f178cf08b5452b120e3 Mon Sep 17 00:00:00 2001 From: Rappie Date: Wed, 13 Mar 2024 18:01:45 +0100 Subject: [PATCH 1/5] Add `f` assertion (inverse of `t`) --- src/AssertWrapper.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/AssertWrapper.sol b/src/AssertWrapper.sol index 45f00a2..b6b3514 100644 --- a/src/AssertWrapper.sol +++ b/src/AssertWrapper.sol @@ -59,4 +59,8 @@ abstract contract AssertWrapper is AssertHelper { function t(bool a, string memory message) internal { assertWithMsg(a, message); } + + function f(bool a, string memory message) internal { + assertWithMsg(!a, message); + } } From 2c702810263d0c0d83487c44e15f4a4add5ef7d7 Mon Sep 17 00:00:00 2001 From: Rappie Date: Wed, 13 Mar 2024 20:43:59 +0100 Subject: [PATCH 2/5] Refactor assertion helpers to use short naming (`eq` vs `assertEq`). `AssertHelperFullName` is available for backwards compatibility. --- src/AssertHelper.sol | 166 +++++++++++++---------------------- src/AssertHelperFullName.sol | 64 ++++++++++++++ src/AssertWrapper.sol | 66 -------------- src/ClampHelper.sol | 4 +- src/FuzzBase.sol | 4 +- 5 files changed, 127 insertions(+), 177 deletions(-) create mode 100644 src/AssertHelperFullName.sol delete mode 100644 src/AssertWrapper.sol diff --git a/src/AssertHelper.sol b/src/AssertHelper.sol index 4928fa3..b47a844 100644 --- a/src/AssertHelper.sol +++ b/src/AssertHelper.sol @@ -13,19 +13,19 @@ abstract contract AssertHelper { event AssertLteFail(string); event AssertLtFail(string); - function assertWithMsg(bool b, string memory reason) internal { - if (!b) { + function t(bool a, string memory reason) internal { + if (!a) { emit AssertFail(reason); assert(false); } } + function f(bool a, string memory reason) internal { + t(!a, reason); + } + /// @notice asserts that a is equal to b. Violations are logged using reason. - function assertEq( - uint256 a, - uint256 b, - string memory reason - ) internal { + function eq(uint256 a, uint256 b, string memory reason) internal { if (a != b) { string memory aStr = FuzzLibString.toString(a); string memory bStr = FuzzLibString.toString(b); @@ -42,12 +42,8 @@ abstract contract AssertHelper { } } - /// @notice int256 version of assertEq - function assertEq( - int256 a, - int256 b, - string memory reason - ) internal { + /// @notice int256 version of `eq` + function eq(int256 a, int256 b, string memory reason) internal { if (a != b) { string memory aStr = FuzzLibString.toString(a); string memory bStr = FuzzLibString.toString(b); @@ -64,12 +60,8 @@ abstract contract AssertHelper { } } - /// @notice bytes4 version of assertEq - function assertEq( - bytes4 a, - bytes4 b, - string memory reason - ) internal { + /// @notice bytes4 version of `eq` + function eq(bytes4 a, bytes4 b, string memory reason) internal { if (a != b) { bytes memory aBytes = abi.encodePacked(a); bytes memory bBytes = abi.encodePacked(b); @@ -89,11 +81,7 @@ abstract contract AssertHelper { } /// @notice asserts that a is not equal to b. Violations are logged using reason. - function assertNeq( - uint256 a, - uint256 b, - string memory reason - ) internal { + function neq(uint256 a, uint256 b, string memory reason) internal { if (a == b) { string memory aStr = FuzzLibString.toString(a); string memory bStr = FuzzLibString.toString(b); @@ -110,12 +98,8 @@ abstract contract AssertHelper { } } - /// @notice int256 version of assertNeq - function assertNeq( - int256 a, - int256 b, - string memory reason - ) internal { + /// @notice int256 version of `neq` + function neq(int256 a, int256 b, string memory reason) internal { if (a == b) { string memory aStr = FuzzLibString.toString(a); string memory bStr = FuzzLibString.toString(b); @@ -132,178 +116,146 @@ abstract contract AssertHelper { } } - /// @notice asserts that a is greater than or equal to b. Violations are logged using reason. - function assertGte( - uint256 a, - uint256 b, - string memory reason - ) internal { - if (!(a >= b)) { + /// @notice asserts that a is greater than b. Violations are logged using reason. + function gt(uint256 a, uint256 b, string memory reason) internal { + if (!(a > b)) { string memory aStr = FuzzLibString.toString(a); string memory bStr = FuzzLibString.toString(b); bytes memory assertMsg = abi.encodePacked( "Invalid: ", aStr, - "<", + "<=", bStr, " failed, reason: ", reason ); - emit AssertGteFail(string(assertMsg)); + emit AssertGtFail(string(assertMsg)); assert(false); } } - /// @notice int256 version of assertGte - function assertGte( - int256 a, - int256 b, - string memory reason - ) internal { - if (!(a >= b)) { + /// @notice int256 version of `gt` + function gt(int256 a, int256 b, string memory reason) internal { + if (!(a > b)) { string memory aStr = FuzzLibString.toString(a); string memory bStr = FuzzLibString.toString(b); bytes memory assertMsg = abi.encodePacked( "Invalid: ", aStr, - "<", + "<=", bStr, " failed, reason: ", reason ); - emit AssertGteFail(string(assertMsg)); + emit AssertGtFail(string(assertMsg)); assert(false); } } - /// @notice asserts that a is greater than b. Violations are logged using reason. - function assertGt( - uint256 a, - uint256 b, - string memory reason - ) internal { - if (!(a > b)) { + /// @notice asserts that a is greater than or equal to b. Violations are logged using reason. + function gte(uint256 a, uint256 b, string memory reason) internal { + if (!(a >= b)) { string memory aStr = FuzzLibString.toString(a); string memory bStr = FuzzLibString.toString(b); bytes memory assertMsg = abi.encodePacked( "Invalid: ", aStr, - "<=", + "<", bStr, " failed, reason: ", reason ); - emit AssertGtFail(string(assertMsg)); + emit AssertGteFail(string(assertMsg)); assert(false); } } - /// @notice int256 version of assertGt - function assertGt( - int256 a, - int256 b, - string memory reason - ) internal { - if (!(a > b)) { + /// @notice int256 version of assertGte + function gte(int256 a, int256 b, string memory reason) internal { + if (!(a >= b)) { string memory aStr = FuzzLibString.toString(a); string memory bStr = FuzzLibString.toString(b); bytes memory assertMsg = abi.encodePacked( "Invalid: ", aStr, - "<=", + "<", bStr, " failed, reason: ", reason ); - emit AssertGtFail(string(assertMsg)); + emit AssertGteFail(string(assertMsg)); assert(false); } } - /// @notice asserts that a is less than or equal to b. Violations are logged using reason. - function assertLte( - uint256 a, - uint256 b, - string memory reason - ) internal { - if (!(a <= b)) { + /// @notice asserts that a is less than b. Violations are logged using reason. + function lt(uint256 a, uint256 b, string memory reason) internal { + if (!(a < b)) { string memory aStr = FuzzLibString.toString(a); string memory bStr = FuzzLibString.toString(b); bytes memory assertMsg = abi.encodePacked( "Invalid: ", aStr, - ">", + ">=", bStr, " failed, reason: ", reason ); - emit AssertLteFail(string(assertMsg)); + emit AssertLtFail(string(assertMsg)); assert(false); } } - /// @notice int256 version of assertLte - function assertLte( - int256 a, - int256 b, - string memory reason - ) internal { - if (!(a <= b)) { + /// @notice int256 version of assertLt + function lt(int256 a, int256 b, string memory reason) internal { + if (!(a < b)) { string memory aStr = FuzzLibString.toString(a); string memory bStr = FuzzLibString.toString(b); bytes memory assertMsg = abi.encodePacked( "Invalid: ", aStr, - ">", + ">=", bStr, " failed, reason: ", reason ); - emit AssertLteFail(string(assertMsg)); + emit AssertLtFail(string(assertMsg)); assert(false); } } - /// @notice asserts that a is less than b. Violations are logged using reason. - function assertLt( - uint256 a, - uint256 b, - string memory reason - ) internal { - if (!(a < b)) { + /// @notice asserts that a is less than or equal to b. Violations are logged using reason. + function lte(uint256 a, uint256 b, string memory reason) internal { + if (!(a <= b)) { string memory aStr = FuzzLibString.toString(a); string memory bStr = FuzzLibString.toString(b); bytes memory assertMsg = abi.encodePacked( "Invalid: ", aStr, - ">=", + ">", bStr, " failed, reason: ", reason ); - emit AssertLtFail(string(assertMsg)); + emit AssertLteFail(string(assertMsg)); assert(false); } } - /// @notice int256 version of assertLt - function assertLt( - int256 a, - int256 b, - string memory reason - ) internal { - if (!(a < b)) { + /// @notice int256 version of assertLte + function lte(int256 a, int256 b, string memory reason) internal { + if (!(a <= b)) { string memory aStr = FuzzLibString.toString(a); string memory bStr = FuzzLibString.toString(b); bytes memory assertMsg = abi.encodePacked( "Invalid: ", aStr, - ">=", + ">", bStr, " failed, reason: ", reason ); - emit AssertLtFail(string(assertMsg)); + emit AssertLteFail(string(assertMsg)); assert(false); } } @@ -313,7 +265,7 @@ abstract contract AssertHelper { string memory reason ) internal { bool isEqual = FuzzLibString.isRevertReasonEqual(returnData, reason); - assertWithMsg(!isEqual, reason); + f(isEqual, reason); } function assertRevertReasonEqual( @@ -321,7 +273,7 @@ abstract contract AssertHelper { string memory reason ) internal { bool isEqual = FuzzLibString.isRevertReasonEqual(returnData, reason); - assertWithMsg(isEqual, reason); + t(isEqual, reason); } function assertRevertReasonEqual( @@ -331,7 +283,7 @@ abstract contract AssertHelper { ) internal { bool isEqual = FuzzLibString.isRevertReasonEqual(returnData, reason1) || FuzzLibString.isRevertReasonEqual(returnData, reason2); - assertWithMsg(isEqual, string.concat(reason1, " OR ", reason2)); + t(isEqual, string.concat(reason1, " OR ", reason2)); } function assertRevertReasonEqual( @@ -343,7 +295,7 @@ abstract contract AssertHelper { bool isEqual = FuzzLibString.isRevertReasonEqual(returnData, reason1) || FuzzLibString.isRevertReasonEqual(returnData, reason2) || FuzzLibString.isRevertReasonEqual(returnData, reason3); - assertWithMsg(isEqual, string.concat(reason1, " OR ", reason2, " OR ", reason3)); + t(isEqual, string.concat(reason1, " OR ", reason2, " OR ", reason3)); } function assertRevertReasonEqual( @@ -357,7 +309,7 @@ abstract contract AssertHelper { FuzzLibString.isRevertReasonEqual(returnData, reason2) || FuzzLibString.isRevertReasonEqual(returnData, reason3) || FuzzLibString.isRevertReasonEqual(returnData, reason4); - assertWithMsg( + t( isEqual, string.concat( reason1, diff --git a/src/AssertHelperFullName.sol b/src/AssertHelperFullName.sol new file mode 100644 index 0000000..2046a44 --- /dev/null +++ b/src/AssertHelperFullName.sol @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "./AssertHelper.sol"; + +/// @author Based on Crytic PropertiesHelper (https://github.com/crytic/properties/blob/main/contracts/util/PropertiesHelper.sol) +/// @notice This contract can be used for compatibility with the Crytic PropertiesHelper API +abstract contract AssertHelperFullName is AssertHelper { + function assertWithMsg(bool b, string memory reason) internal { + t(b, reason); + } + + function assertEq(uint256 a, uint256 b, string memory reason) internal { + eq(a, b, reason); + } + + function assertEq(int256 a, int256 b, string memory reason) internal { + eq(a, b, reason); + } + + function assertEq(bytes4 a, bytes4 b, string memory reason) internal { + eq(a, b, reason); + } + + function assertNeq(uint256 a, uint256 b, string memory reason) internal { + neq(a, b, reason); + } + + function assertNeq(int256 a, int256 b, string memory reason) internal { + neq(a, b, reason); + } + + function assertGt(uint256 a, uint256 b, string memory reason) internal { + gt(a, b, reason); + } + + function assertGt(int256 a, int256 b, string memory reason) internal { + gt(a, b, reason); + } + + function assertGte(uint256 a, uint256 b, string memory reason) internal { + gte(a, b, reason); + } + + function assertGte(int256 a, int256 b, string memory reason) internal { + gte(a, b, reason); + } + + function assertLt(uint256 a, uint256 b, string memory reason) internal { + lt(a, b, reason); + } + + function assertLt(int256 a, int256 b, string memory reason) internal { + lt(a, b, reason); + } + + function assertLte(uint256 a, uint256 b, string memory reason) internal { + lte(a, b, reason); + } + + function assertLte(int256 a, int256 b, string memory reason) internal { + lte(a, b, reason); + } +} diff --git a/src/AssertWrapper.sol b/src/AssertWrapper.sol deleted file mode 100644 index b6b3514..0000000 --- a/src/AssertWrapper.sol +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "./AssertHelper.sol"; - -abstract contract AssertWrapper is AssertHelper { - function gt(uint256 a, uint256 b, string memory message) internal { - assertGt(a, b, message); - } - - function gt(int256 a, int256 b, string memory message) internal { - assertGt(a, b, message); - } - - function lt(uint256 a, uint256 b, string memory message) internal { - assertLt(a, b, message); - } - - function lt(int256 a, int256 b, string memory message) internal { - assertLt(a, b, message); - } - - function gte(uint256 a, uint256 b, string memory message) internal { - assertGte(a, b, message); - } - - function gte(int256 a, int256 b, string memory message) internal { - assertGte(a, b, message); - } - - function lte(uint256 a, uint256 b, string memory message) internal { - assertLte(a, b, message); - } - - function lte(int256 a, int256 b, string memory message) internal { - assertLte(a, b, message); - } - - function eq(uint256 a, uint256 b, string memory message) internal { - assertEq(a, b, message); - } - - function eq(int256 a, int256 b, string memory message) internal { - assertEq(a, b, message); - } - - function eq(bytes4 a, bytes4 b, string memory message) internal { - assertEq(a, b, message); - } - - function neq(uint256 a, uint256 b, string memory message) internal { - assertNeq(a, b, message); - } - - function neq(int256 a, int256 b, string memory message) internal { - assertNeq(a, b, message); - } - - function t(bool a, string memory message) internal { - assertWithMsg(a, message); - } - - function f(bool a, string memory message) internal { - assertWithMsg(!a, message); - } -} diff --git a/src/ClampHelper.sol b/src/ClampHelper.sol index b7bc419..a961116 100644 --- a/src/ClampHelper.sol +++ b/src/ClampHelper.sol @@ -64,7 +64,7 @@ abstract contract ClampHelper is AssertHelper { /// @notice clamps a to be less than b function clampLt(uint256 a, uint256 b, bool enableLogs) internal returns (uint256) { if (!(a < b)) { - assertNeq( + neq( b, 0, "clampLt cannot clamp value a to be less than zero. Check your inputs/assumptions." @@ -149,7 +149,7 @@ abstract contract ClampHelper is AssertHelper { /// @notice clamps a to be greater than b function clampGt(uint256 a, uint256 b, bool enableLogs) internal returns (uint256) { if (!(a > b)) { - assertNeq( + neq( b, type(uint256).max, "clampGt cannot clamp value a to be larger than uint256.max. Check your inputs/assumptions." diff --git a/src/FuzzBase.sol b/src/FuzzBase.sol index 9e5048a..8e67d34 100644 --- a/src/FuzzBase.sol +++ b/src/FuzzBase.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import "./AssertWrapper.sol"; +import "./AssertHelper.sol"; import "./ClampWrapper.sol"; import "./MathHelper.sol"; import "./RandomHelper.sol"; @@ -11,7 +11,7 @@ import "./IHevm.sol"; import "./IStdCheats.sol"; abstract contract FuzzBase is - AssertWrapper, + AssertHelper, ClampWrapper, MathHelper, RandomHelper, From f33d3bcac36f9e3fb6fbd954027b74480d6044d1 Mon Sep 17 00:00:00 2001 From: Rappie Date: Fri, 15 Mar 2024 12:08:11 +0100 Subject: [PATCH 3/5] Documentation --- src/AssertHelper.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/src/AssertHelper.sol b/src/AssertHelper.sol index b47a844..708528c 100644 --- a/src/AssertHelper.sol +++ b/src/AssertHelper.sol @@ -13,6 +13,7 @@ abstract contract AssertHelper { event AssertLteFail(string); event AssertLtFail(string); + /// @notice asserts that a is true. Violations are logged using reason. function t(bool a, string memory reason) internal { if (!a) { emit AssertFail(reason); From 5c1282fb03129dc96e25a0af1f8f726c23ad5435 Mon Sep 17 00:00:00 2001 From: Rappie Date: Fri, 15 Mar 2024 12:08:18 +0100 Subject: [PATCH 4/5] Remove `f` function --- src/AssertHelper.sol | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/AssertHelper.sol b/src/AssertHelper.sol index 708528c..a20cd72 100644 --- a/src/AssertHelper.sol +++ b/src/AssertHelper.sol @@ -21,10 +21,6 @@ abstract contract AssertHelper { } } - function f(bool a, string memory reason) internal { - t(!a, reason); - } - /// @notice asserts that a is equal to b. Violations are logged using reason. function eq(uint256 a, uint256 b, string memory reason) internal { if (a != b) { From 50f190c1e6d34ac66b70bbe8cb761cf5553dd1b8 Mon Sep 17 00:00:00 2001 From: Rappie Date: Fri, 15 Mar 2024 12:10:33 +0100 Subject: [PATCH 5/5] Bugfix --- src/AssertHelper.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AssertHelper.sol b/src/AssertHelper.sol index a20cd72..fa7df74 100644 --- a/src/AssertHelper.sol +++ b/src/AssertHelper.sol @@ -262,7 +262,7 @@ abstract contract AssertHelper { string memory reason ) internal { bool isEqual = FuzzLibString.isRevertReasonEqual(returnData, reason); - f(isEqual, reason); + t(!isEqual, reason); } function assertRevertReasonEqual(