From c9955286b5bdcc6fe6c4a59a77fe1d412564cd2a Mon Sep 17 00:00:00 2001 From: Michael De Luca <35537333+deluca-mike@users.noreply.github.com> Date: Wed, 30 Oct 2024 15:01:48 -0400 Subject: [PATCH] feat: IndexingMath, Proxy, Migratable (#38) --- src/ERC20Extended.sol | 2 +- src/ERC3009.sol | 2 +- src/ERC712Extended.sol | 2 +- src/Migratable.sol | 61 +++++++++++++ src/Proxy.sol | 48 ++++++++++ src/StatefulERC712.sol | 2 +- src/interfaces/IERC1271.sol | 2 +- src/interfaces/IERC20.sol | 2 +- src/interfaces/IERC20Extended.sol | 2 +- src/interfaces/IERC3009.sol | 2 +- src/interfaces/IERC712.sol | 2 +- src/interfaces/IERC712Extended.sol | 2 +- src/interfaces/IMigratable.sol | 44 ++++++++++ src/interfaces/IStatefulERC712.sol | 2 +- src/libs/Bytes32String.sol | 2 +- src/libs/ContractHelper.sol | 42 +++++++-- src/libs/IndexingMath.sol | 97 +++++++++++++++++++++ src/libs/SignatureChecker.sol | 2 +- src/libs/UIntMath.sol | 2 +- test/Bytes32String.sol | 2 +- test/ContractHelper.t.sol | 2 +- test/ERC20Extended.t.sol | 2 +- test/ERC3009.t.sol | 2 +- test/ERC712Extended.t.sol | 2 +- test/SignatureChecker.t.sol | 2 +- test/UIntMath.t.sol | 2 +- test/invariant/ERC20ExtendedInvariant.t.sol | 2 +- test/utils/Bytes32StringHarness.sol | 2 +- test/utils/ContractHelperHarness.sol | 2 +- test/utils/ERC1271WalletMock.sol | 2 +- test/utils/ERC20ExtendedHarness.sol | 2 +- test/utils/ERC712ExtendedHarness.sol | 2 +- test/utils/SignatureCheckerHarness.sol | 2 +- test/utils/TestUtils.t.sol | 2 +- test/utils/UIntMathHarness.sol | 2 +- 35 files changed, 313 insertions(+), 39 deletions(-) create mode 100644 src/Migratable.sol create mode 100644 src/Proxy.sol create mode 100644 src/interfaces/IMigratable.sol create mode 100644 src/libs/IndexingMath.sol diff --git a/src/ERC20Extended.sol b/src/ERC20Extended.sol index 84cdaa8..ac770a9 100644 --- a/src/ERC20Extended.sol +++ b/src/ERC20Extended.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; import { IERC20 } from "./interfaces/IERC20.sol"; import { IERC20Extended } from "./interfaces/IERC20Extended.sol"; diff --git a/src/ERC3009.sol b/src/ERC3009.sol index 0b84200..7bbb064 100644 --- a/src/ERC3009.sol +++ b/src/ERC3009.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; import { IERC3009 } from "./interfaces/IERC3009.sol"; diff --git a/src/ERC712Extended.sol b/src/ERC712Extended.sol index d4eee0d..d450004 100644 --- a/src/ERC712Extended.sol +++ b/src/ERC712Extended.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; import { IERC712 } from "./interfaces/IERC712.sol"; import { IERC712Extended } from "./interfaces/IERC712Extended.sol"; diff --git a/src/Migratable.sol b/src/Migratable.sol new file mode 100644 index 0000000..9faf832 --- /dev/null +++ b/src/Migratable.sol @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity >=0.8.20 <0.9.0; + +import { IMigratable } from "./interfaces/IMigratable.sol"; + +/** + * @title Abstract implementation for exposing the ability to migrate a contract, extending ERC-1967. + * @author M^0 Labs + */ +abstract contract Migratable is IMigratable { + /* ============ Variables ============ */ + + /// @dev Storage slot with the address of the current factory. `keccak256('eip1967.proxy.implementation') - 1`. + uint256 private constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + + /* ============ Interactive Functions ============ */ + + /// @inheritdoc IMigratable + function migrate() external { + _migrate(_getMigrator()); + } + + /* ============ View/Pure Functions ============ */ + + /// @inheritdoc IMigratable + function implementation() public view returns (address implementation_) { + assembly { + implementation_ := sload(_IMPLEMENTATION_SLOT) + } + } + + /* ============ Internal Interactive Functions ============ */ + + /** + * @dev Performs an arbitrary migration by delegate-calling `migrator_`. + * @param migrator_ The address of a migrator contract. + */ + function _migrate(address migrator_) internal { + if (migrator_ == address(0)) revert ZeroMigrator(); + + if (migrator_.code.length == 0) revert InvalidMigrator(); + + address oldImplementation_ = implementation(); + + (bool success_, ) = migrator_.delegatecall(""); + if (!success_) revert MigrationFailed(); + + address newImplementation_ = implementation(); + + emit Migrated(migrator_, oldImplementation_, newImplementation_); + + // NOTE: Redundant event emitted to conform to the EIP-1967 standard. + emit Upgraded(newImplementation_); + } + + /* ============ Internal View/Pure Functions ============ */ + + /// @dev Returns the address of a migrator contract. + function _getMigrator() internal view virtual returns (address); +} diff --git a/src/Proxy.sol b/src/Proxy.sol new file mode 100644 index 0000000..d61457e --- /dev/null +++ b/src/Proxy.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity >=0.8.20 <0.9.0; + +/** + * @title Minimal transparent proxy. + * @author M^0 Labs + */ +contract Proxy { + /// @dev Storage slot with the address of the current factory. `keccak256('eip1967.proxy.implementation') - 1`. + uint256 private constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + + /** + * @dev Constructs the contract given the address of some implementation. + * @param implementation_ The address of some implementation. + */ + constructor(address implementation_) { + if (implementation_ == address(0)) revert(); + + assembly { + sstore(_IMPLEMENTATION_SLOT, implementation_) + } + } + + fallback() external payable virtual { + bytes32 implementation_; + + assembly { + implementation_ := sload(_IMPLEMENTATION_SLOT) + } + + assembly { + calldatacopy(0, 0, calldatasize()) + + let result_ := delegatecall(gas(), implementation_, 0, calldatasize(), 0, 0) + + returndatacopy(0, 0, returndatasize()) + + switch result_ + case 0 { + revert(0, returndatasize()) + } + default { + return(0, returndatasize()) + } + } + } +} diff --git a/src/StatefulERC712.sol b/src/StatefulERC712.sol index 39f43b8..a824e63 100644 --- a/src/StatefulERC712.sol +++ b/src/StatefulERC712.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; import { IStatefulERC712 } from "./interfaces/IStatefulERC712.sol"; diff --git a/src/interfaces/IERC1271.sol b/src/interfaces/IERC1271.sol index ef30f9b..e47ad8c 100644 --- a/src/interfaces/IERC1271.sol +++ b/src/interfaces/IERC1271.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; /** * @title Standard Signature Validation Method for Contracts via EIP-1271. diff --git a/src/interfaces/IERC20.sol b/src/interfaces/IERC20.sol index 9231189..6ff6685 100644 --- a/src/interfaces/IERC20.sol +++ b/src/interfaces/IERC20.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; /** * @title ERC20 Token Standard. diff --git a/src/interfaces/IERC20Extended.sol b/src/interfaces/IERC20Extended.sol index ef701c7..f9716b8 100644 --- a/src/interfaces/IERC20Extended.sol +++ b/src/interfaces/IERC20Extended.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; import { IERC20 } from "./IERC20.sol"; import { IERC3009 } from "./IERC3009.sol"; diff --git a/src/interfaces/IERC3009.sol b/src/interfaces/IERC3009.sol index 6dd564b..cc71f81 100644 --- a/src/interfaces/IERC3009.sol +++ b/src/interfaces/IERC3009.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; import { IStatefulERC712 } from "./IStatefulERC712.sol"; diff --git a/src/interfaces/IERC712.sol b/src/interfaces/IERC712.sol index 35474d9..688b8e3 100644 --- a/src/interfaces/IERC712.sol +++ b/src/interfaces/IERC712.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; /** * @title Typed structured data hashing and signing via EIP-712. diff --git a/src/interfaces/IERC712Extended.sol b/src/interfaces/IERC712Extended.sol index 4774e2e..2259c28 100644 --- a/src/interfaces/IERC712Extended.sol +++ b/src/interfaces/IERC712Extended.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; import { IERC712 } from "./IERC712.sol"; diff --git a/src/interfaces/IMigratable.sol b/src/interfaces/IMigratable.sol new file mode 100644 index 0000000..52b0057 --- /dev/null +++ b/src/interfaces/IMigratable.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity >=0.8.20 <0.9.0; + +/** + * @title Interface for exposing the ability to migrate a contract, extending the ERC-1967 interface. + * @author M^0 Labs + */ +interface IMigratable { + /* ============ Events ============ */ + + /** + * @notice Emitted when a migration to a new implementation is performed. + * @param migrator The address that performed the migration. + * @param oldImplementation The address of the old implementation. + * @param newImplementation The address of the new implementation. + */ + event Migrated(address indexed migrator, address indexed oldImplementation, address indexed newImplementation); + + /** + * @notice Emitted when the implementation address for the proxy is changed. + * @param implementation The address of the new implementation for the proxy. + */ + event Upgraded(address indexed implementation); + + /// @notice Emitted when calling `stopEarning` for an account approved as earner by the Registrar. + error InvalidMigrator(); + + /// @notice Emitted when the delegatecall to a migrator fails. + error MigrationFailed(); + + /// @notice Emitted when the zero address is passed as a migrator. + error ZeroMigrator(); + + /* ============ Interactive Functions ============ */ + + /// @notice Performs an arbitrarily defined migration. + function migrate() external; + + /* ============ View/Pure Functions ============ */ + + /// @notice Returns the address of the current implementation contract. + function implementation() external view returns (address); +} diff --git a/src/interfaces/IStatefulERC712.sol b/src/interfaces/IStatefulERC712.sol index 9ab0d63..fd346be 100644 --- a/src/interfaces/IStatefulERC712.sol +++ b/src/interfaces/IStatefulERC712.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; import { IERC712Extended } from "./IERC712Extended.sol"; diff --git a/src/libs/Bytes32String.sol b/src/libs/Bytes32String.sol index 15d2b46..a36db9e 100644 --- a/src/libs/Bytes32String.sol +++ b/src/libs/Bytes32String.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; /** * @title A library to convert between string and bytes32 (assuming 32 characters or less). diff --git a/src/libs/ContractHelper.sol b/src/libs/ContractHelper.sol index 9e05597..73f3a44 100644 --- a/src/libs/ContractHelper.sol +++ b/src/libs/ContractHelper.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; // solhint-disable max-line-length @@ -35,14 +35,38 @@ library ContractHelper { nonce_ == 0x00 ? abi.encodePacked(bytes1(0xd6), bytes1(0x94), account_, bytes1(0x80)) : nonce_ <= 0x7f - ? abi.encodePacked(bytes1(0xd6), bytes1(0x94), account_, uint8(nonce_)) - : nonce_ <= 0xff - ? abi.encodePacked(bytes1(0xd7), bytes1(0x94), account_, bytes1(0x81), uint8(nonce_)) - : nonce_ <= 0xffff - ? abi.encodePacked(bytes1(0xd8), bytes1(0x94), account_, bytes1(0x82), uint16(nonce_)) - : nonce_ <= 0xffffff - ? abi.encodePacked(bytes1(0xd9), bytes1(0x94), account_, bytes1(0x83), uint24(nonce_)) - : abi.encodePacked(bytes1(0xda), bytes1(0x94), account_, bytes1(0x84), uint32(nonce_)) + ? abi.encodePacked(bytes1(0xd6), bytes1(0x94), account_, uint8(nonce_)) + : nonce_ <= 0xff + ? abi.encodePacked( + bytes1(0xd7), + bytes1(0x94), + account_, + bytes1(0x81), + uint8(nonce_) + ) + : nonce_ <= 0xffff + ? abi.encodePacked( + bytes1(0xd8), + bytes1(0x94), + account_, + bytes1(0x82), + uint16(nonce_) + ) + : nonce_ <= 0xffffff + ? abi.encodePacked( + bytes1(0xd9), + bytes1(0x94), + account_, + bytes1(0x83), + uint24(nonce_) + ) + : abi.encodePacked( + bytes1(0xda), + bytes1(0x94), + account_, + bytes1(0x84), + uint32(nonce_) + ) ) ) ) diff --git a/src/libs/IndexingMath.sol b/src/libs/IndexingMath.sol new file mode 100644 index 0000000..cb17bce --- /dev/null +++ b/src/libs/IndexingMath.sol @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity >=0.8.20 <0.9.0; + +import { UIntMath } from "./UIntMath.sol"; + +/** + * @title Helper library for indexing math functions. + * @author M^0 Labs + */ +library IndexingMath { + /* ============ Variables ============ */ + + /// @notice The scaling of indexes for exponent math. + uint56 internal constant EXP_SCALED_ONE = 1e12; + + /* ============ Custom Errors ============ */ + + /// @notice Emitted when a division by zero occurs. + error DivisionByZero(); + + /* ============ Internal View/Pure Functions ============ */ + + /** + * @notice Helper function to calculate `(x * EXP_SCALED_ONE) / y`, rounded down. + * @dev Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol) + */ + function divide240By128Down(uint240 x_, uint128 y_) internal pure returns (uint112) { + if (y_ == 0) revert DivisionByZero(); + + unchecked { + // NOTE: While `uint256(x) * EXP_SCALED_ONE` can technically overflow, these divide/multiply functions are + // only used for the purpose of principal/present amount calculations for continuous indexing, and + // so for an `x` to be large enough to overflow this, it would have to be a possible result of + // `multiply112By128Down` or `multiply112By128Up`, which would already satisfy + // `uint256(x) * EXP_SCALED_ONE < type(uint240).max`. + return UIntMath.safe112((uint256(x_) * EXP_SCALED_ONE) / y_); + } + } + + /** + * @notice Helper function to calculate `(x * EXP_SCALED_ONE) / y`, rounded up. + * @dev Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol) + */ + function divide240By128Up(uint240 x_, uint128 y_) internal pure returns (uint112) { + if (y_ == 0) revert DivisionByZero(); + + unchecked { + // NOTE: While `uint256(x) * EXP_SCALED_ONE` can technically overflow, these divide/multiply functions are + // only used for the purpose of principal/present amount calculations for continuous indexing, and + // so for an `x` to be large enough to overflow this, it would have to be a possible result of + // `multiply112By128Down` or `multiply112By128Up`, which would already satisfy + // `uint256(x) * EXP_SCALED_ONE < type(uint240).max`. + return UIntMath.safe112(((uint256(x_) * EXP_SCALED_ONE) + y_ - 1) / y_); + } + } + + /** + * @notice Helper function to calculate `(x * y) / EXP_SCALED_ONE`, rounded down. + * @dev Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol) + */ + function multiply112By128Down(uint112 x_, uint128 y_) internal pure returns (uint240) { + unchecked { + return uint240((uint256(x_) * y_) / EXP_SCALED_ONE); + } + } + + /** + * @dev Returns the present amount (rounded down) given the principal amount and an index. + * @param principalAmount_ The principal amount. + * @param index_ An index. + * @return The present amount rounded down. + */ + function getPresentAmountRoundedDown(uint112 principalAmount_, uint128 index_) internal pure returns (uint240) { + return multiply112By128Down(principalAmount_, index_); + } + + /** + * @dev Returns the principal amount given the present amount, using the current index. + * @param presentAmount_ The present amount. + * @param index_ An index. + * @return The principal amount rounded down. + */ + function getPrincipalAmountRoundedDown(uint240 presentAmount_, uint128 index_) internal pure returns (uint112) { + return divide240By128Down(presentAmount_, index_); + } + + /** + * @dev Returns the principal amount given the present amount, using the current index. + * @param presentAmount_ The present amount. + * @param index_ An index. + * @return The principal amount rounded up. + */ + function getPrincipalAmountRoundedUp(uint240 presentAmount_, uint128 index_) internal pure returns (uint112) { + return divide240By128Up(presentAmount_, index_); + } +} diff --git a/src/libs/SignatureChecker.sol b/src/libs/SignatureChecker.sol index 6d2e1ab..1b45c62 100644 --- a/src/libs/SignatureChecker.sol +++ b/src/libs/SignatureChecker.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; import { IERC1271 } from "../interfaces/IERC1271.sol"; diff --git a/src/libs/UIntMath.sol b/src/libs/UIntMath.sol index 5dd8ea0..49921db 100644 --- a/src/libs/UIntMath.sol +++ b/src/libs/UIntMath.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; /** * @title Library to perform safe math operations on uint types diff --git a/test/Bytes32String.sol b/test/Bytes32String.sol index c6ed22d..9441362 100644 --- a/test/Bytes32String.sol +++ b/test/Bytes32String.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; import { Test } from "../lib/forge-std/src/Test.sol"; diff --git a/test/ContractHelper.t.sol b/test/ContractHelper.t.sol index 6865a11..0cf4d56 100644 --- a/test/ContractHelper.t.sol +++ b/test/ContractHelper.t.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; import { Test } from "../lib/forge-std/src/Test.sol"; diff --git a/test/ERC20Extended.t.sol b/test/ERC20Extended.t.sol index c69c174..01d6565 100644 --- a/test/ERC20Extended.t.sol +++ b/test/ERC20Extended.t.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; import { IERC20 } from "../src/interfaces/IERC20.sol"; import { IERC20Extended } from "../src/interfaces/IERC20Extended.sol"; diff --git a/test/ERC3009.t.sol b/test/ERC3009.t.sol index 848121d..e9f3002 100644 --- a/test/ERC3009.t.sol +++ b/test/ERC3009.t.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; import { IERC3009 } from "../src/interfaces/IERC3009.sol"; import { IERC712 } from "../src/interfaces/IERC712.sol"; diff --git a/test/ERC712Extended.t.sol b/test/ERC712Extended.t.sol index 48448ff..6c5fd36 100644 --- a/test/ERC712Extended.t.sol +++ b/test/ERC712Extended.t.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; import { TestUtils } from "./utils/TestUtils.t.sol"; diff --git a/test/SignatureChecker.t.sol b/test/SignatureChecker.t.sol index eb5b7b4..01bd62f 100644 --- a/test/SignatureChecker.t.sol +++ b/test/SignatureChecker.t.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; import { TestUtils } from "./utils/TestUtils.t.sol"; diff --git a/test/UIntMath.t.sol b/test/UIntMath.t.sol index f32b14f..de5fac1 100644 --- a/test/UIntMath.t.sol +++ b/test/UIntMath.t.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; import { Test } from "../lib/forge-std/src/Test.sol"; diff --git a/test/invariant/ERC20ExtendedInvariant.t.sol b/test/invariant/ERC20ExtendedInvariant.t.sol index c42b2de..74eb3ce 100644 --- a/test/invariant/ERC20ExtendedInvariant.t.sol +++ b/test/invariant/ERC20ExtendedInvariant.t.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; import { CommonBase } from "../../lib/forge-std/src/Base.sol"; import { StdCheats } from "../../lib/forge-std/src/StdCheats.sol"; diff --git a/test/utils/Bytes32StringHarness.sol b/test/utils/Bytes32StringHarness.sol index b86171b..fa988a6 100644 --- a/test/utils/Bytes32StringHarness.sol +++ b/test/utils/Bytes32StringHarness.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; import { Bytes32String } from "../../src/libs/Bytes32String.sol"; diff --git a/test/utils/ContractHelperHarness.sol b/test/utils/ContractHelperHarness.sol index a1e1b21..613614d 100644 --- a/test/utils/ContractHelperHarness.sol +++ b/test/utils/ContractHelperHarness.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; import { ContractHelper } from "../../src/libs/ContractHelper.sol"; diff --git a/test/utils/ERC1271WalletMock.sol b/test/utils/ERC1271WalletMock.sol index 382f48d..700692d 100644 --- a/test/utils/ERC1271WalletMock.sol +++ b/test/utils/ERC1271WalletMock.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; import { IERC1271 } from "../../src/interfaces/IERC1271.sol"; import { SignatureChecker } from "../../src/libs/SignatureChecker.sol"; diff --git a/test/utils/ERC20ExtendedHarness.sol b/test/utils/ERC20ExtendedHarness.sol index 4a3e752..920b409 100644 --- a/test/utils/ERC20ExtendedHarness.sol +++ b/test/utils/ERC20ExtendedHarness.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; import { ERC20Extended } from "../../src/ERC20Extended.sol"; diff --git a/test/utils/ERC712ExtendedHarness.sol b/test/utils/ERC712ExtendedHarness.sol index cce5274..54f8a8b 100644 --- a/test/utils/ERC712ExtendedHarness.sol +++ b/test/utils/ERC712ExtendedHarness.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; import { ERC712Extended } from "../../src/ERC712Extended.sol"; diff --git a/test/utils/SignatureCheckerHarness.sol b/test/utils/SignatureCheckerHarness.sol index cbb0c18..3d31b6f 100644 --- a/test/utils/SignatureCheckerHarness.sol +++ b/test/utils/SignatureCheckerHarness.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; import { SignatureChecker } from "../../src/libs/SignatureChecker.sol"; diff --git a/test/utils/TestUtils.t.sol b/test/utils/TestUtils.t.sol index 62ad529..e5c9841 100644 --- a/test/utils/TestUtils.t.sol +++ b/test/utils/TestUtils.t.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; import { Test } from "../../lib/forge-std/src/Test.sol"; diff --git a/test/utils/UIntMathHarness.sol b/test/utils/UIntMathHarness.sol index 1c8970a..b34abb8 100644 --- a/test/utils/UIntMathHarness.sol +++ b/test/utils/UIntMathHarness.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.26; +pragma solidity >=0.8.20 <0.9.0; import { UIntMath } from "../../src/libs/UIntMath.sol";