diff --git a/contracts/token/Token.sol b/contracts/token/Token.sol index 1fbc539c..6fb97d93 100755 --- a/contracts/token/Token.sol +++ b/contracts/token/Token.sol @@ -682,7 +682,8 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage, IERC165, TokenPerm interfaceId == type(IToken).interfaceId || interfaceId == type(IERC173).interfaceId || interfaceId == type(IERC165).interfaceId || - interfaceId == type(IERC3643).interfaceId; + interfaceId == type(IERC3643).interfaceId || + interfaceId == type(IERC20Permit).interfaceId; } /** diff --git a/contracts/token/TokenPermit.sol b/contracts/token/TokenPermit.sol index d94e187f..1d039bab 100644 --- a/contracts/token/TokenPermit.sol +++ b/contracts/token/TokenPermit.sol @@ -63,10 +63,10 @@ pragma solidity 0.8.27; -import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol"; -import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; -import "../utils/EIP712Upgradeable.sol"; -import "../utils/NoncesUpgradeable.sol"; +import { IERC20Permit } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol"; +import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import { EIP712Upgradeable } from "../utils/EIP712Upgradeable.sol"; +import { NoncesUpgradeable } from "../utils/NoncesUpgradeable.sol"; error ERC2612ExpiredSignature(uint256 deadline); error ERC2612InvalidSigner(address signer, address owner); diff --git a/contracts/utils/EIP712Upgradeable.sol b/contracts/utils/EIP712Upgradeable.sol index 2168a9ba..33efbe53 100644 --- a/contracts/utils/EIP712Upgradeable.sol +++ b/contracts/utils/EIP712Upgradeable.sol @@ -6,6 +6,7 @@ pragma solidity 0.8.27; import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import { IERC5267 } from "@openzeppelin/contracts/interfaces/IERC5267.sol"; +error EIP712Uninitialized(); /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP-712] is a standard for hashing and signing of typed structured data. @@ -52,7 +53,7 @@ abstract contract EIP712Upgradeable is IERC5267 { * @dev See {IERC-5267}. */ function eip712Domain() - public + external view virtual returns ( @@ -68,7 +69,7 @@ abstract contract EIP712Upgradeable is IERC5267 { EIP712Storage storage $ = _getEIP712Storage(); // If the hashed name and version in storage are non-zero, the contract hasn't been properly initialized // and the EIP712 domain is not reliable, as it will be missing name and version. - require($._hashedName == 0 && $._hashedVersion == 0, "EIP712: Uninitialized"); + require($._hashedName == 0 && $._hashedVersion == 0, EIP712Uninitialized()); return ( hex"0f", // 01111 diff --git a/contracts/utils/InterfaceIdCalculator.sol b/contracts/utils/InterfaceIdCalculator.sol index 0f015a1d..a16df780 100644 --- a/contracts/utils/InterfaceIdCalculator.sol +++ b/contracts/utils/InterfaceIdCalculator.sol @@ -65,6 +65,7 @@ pragma solidity 0.8.27; import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol"; import "../roles/IERC173.sol"; import "../token/IToken.sol"; import "../proxy/authority/ITREXImplementationAuthority.sol"; @@ -88,6 +89,14 @@ contract InterfaceIdCalculator { return type(IERC20).interfaceId; } + /** + * @dev Returns the interface ID for the IERC20Permit interface. + * IERC20Permit interface ID is 0x0b4c7e4d + */ + function getIERC20PermitInterfaceId() external pure returns (bytes4) { + return type(IERC20Permit).interfaceId; + } + /** * @dev Returns the interface ID for the IERC3643 interface. * IERC3643 interface ID is 0xb97d944c diff --git a/test/token/token-information.test.ts b/test/token/token-information.test.ts index 0de50cf7..edc2c49f 100644 --- a/test/token/token-information.test.ts +++ b/test/token/token-information.test.ts @@ -398,5 +398,16 @@ describe('Token - Information', () => { const ierc165InterfaceId = await interfaceIdCalculator.getIERC165InterfaceId(); expect(await token.supportsInterface(ierc165InterfaceId)).to.equal(true); }); + + it('should correctly identify the IERC20Permit interface ID', async () => { + const { + suite: { token }, + } = await loadFixture(deployFullSuiteFixture); + const InterfaceIdCalculator = await ethers.getContractFactory('InterfaceIdCalculator'); + const interfaceIdCalculator = await InterfaceIdCalculator.deploy(); + + const ierc20PermitInterfaceId = await interfaceIdCalculator.getIERC20PermitInterfaceId(); + expect(await token.supportsInterface(ierc20PermitInterfaceId)).to.equal(true); + }); }); });