diff --git a/src/AssertWrapper.sol b/src/AssertWrapper.sol deleted file mode 100644 index 87b8766..0000000 --- a/src/AssertWrapper.sol +++ /dev/null @@ -1,70 +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 errAllow(bytes4 errorSelector, bytes4[] memory allowedErrors, string memory message) internal { - assertErrorsAllowed(errorSelector, allowedErrors, message); - } - - function errsAllow(bytes4 errorSelector, bytes4[] memory allowedErrors, string[] memory message) internal { - assertErrorsAllowedMultiMsg(errorSelector, allowedErrors, message); - } -} diff --git a/src/ClampWrapper.sol b/src/ClampWrapper.sol deleted file mode 100644 index 503f2ca..0000000 --- a/src/ClampWrapper.sol +++ /dev/null @@ -1,65 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "./ClampHelper.sol"; - -abstract contract ClampWrapper is ClampHelper { - - /// @notice Clamps value to be between low and high, both inclusive - function clampBetween( - uint256 value, - uint256 low, - uint256 high - ) internal returns (uint256) { - return clampBetween(value, low, high, true); - } - - /// @notice int256 version of clampBetween - function clampBetween( - int256 value, - int256 low, - int256 high - ) internal returns (int256) { - return clampBetween(value, low, high, true); - } - - /// @notice clamps a to be less than b - function clampLt(uint256 a, uint256 b) internal returns (uint256) { - return clampLt(a, b); - } - - /// @notice int256 version of clampLt - function clampLt(int256 a, int256 b) internal returns (int256) { - return clampLt(a, b, true); - } - - /// @notice clamps a to be less than or equal to b - function clampLte(uint256 a, uint256 b) internal returns (uint256) { - return clampLte(a, b, true); - } - - /// @notice int256 version of clampLte - function clampLte(int256 a, int256 b) internal returns (int256) { - return clampLte(a, b, true); - } - - /// @notice clamps a to be greater than b - function clampGt(uint256 a, uint256 b) internal returns (uint256) { - return clampGt(a, b, true); - } - - /// @notice int256 version of clampGt - function clampGt(int256 a, int256 b) internal returns (int256) { - return clampGt(a, b, true); - } - - /// @notice clamps a to be greater than or equal to b - function clampGte(uint256 a, uint256 b) internal returns (uint256) { - return clampGte(a, b, true); - } - - /// @notice int256 version of clampGte - function clampGte(int256 a, int256 b) internal returns (int256) { - return clampGte(a, b, true); - } -} diff --git a/src/Constants.sol b/src/Constants.sol index 0f4ddad..75bf73a 100644 --- a/src/Constants.sol +++ b/src/Constants.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -abstract contract Constants { +library Constants { // https://docs.soliditylang.org/en/latest/control-structures.html#panic-via-assert-and-error-via-require // 0x00: Used for generic compiler inserted panics. // 0x01: If you call assert with an argument that evaluates to false. @@ -13,14 +13,17 @@ abstract contract Constants { // 0x32: If you access an array, bytesN or an array slice at an out-of-bounds or negative index (i.e. x[i] where i >= x.length or i < 0). // 0x41: If you allocate too much memory or create an array that is too large. // 0x51: If you call a zero-initialized variable of internal function type. - uint256 internal constant PANIC_GENERAL = 0x00; - uint256 internal constant PANIC_ASSERT = 0x01; - uint256 internal constant PANIC_ARITHMETIC = 0x11; - uint256 internal constant PANIC_DIVISION_BY_ZERO = 0x12; - uint256 internal constant PANIC_ENUM_OUT_OF_BOUNDS = 0x21; - uint256 internal constant PANIC_STORAGE_BYTES_ARRAY_ENCODING = 0x22; - uint256 internal constant PANIC_POP_EMPTY_ARRAY = 0x31; - uint256 internal constant PANIC_ARRAY_OUT_OF_BOUNDS = 0x32; - uint256 internal constant PANIC_ALLOC_TOO_MUCH_MEMORY = 0x41; - uint256 internal constant PANIC_ZERO_INIT_INTERNAL_FUNCTION = 0x51; + uint256 public constant PANIC_GENERAL = 0x00; + uint256 public constant PANIC_ASSERT = 0x01; + uint256 public constant PANIC_ARITHMETIC = 0x11; + uint256 public constant PANIC_DIVISION_BY_ZERO = 0x12; + uint256 public constant PANIC_ENUM_OUT_OF_BOUNDS = 0x21; + uint256 public constant PANIC_STORAGE_BYTES_ARRAY_ENCODING = 0x22; + uint256 public constant PANIC_POP_EMPTY_ARRAY = 0x31; + uint256 public constant PANIC_ARRAY_OUT_OF_BOUNDS = 0x32; + uint256 public constant PANIC_ALLOC_TOO_MUCH_MEMORY = 0x41; + uint256 public constant PANIC_ZERO_INIT_INTERNAL_FUNCTION = 0x51; + + address public constant ADDRESS_CHEATS = + 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D; } diff --git a/src/FuzzBase.sol b/src/FuzzBase.sol index 9e5048a..f1751ae 100644 --- a/src/FuzzBase.sol +++ b/src/FuzzBase.sol @@ -1,23 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import "./AssertWrapper.sol"; -import "./ClampWrapper.sol"; -import "./MathHelper.sol"; -import "./RandomHelper.sol"; -import "./Logging.sol"; -import "./Constants.sol"; -import "./IHevm.sol"; -import "./IStdCheats.sol"; +import {Fuzzlib} from "./Fuzzlib.sol"; +import {PlatformCrytic} from "./platform/PlatformCrytic.sol"; -abstract contract FuzzBase is - AssertWrapper, - ClampWrapper, - MathHelper, - RandomHelper, - Logging, - Constants -{ - IHevm internal vm = IHevm(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D); // for echidna - IStdCheats internal mvm = IStdCheats(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D); // for medusa +abstract contract FuzzBase { + Fuzzlib internal fl = new Fuzzlib(); + + constructor() { + fl.setPlatform(address(new PlatformCrytic())); + } } diff --git a/src/Fuzzlib.sol b/src/Fuzzlib.sol new file mode 100644 index 0000000..0fc1770 --- /dev/null +++ b/src/Fuzzlib.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {HelperBase} from "./helpers/HelperBase.sol"; +import {HelperAssert} from "./helpers/HelperAssert.sol"; +import {HelperCheats} from "./helpers/HelperCheats.sol"; +import {HelperClamp} from "./helpers/HelperClamp.sol"; + +contract Fuzzlib is + HelperBase, + HelperAssert, + HelperCheats, + HelperClamp +{} diff --git a/src/AssertHelper.sol b/src/helpers/HelperAssert.sol similarity index 84% rename from src/AssertHelper.sol rename to src/helpers/HelperAssert.sol index 4e70c23..b6c0549 100644 --- a/src/AssertHelper.sol +++ b/src/helpers/HelperAssert.sol @@ -1,10 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import "./FuzzLibString.sol"; +import "./HelperBase.sol"; + +import "../FuzzLibString.sol"; /// @author Based on Crytic PropertiesHelper (https://github.com/crytic/properties/blob/main/contracts/util/PropertiesHelper.sol) -abstract contract AssertHelper { +abstract contract HelperAssert is HelperBase { event AssertFail(string); event AssertEqFail(string); event AssertNeqFail(string); @@ -13,19 +15,19 @@ abstract contract AssertHelper { event AssertLteFail(string); event AssertLtFail(string); - function assertWithMsg(bool b, string memory reason) internal { + function t(bool b, string memory reason) public { if (!b) { emit AssertFail(reason); - assert(false); + platform.assertFail(); } } /// @notice asserts that a is equal to b. Violations are logged using reason. - function assertEq( + function eq( uint256 a, uint256 b, string memory reason - ) internal { + ) public { if (a != b) { string memory aStr = FuzzLibString.toString(a); string memory bStr = FuzzLibString.toString(b); @@ -38,16 +40,16 @@ abstract contract AssertHelper { reason ); emit AssertEqFail(string(assertMsg)); - assert(false); + platform.assertFail(); } } - /// @notice int256 version of assertEq - function assertEq( + /// @notice int256 version of eq + function eq( int256 a, int256 b, string memory reason - ) internal { + ) public { if (a != b) { string memory aStr = FuzzLibString.toString(a); string memory bStr = FuzzLibString.toString(b); @@ -60,16 +62,16 @@ abstract contract AssertHelper { reason ); emit AssertEqFail(string(assertMsg)); - assert(false); + platform.assertFail(); } } - /// @notice bytes4 version of assertEq - function assertEq( + /// @notice bytes4 version of eq + function eq( bytes4 a, bytes4 b, string memory reason - ) internal { + ) public { if (a != b) { bytes memory aBytes = abi.encodePacked(a); bytes memory bBytes = abi.encodePacked(b); @@ -84,16 +86,16 @@ abstract contract AssertHelper { reason ); emit AssertEqFail(string(assertMsg)); - assert(false); + platform.assertFail(); } } /// @notice asserts that a is not equal to b. Violations are logged using reason. - function assertNeq( + function neq( uint256 a, uint256 b, string memory reason - ) internal { + ) public { if (a == b) { string memory aStr = FuzzLibString.toString(a); string memory bStr = FuzzLibString.toString(b); @@ -106,16 +108,16 @@ abstract contract AssertHelper { reason ); emit AssertNeqFail(string(assertMsg)); - assert(false); + platform.assertFail(); } } - /// @notice int256 version of assertNeq - function assertNeq( + /// @notice int256 version of neq + function neq( int256 a, int256 b, string memory reason - ) internal { + ) public { if (a == b) { string memory aStr = FuzzLibString.toString(a); string memory bStr = FuzzLibString.toString(b); @@ -128,16 +130,16 @@ abstract contract AssertHelper { reason ); emit AssertNeqFail(string(assertMsg)); - assert(false); + platform.assertFail(); } } /// @notice asserts that a is greater than or equal to b. Violations are logged using reason. - function assertGte( + function gte( uint256 a, uint256 b, string memory reason - ) internal { + ) public { if (!(a >= b)) { string memory aStr = FuzzLibString.toString(a); string memory bStr = FuzzLibString.toString(b); @@ -150,16 +152,16 @@ abstract contract AssertHelper { reason ); emit AssertGteFail(string(assertMsg)); - assert(false); + platform.assertFail(); } } - /// @notice int256 version of assertGte - function assertGte( + /// @notice int256 version of gte + function gte( int256 a, int256 b, string memory reason - ) internal { + ) public { if (!(a >= b)) { string memory aStr = FuzzLibString.toString(a); string memory bStr = FuzzLibString.toString(b); @@ -172,16 +174,16 @@ abstract contract AssertHelper { reason ); emit AssertGteFail(string(assertMsg)); - assert(false); + platform.assertFail(); } } /// @notice asserts that a is greater than b. Violations are logged using reason. - function assertGt( + function gt( uint256 a, uint256 b, string memory reason - ) internal { + ) public { if (!(a > b)) { string memory aStr = FuzzLibString.toString(a); string memory bStr = FuzzLibString.toString(b); @@ -194,16 +196,16 @@ abstract contract AssertHelper { reason ); emit AssertGtFail(string(assertMsg)); - assert(false); + platform.assertFail(); } } - /// @notice int256 version of assertGt - function assertGt( + /// @notice int256 version of gt + function gt( int256 a, int256 b, string memory reason - ) internal { + ) public { if (!(a > b)) { string memory aStr = FuzzLibString.toString(a); string memory bStr = FuzzLibString.toString(b); @@ -216,16 +218,16 @@ abstract contract AssertHelper { reason ); emit AssertGtFail(string(assertMsg)); - assert(false); + platform.assertFail(); } } /// @notice asserts that a is less than or equal to b. Violations are logged using reason. - function assertLte( + function lte( uint256 a, uint256 b, string memory reason - ) internal { + ) public { if (!(a <= b)) { string memory aStr = FuzzLibString.toString(a); string memory bStr = FuzzLibString.toString(b); @@ -238,16 +240,16 @@ abstract contract AssertHelper { reason ); emit AssertLteFail(string(assertMsg)); - assert(false); + platform.assertFail(); } } - /// @notice int256 version of assertLte - function assertLte( + /// @notice int256 version of lte + function lte( int256 a, int256 b, string memory reason - ) internal { + ) public { if (!(a <= b)) { string memory aStr = FuzzLibString.toString(a); string memory bStr = FuzzLibString.toString(b); @@ -260,16 +262,16 @@ abstract contract AssertHelper { reason ); emit AssertLteFail(string(assertMsg)); - assert(false); + platform.assertFail(); } } /// @notice asserts that a is less than b. Violations are logged using reason. - function assertLt( + function lt( uint256 a, uint256 b, string memory reason - ) internal { + ) public { if (!(a < b)) { string memory aStr = FuzzLibString.toString(a); string memory bStr = FuzzLibString.toString(b); @@ -282,16 +284,16 @@ abstract contract AssertHelper { reason ); emit AssertLtFail(string(assertMsg)); - assert(false); + platform.assertFail(); } } - /// @notice int256 version of assertLt - function assertLt( + /// @notice int256 version of lt + function lt( int256 a, int256 b, string memory reason - ) internal { + ) public { if (!(a < b)) { string memory aStr = FuzzLibString.toString(a); string memory bStr = FuzzLibString.toString(b); @@ -304,37 +306,37 @@ abstract contract AssertHelper { reason ); emit AssertLtFail(string(assertMsg)); - assert(false); + platform.assertFail(); } } function assertRevertReasonNotEqual( bytes memory returnData, string memory reason - ) internal { + ) public { bool isEqual = FuzzLibString.isRevertReasonEqual(returnData, reason); - assertWithMsg(!isEqual, reason); + t(!isEqual, reason); } function assertRevertReasonEqual( bytes memory returnData, string memory reason - ) internal { + ) public { bool isEqual = FuzzLibString.isRevertReasonEqual(returnData, reason); - assertWithMsg(isEqual, reason); + t(isEqual, reason); } function assertRevertReasonEqual( bytes memory returnData, string memory reason1, string memory reason2 - ) internal { + ) public { bool isEqual = FuzzLibString.isRevertReasonEqual(returnData, reason1) || FuzzLibString.isRevertReasonEqual(returnData, reason2); string memory assertMsg = string( abi.encodePacked(reason1, " OR ", reason2) ); - assertWithMsg(isEqual, assertMsg); + t(isEqual, assertMsg); } function assertRevertReasonEqual( @@ -342,14 +344,14 @@ abstract contract AssertHelper { string memory reason1, string memory reason2, string memory reason3 - ) internal { + ) public { bool isEqual = FuzzLibString.isRevertReasonEqual(returnData, reason1) || FuzzLibString.isRevertReasonEqual(returnData, reason2) || FuzzLibString.isRevertReasonEqual(returnData, reason3); string memory assertMsg = string( abi.encodePacked(reason1, " OR ", reason2, " OR ", reason3) ); - assertWithMsg(isEqual, assertMsg); + t(isEqual, assertMsg); } function assertRevertReasonEqual( @@ -358,7 +360,7 @@ abstract contract AssertHelper { string memory reason2, string memory reason3, string memory reason4 - ) internal { + ) public { bool isEqual = FuzzLibString.isRevertReasonEqual(returnData, reason1) || FuzzLibString.isRevertReasonEqual(returnData, reason2) || FuzzLibString.isRevertReasonEqual(returnData, reason3) || @@ -374,14 +376,14 @@ abstract contract AssertHelper { reason4 ) ); - assertWithMsg(isEqual, assertMsg); + t(isEqual, assertMsg); } - function assertErrorsAllowed( + function errAllow( bytes4 errorSelector, bytes4[] memory allowedErrors, string memory message - ) internal { + ) public { bool allowed = false; for (uint256 i = 0; i < allowedErrors.length; i++) { if (errorSelector == allowedErrors[i]) { @@ -389,14 +391,14 @@ abstract contract AssertHelper { break; } } - assertWithMsg(allowed, message); + t(allowed, message); } - function assertErrorsAllowedMultiMsg( + function errsAllow( bytes4 errorSelector, bytes4[] memory allowedErrors, string[] memory messages - ) internal { + ) public { bool allowed = false; uint256 passIndex = 0; for (uint256 i = 0; i < allowedErrors.length; i++) { @@ -406,6 +408,6 @@ abstract contract AssertHelper { break; } } - assertWithMsg(allowed, messages[passIndex]); + t(allowed, messages[passIndex]); } } diff --git a/src/helpers/HelperBase.sol b/src/helpers/HelperBase.sol new file mode 100644 index 0000000..9cbeee3 --- /dev/null +++ b/src/helpers/HelperBase.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IPlatform} from "../platform/IPlatform.sol"; + +contract HelperBase { + IPlatform public platform; + + function setPlatform(address _platform) public { + platform = IPlatform(_platform); + } +} diff --git a/src/helpers/HelperCheats.sol b/src/helpers/HelperCheats.sol new file mode 100644 index 0000000..8553b81 --- /dev/null +++ b/src/helpers/HelperCheats.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IHevm} from "../IHevm.sol"; +import {IStdCheats} from "../IStdCheats.sol"; +import {Constants} from "../Constants.sol"; + +abstract contract HelperCheats { + IHevm internal vm = IHevm(Constants.ADDRESS_CHEATS); // echidna + IStdCheats internal mvm = IStdCheats(Constants.ADDRESS_CHEATS); // medusa + + function warp(uint256 timestamp) public { + vm.warp(timestamp); + } + + function roll(uint256 blockNumber) public { + vm.roll(blockNumber); + } + + function prank(address sender) public { + vm.prank(sender); + } +} diff --git a/src/ClampHelper.sol b/src/helpers/HelperClamp.sol similarity index 67% rename from src/ClampHelper.sol rename to src/helpers/HelperClamp.sol index b7bc419..dd64876 100644 --- a/src/ClampHelper.sol +++ b/src/helpers/HelperClamp.sol @@ -1,20 +1,90 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import "./FuzzLibString.sol"; -import "./AssertHelper.sol"; +import "../FuzzLibString.sol"; +import "./HelperAssert.sol"; /// @author Based on Crytic PropertiesHelper (https://github.com/crytic/properties/blob/main/contracts/util/PropertiesHelper.sol) -abstract contract ClampHelper is AssertHelper { +abstract contract HelperClamp is HelperAssert { event Clamped(string); + /* + ************************************************************************** + * Clamp functions with logging enabled + ************************************************************************** + */ + /// @notice Clamps value to be between low and high, both inclusive - function clampBetween( + function clamp( + uint256 value, + uint256 low, + uint256 high + ) public returns (uint256) { + return clamp(value, low, high, true); + } + + /// @notice int256 version of clamp + function clamp( + int256 value, + int256 low, + int256 high + ) public returns (int256) { + return clamp(value, low, high, true); + } + + /// @notice clamps a to be less than b + function clampLt(uint256 a, uint256 b) public returns (uint256) { + return clampLt(a, b); + } + + /// @notice int256 version of clampLt + function clampLt(int256 a, int256 b) public returns (int256) { + return clampLt(a, b, true); + } + + /// @notice clamps a to be less than or equal to b + function clampLte(uint256 a, uint256 b) public returns (uint256) { + return clampLte(a, b, true); + } + + /// @notice int256 version of clampLte + function clampLte(int256 a, int256 b) public returns (int256) { + return clampLte(a, b, true); + } + + /// @notice clamps a to be greater than b + function clampGt(uint256 a, uint256 b) public returns (uint256) { + return clampGt(a, b, true); + } + + /// @notice int256 version of clampGt + function clampGt(int256 a, int256 b) public returns (int256) { + return clampGt(a, b, true); + } + + /// @notice clamps a to be greater than or equal to b + function clampGte(uint256 a, uint256 b) public returns (uint256) { + return clampGte(a, b, true); + } + + /// @notice int256 version of clampGte + function clampGte(int256 a, int256 b) public returns (int256) { + return clampGte(a, b, true); + } + + /* + ************************************************************************** + * Clamp functions with optional logging + ************************************************************************** + */ + + /// @notice Clamps value to be between low and high, both inclusive + function clamp( uint256 value, uint256 low, uint256 high, bool enableLogs - ) internal returns (uint256) { + ) public returns (uint256) { if (value < low || value > high) { uint256 ans = low + (value % (high - low + 1)); if (enableLogs) { @@ -33,13 +103,13 @@ abstract contract ClampHelper is AssertHelper { return value; } - /// @notice int256 version of clampBetween - function clampBetween( + /// @notice int256 version of clamp + function clamp( int256 value, int256 low, int256 high, bool enableLogs - ) internal returns (int256) { + ) public returns (int256) { if (value < low || value > high) { int256 range = high - low + 1; int256 clamped = (value - low) % (range); @@ -62,9 +132,13 @@ abstract contract ClampHelper is AssertHelper { } /// @notice clamps a to be less than b - function clampLt(uint256 a, uint256 b, bool enableLogs) internal returns (uint256) { + function clampLt( + uint256 a, + uint256 b, + bool enableLogs + ) public returns (uint256) { if (!(a < b)) { - assertNeq( + neq( b, 0, "clampLt cannot clamp value a to be less than zero. Check your inputs/assumptions." @@ -87,7 +161,11 @@ abstract contract ClampHelper is AssertHelper { } /// @notice int256 version of clampLt - function clampLt(int256 a, int256 b, bool enableLogs) internal returns (int256) { + function clampLt( + int256 a, + int256 b, + bool enableLogs + ) public returns (int256) { if (!(a < b)) { int256 value = b - 1; if (enableLogs) { @@ -107,7 +185,11 @@ abstract contract ClampHelper is AssertHelper { } /// @notice clamps a to be less than or equal to b - function clampLte(uint256 a, uint256 b, bool enableLogs) internal returns (uint256) { + function clampLte( + uint256 a, + uint256 b, + bool enableLogs + ) public returns (uint256) { if (!(a <= b)) { uint256 value = a % (b + 1); if (enableLogs) { @@ -127,7 +209,11 @@ abstract contract ClampHelper is AssertHelper { } /// @notice int256 version of clampLte - function clampLte(int256 a, int256 b, bool enableLogs) internal returns (int256) { + function clampLte( + int256 a, + int256 b, + bool enableLogs + ) public returns (int256) { if (!(a <= b)) { int256 value = b; if (enableLogs) { @@ -147,9 +233,13 @@ abstract contract ClampHelper is AssertHelper { } /// @notice clamps a to be greater than b - function clampGt(uint256 a, uint256 b, bool enableLogs) internal returns (uint256) { + function clampGt( + uint256 a, + uint256 b, + bool enableLogs + ) public 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." @@ -173,7 +263,11 @@ abstract contract ClampHelper is AssertHelper { } /// @notice int256 version of clampGt - function clampGt(int256 a, int256 b, bool enableLogs) internal returns (int256) { + function clampGt( + int256 a, + int256 b, + bool enableLogs + ) public returns (int256) { if (!(a > b)) { int256 value = b + 1; if (enableLogs) { @@ -194,7 +288,11 @@ abstract contract ClampHelper is AssertHelper { } /// @notice clamps a to be greater than or equal to b - function clampGte(uint256 a, uint256 b, bool enableLogs) internal returns (uint256) { + function clampGte( + uint256 a, + uint256 b, + bool enableLogs + ) public returns (uint256) { if (!(a > b)) { uint256 value = b; if (enableLogs) { @@ -214,7 +312,11 @@ abstract contract ClampHelper is AssertHelper { } /// @notice int256 version of clampGte - function clampGte(int256 a, int256 b, bool enableLogs) internal returns (int256) { + function clampGte( + int256 a, + int256 b, + bool enableLogs + ) public returns (int256) { if (!(a > b)) { int256 value = b; if (enableLogs) { diff --git a/src/Logging.sol b/src/helpers/HelperLog.sol similarity index 81% rename from src/Logging.sol rename to src/helpers/HelperLog.sol index 6124ffc..26c6848 100644 --- a/src/Logging.sol +++ b/src/helpers/HelperLog.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -abstract contract Logging { +abstract contract HelperLog { event Log(string debugString); event LogString(string description, string data); event LogString(string prefix, string description, string data); @@ -31,11 +31,11 @@ abstract contract Logging { event AssertionFailed(string description, bool data); event AssertionFailed(string prefix, string description, bool data); - function log(string memory debugString) internal { + function log(string memory debugString) public { emit Log(debugString); } - function log(string memory description, string memory data) internal { + function log(string memory description, string memory data) public { emit LogString(description, data); } @@ -43,11 +43,11 @@ abstract contract Logging { string memory prefix, string memory description, string memory data - ) internal { + ) public { emit LogString(prefix, description, data); } - function log(string memory description, bytes memory data) internal { + function log(string memory description, bytes memory data) public { emit LogBytes(description, data); } @@ -55,11 +55,11 @@ abstract contract Logging { string memory prefix, string memory description, bytes memory data - ) internal { + ) public { emit LogBytes(prefix, description, data); } - function log(string memory description, uint256 data) internal { + function log(string memory description, uint256 data) public { emit LogUint(description, data); } @@ -67,11 +67,11 @@ abstract contract Logging { string memory prefix, string memory description, uint256 data - ) internal { + ) public { emit LogUint(prefix, description, data); } - function log(string memory description, int256 data) internal { + function log(string memory description, int256 data) public { emit LogInt(description, data); } @@ -79,11 +79,11 @@ abstract contract Logging { string memory prefix, string memory description, int256 data - ) internal { + ) public { emit LogInt(prefix, description, data); } - function log(string memory description, address data) internal { + function log(string memory description, address data) public { emit LogAddress(description, data); } @@ -91,11 +91,11 @@ abstract contract Logging { string memory prefix, string memory description, address data - ) internal { + ) public { emit LogAddress(prefix, description, data); } - function log(string memory description, bool data) internal { + function log(string memory description, bool data) public { emit LogBool(description, data); } @@ -103,19 +103,19 @@ abstract contract Logging { string memory prefix, string memory description, bool data - ) internal { + ) public { emit LogBool(prefix, description, data); } - function logFail() internal { + function logFail() public { emit AssertionFailed(); } - function logFail(string memory debugString) internal { + function logFail(string memory debugString) public { emit AssertionFailed(debugString); } - function logFail(string memory description, string memory data) internal { + function logFail(string memory description, string memory data) public { emit AssertionFailed(description, data); } @@ -123,11 +123,11 @@ abstract contract Logging { string memory prefix, string memory description, string memory data - ) internal { + ) public { emit AssertionFailed(prefix, description, data); } - function logFail(string memory description, bytes memory data) internal { + function logFail(string memory description, bytes memory data) public { emit AssertionFailed(description, data); } @@ -135,11 +135,11 @@ abstract contract Logging { string memory prefix, string memory description, bytes memory data - ) internal { + ) public { emit AssertionFailed(prefix, description, data); } - function logFail(string memory description, uint256 data) internal { + function logFail(string memory description, uint256 data) public { emit AssertionFailed(description, data); } @@ -147,11 +147,11 @@ abstract contract Logging { string memory prefix, string memory description, uint256 data - ) internal { + ) public { emit AssertionFailed(prefix, description, data); } - function logFail(string memory description, int256 data) internal { + function logFail(string memory description, int256 data) public { emit AssertionFailed(description, data); } @@ -159,11 +159,11 @@ abstract contract Logging { string memory prefix, string memory description, int256 data - ) internal { + ) public { emit AssertionFailed(prefix, description, data); } - function logFail(string memory description, address data) internal { + function logFail(string memory description, address data) public { emit AssertionFailed(description, data); } @@ -171,11 +171,11 @@ abstract contract Logging { string memory prefix, string memory description, address data - ) internal { + ) public { emit AssertionFailed(prefix, description, data); } - function logFail(string memory description, bool data) internal { + function logFail(string memory description, bool data) public { emit AssertionFailed(description, data); } @@ -183,7 +183,7 @@ abstract contract Logging { string memory prefix, string memory description, bool data - ) internal { + ) public { emit AssertionFailed(prefix, description, data); } } diff --git a/src/MathHelper.sol b/src/helpers/HelperMath.sol similarity index 56% rename from src/MathHelper.sol rename to src/helpers/HelperMath.sol index 7de0dde..1f95c15 100644 --- a/src/MathHelper.sol +++ b/src/helpers/HelperMath.sol @@ -1,30 +1,30 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -abstract contract MathHelper { - function min(uint256 a, uint256 b) internal pure returns (uint256) { +abstract contract HelperMath { + function min(uint256 a, uint256 b) public pure returns (uint256) { return a < b ? a : b; } // Forked from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.0/contracts/utils/math/SignedMath.sol - function max(int256 a, int256 b) internal pure returns (int256) { + function max(int256 a, int256 b) public pure returns (int256) { return a > b ? a : b; } // Forked with modifications from https://ethereum.stackexchange.com/a/84391 - function abs(int128 n) internal pure returns (int128) { + function abs(int128 n) public pure returns (int128) { return n >= 0 ? n : -n; } - function abs(int256 n) internal pure returns (uint256) { + function abs(int256 n) public pure returns (uint256) { return n >= 0 ? uint256(n) : uint256(-n); } - function diff(int256 a, int256 b) internal pure returns (uint256) { + function diff(int256 a, int256 b) public pure returns (uint256) { return a >= b ? uint256(a - b) : uint256(b - a); } - function diff(uint256 a, uint256 b) internal pure returns (uint256) { + function diff(uint256 a, uint256 b) public pure returns (uint256) { return a >= b ? a - b : b - a; } } diff --git a/src/RandomHelper.sol b/src/helpers/HelperRandom.sol similarity index 79% rename from src/RandomHelper.sol rename to src/helpers/HelperRandom.sol index 1bf3502..e46e5b8 100644 --- a/src/RandomHelper.sol +++ b/src/helpers/HelperRandom.sol @@ -1,10 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -abstract contract RandomHelper { +abstract contract HelperRandom { /// @notice Shuffle an array using Fisher-Yates algorithm /// @dev Based on https://gist.github.com/scammi/602387a22e04c77beb73c0ebc0f0bc18 - function shuffleArray(uint256[] memory shuffle, uint256 entropy) internal pure { + function shuffleArray( + uint256[] memory shuffle, + uint256 entropy + ) public pure { for (uint256 i = shuffle.length - 1; i > 0; i--) { uint256 swapIndex = entropy % (shuffle.length - i); diff --git a/src/platform/IPlatform.sol b/src/platform/IPlatform.sol new file mode 100644 index 0000000..157139f --- /dev/null +++ b/src/platform/IPlatform.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IPlatform { + function assertFail() pure external; +} diff --git a/src/platform/PlatformCrytic.sol b/src/platform/PlatformCrytic.sol new file mode 100644 index 0000000..50c4797 --- /dev/null +++ b/src/platform/PlatformCrytic.sol @@ -0,0 +1,11 @@ + +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IPlatform} from "./IPlatform.sol"; + +contract PlatformCrytic is IPlatform { + function assertFail() pure public override{ + assert(false); + } +} diff --git a/src/platform/PlatformEchidna.sol b/src/platform/PlatformEchidna.sol new file mode 100644 index 0000000..fec5e02 --- /dev/null +++ b/src/platform/PlatformEchidna.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {PlatformCrytic} from "./PlatformCrytic.sol"; + +contract PlatformEchidna is PlatformCrytic {} diff --git a/src/platform/PlatformMedusa.sol b/src/platform/PlatformMedusa.sol new file mode 100644 index 0000000..5d18711 --- /dev/null +++ b/src/platform/PlatformMedusa.sol @@ -0,0 +1,7 @@ + +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {PlatformCrytic} from "./PlatformCrytic.sol"; + +contract PlatformMedusa is PlatformCrytic {} diff --git a/test/Assert.t.sol b/test/Assert.t.sol new file mode 100644 index 0000000..9f23717 --- /dev/null +++ b/test/Assert.t.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "forge-std/Test.sol"; +import "forge-std/console.sol"; + +import {HelperAssert} from "../src/helpers/HelperAssert.sol"; +import {PlatformTest} from "./util/PlatformTest.sol"; + +contract TestAsserts is Test, HelperAssert { + function setUp() public { + setPlatform(address(new PlatformTest())); + } + + function test_TFail() public { + string memory reason = "Testing assertion"; + + vm.expectEmit(true, true, true, true); + emit AssertFail("Testing assertion"); + vm.expectRevert(PlatformTest.TestAssertFail.selector); + t(false, reason); + } + + function test_TSuccess() public { + string memory reason = "Testing assertion"; + t(true, reason); + } +} diff --git a/test/util/PlatformTest.sol b/test/util/PlatformTest.sol new file mode 100644 index 0000000..c27c48b --- /dev/null +++ b/test/util/PlatformTest.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IPlatform} from "../../src/platform/IPlatform.sol"; + +contract PlatformTest is IPlatform { + error TestAssertFail(); + + function assertFail() pure public override { + revert TestAssertFail(); + } +}