From 63f68da9c15fdb6ebfe43b574651e93d34140664 Mon Sep 17 00:00:00 2001 From: mriynyk Date: Mon, 22 Sep 2025 21:26:51 +0800 Subject: [PATCH] Royalty manager --- contracts/art-token/ArtToken.sol | 11 ++++- contracts/art-token/ArtTokenBase.sol | 11 +++-- .../art-token/ArtTokenRoyaltyManager.sol | 42 +++++++++++++++++++ .../ArtTokenConfigManager.sol | 2 +- .../currency-manager/CurrencyManager.sol | 2 +- .../CurrencyManagerStorage.sol | 2 +- .../currency-manager/ICurrencyManager.sol | 2 +- 7 files changed, 63 insertions(+), 9 deletions(-) create mode 100644 contracts/art-token/ArtTokenRoyaltyManager.sol diff --git a/contracts/art-token/ArtToken.sol b/contracts/art-token/ArtToken.sol index a1cff45..0a15b05 100644 --- a/contracts/art-token/ArtToken.sol +++ b/contracts/art-token/ArtToken.sol @@ -12,6 +12,7 @@ import {Roles} from "../utils/Roles.sol"; import {IAuctionHouse} from "../auction-house/IAuctionHouse.sol"; import {ArtTokenConfigManager} from "./art-token-config-manager/ArtTokenConfigManager.sol"; import {TokenMintingPermit} from "./libraries/TokenMintingPermit.sol"; +import {ArtTokenRoyaltyManager} from "./ArtTokenRoyaltyManager.sol"; import {ArtTokenBase} from "./ArtTokenBase.sol"; import {IArtToken} from "./IArtToken.sol"; @@ -22,7 +23,15 @@ import {IArtToken} from "./IArtToken.sol"; * logic, integrates EIP-712 permits and enforces optional transfer * restrictions for regulated collections. */ -contract ArtToken is IArtToken, ArtTokenBase, EIP712Domain, RoleSystem, Authorization, ArtTokenConfigManager { +contract ArtToken is + IArtToken, + ArtTokenBase, + EIP712Domain, + RoleSystem, + Authorization, + ArtTokenConfigManager, + ArtTokenRoyaltyManager +{ // TODO: need to implement method for validation mint conditions (tokenId, URI, config, etc) using SafeERC20 for IERC20; using TokenMintingPermit for TokenMintingPermit.Type; diff --git a/contracts/art-token/ArtTokenBase.sol b/contracts/art-token/ArtTokenBase.sol index 8f95dc6..9b47310 100644 --- a/contracts/art-token/ArtTokenBase.sol +++ b/contracts/art-token/ArtTokenBase.sol @@ -8,7 +8,9 @@ import { import { ERC721EnumerableUpgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721EnumerableUpgradeable.sol"; +import {IERC165} from "@openzeppelin/contracts/interfaces/IERC165.sol"; import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; +import {IERC2981} from "@openzeppelin/contracts/interfaces/IERC2981.sol"; /** * @title ArtTokenBase @@ -17,7 +19,7 @@ import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; * protocol's ArtToken contracts. Relies on OpenZeppelin upgradeable libraries and * bundles the Enumerable and URIStorage extensions in a single inheritance tree. */ -abstract contract ArtTokenBase is ERC721EnumerableUpgradeable, ERC721URIStorageUpgradeable { +abstract contract ArtTokenBase is ERC721EnumerableUpgradeable, ERC721URIStorageUpgradeable, IERC2981 { /** * @notice Initializes the token with a `name` and a `symbol`. * @@ -58,12 +60,13 @@ abstract contract ArtTokenBase is ERC721EnumerableUpgradeable, ERC721URIStorageU } /** - * @dev An override required by Solidity. + * @notice Returns true if the contract implements the interface defined by + * `interfaceId`. See the corresponding EIP-165 standard for more details. */ function supportsInterface( bytes4 interfaceId - ) public view override(ERC721EnumerableUpgradeable, ERC721URIStorageUpgradeable) returns (bool) { - return super.supportsInterface(interfaceId); + ) public view override(ERC721EnumerableUpgradeable, ERC721URIStorageUpgradeable, IERC165) returns (bool) { + return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId); } /** diff --git a/contracts/art-token/ArtTokenRoyaltyManager.sol b/contracts/art-token/ArtTokenRoyaltyManager.sol new file mode 100644 index 0000000..ff46e85 --- /dev/null +++ b/contracts/art-token/ArtTokenRoyaltyManager.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.20; + +import {IERC2981} from "@openzeppelin/contracts/interfaces/IERC2981.sol"; +import {ArtTokenConfigManager} from "./art-token-config-manager/ArtTokenConfigManager.sol"; + +/** + * @title ArtTokenRoyaltyManager + * + * @notice Abstract contract that provides a basic implementation of the EIP-2981 royalty standard. + * + * @dev This implementation calculates a fixed 5% royalty on the sale price and designates the + * original token creator as the royalty recipient. + */ +abstract contract ArtTokenRoyaltyManager is IERC2981, ArtTokenConfigManager { + /** + * @notice The royalty percentage in basis points (500 = 5%). + */ + uint256 public constant ROYALTY_PERCENT_IN_BP = 500; // 5% + + /** + * @notice One hundred percent represented in basis points (10000 = 100%). + */ + uint256 public constant ONE_HUNDRED_PERCENT_IN_BP = 10000; // 100% in basis points + + /** + * @notice Calculates the royalty payment for a token sale, returning the recipient's address and the royalty amount. + * + * @param tokenId The ID of the token for which royalty information is being requested. + * @param salePrice The price at which the token was sold. + * + * @return receiver The address that should receive the royalty payment. + * @return royaltyAmount The amount of the royalty payment. + */ + function royaltyInfo( + uint256 tokenId, + uint256 salePrice + ) external view returns (address receiver, uint256 royaltyAmount) { + receiver = _tokenCreator(tokenId); + royaltyAmount = (salePrice * ROYALTY_PERCENT_IN_BP) / ONE_HUNDRED_PERCENT_IN_BP; + } +} diff --git a/contracts/art-token/art-token-config-manager/ArtTokenConfigManager.sol b/contracts/art-token/art-token-config-manager/ArtTokenConfigManager.sol index 25e58eb..854388b 100644 --- a/contracts/art-token/art-token-config-manager/ArtTokenConfigManager.sol +++ b/contracts/art-token/art-token-config-manager/ArtTokenConfigManager.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.20; import {RoleSystem} from "../../utils/role-system/RoleSystem.sol"; diff --git a/contracts/utils/currency-manager/CurrencyManager.sol b/contracts/utils/currency-manager/CurrencyManager.sol index 6d4477e..0814f3c 100644 --- a/contracts/utils/currency-manager/CurrencyManager.sol +++ b/contracts/utils/currency-manager/CurrencyManager.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.20; import {RoleSystem} from "../role-system/RoleSystem.sol"; diff --git a/contracts/utils/currency-manager/CurrencyManagerStorage.sol b/contracts/utils/currency-manager/CurrencyManagerStorage.sol index 1539a9c..3c587e1 100644 --- a/contracts/utils/currency-manager/CurrencyManagerStorage.sol +++ b/contracts/utils/currency-manager/CurrencyManagerStorage.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.20; /** diff --git a/contracts/utils/currency-manager/ICurrencyManager.sol b/contracts/utils/currency-manager/ICurrencyManager.sol index a81653d..fc7b630 100644 --- a/contracts/utils/currency-manager/ICurrencyManager.sol +++ b/contracts/utils/currency-manager/ICurrencyManager.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.20; /**