diff --git a/contracts/token/ERC20/ERC1404.sol b/contracts/token/ERC20/ERC1404.sol new file mode 100644 index 00000000000..24eb9d2c38b --- /dev/null +++ b/contracts/token/ERC20/ERC1404.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "./ERC20.sol"; +import "./IERC1404.sol"; +import "../../utils/Strings.sol"; + +/** + * @title ERC-1404: Simple Restricted Token Standard + * @dev see https://github.com/ethereum/eips/issues/1404 + */ +abstract contract ERC1404 is ERC20, IERC1404 { + /** + * @dev Implement transfer restriction codes. Override this function to + * implement your restriction policy. + */ + function detectTransferRestriction(address /*from*/, address /*to*/, uint256 /*amount*/) public virtual override view returns (uint8) { + return uint8(0); + } + + /** + * @dev Provides error messages for each restriction codes. Override this + * function to return meaningfull revert reasons. + */ + function messageForTransferRestriction(uint8 restrictionCode) public virtual override view returns (string memory) { + return string(abi.encodePacked("ERC1404: Transfer restriction with code ", Strings.toString(uint256(restrictionCode)))); + } + + /** + * @dev See {ERC20-_beforeTokenTransfer}. + * + * Requirements: + * + * - transfer must abide by the transfer restriction rules. + */ + function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override { + uint8 restrictionCode = detectTransferRestriction(from, to, amount); + if (restrictionCode != uint8(0)) { + revert(messageForTransferRestriction(restrictionCode)); + } + super._beforeTokenTransfer(from, to, amount); + } +} diff --git a/contracts/token/ERC20/IERC1404.sol b/contracts/token/ERC20/IERC1404.sol new file mode 100644 index 00000000000..50665fe22a6 --- /dev/null +++ b/contracts/token/ERC20/IERC1404.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT + +pragma solidity >=0.6.0 <0.9.0; + +import "./IERC20.sol"; + +/** + * @dev Interface of the ERC1404 standard as defined in the EIP. + */ +interface IERC1404 is IERC20 { + function detectTransferRestriction(address from, address to, uint256 amount) external view returns (uint8); + function messageForTransferRestriction(uint8 restrictionCode) external view returns (string memory); +}