Created
June 26, 2022 00:04
-
-
Save cygaar/e1bff789e6e6b24a3ff82b35bc565cf8 to your computer and use it in GitHub Desktop.
ERC2981Optimized.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Can be found at: https://www.diffchecker.com/lPIpRFNs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: MIT | |
// OpenZeppelin Contracts (last updated v4.6.0) (token/common/ERC2981.sol) | |
pragma solidity ^0.8.0; | |
import "../../interfaces/IERC2981.sol"; | |
import "../../utils/introspection/ERC165.sol"; | |
/** | |
* @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information. | |
* | |
* Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for | |
* specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first. | |
* | |
* Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the | |
* fee is specified in basis points by default. | |
* | |
* IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See | |
* https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to | |
* voluntarily pay royalties together with sales, but note that this standard is not yet widely supported. | |
* | |
* _Available since v4.5._ | |
*/ | |
abstract contract ERC2981 is IERC2981, ERC165 { | |
uint256 private _defaultRoyaltyInfo; | |
mapping(uint256 => uint256) private _tokenRoyaltyInfo; | |
uint256 private constant ADDRESS_MASK = (1 << 161) - 1; | |
/** | |
* @dev See {IERC165-supportsInterface}. | |
*/ | |
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) { | |
return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId); | |
} | |
/** | |
* @inheritdoc IERC2981 | |
*/ | |
function royaltyInfo(uint256 _tokenId, uint256 _salePrice) public view virtual override returns (address, uint256) { | |
uint256 packedRoyalty = _tokenRoyaltyInfo[_tokenId]; | |
address receiver = address(uint160(packedRoyalty)); | |
if (receiver == address(0)) { | |
packedRoyalty = _defaultRoyaltyInfo; | |
receiver = address(uint160(packedRoyalty)); | |
} | |
uint96 royaltyFraction = uint96(packedRoyalty >> 160); | |
uint256 royaltyAmount = (_salePrice * royaltyFraction) / _feeDenominator(); | |
return (receiver, royaltyAmount); | |
} | |
/** | |
* @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a | |
* fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an | |
* override. | |
*/ | |
function _feeDenominator() internal pure virtual returns (uint96) { | |
return 10000; | |
} | |
/** | |
* @dev Sets the royalty information that all ids in this contract will default to. | |
* | |
* Requirements: | |
* | |
* - `receiver` cannot be the zero address. | |
* - `feeNumerator` cannot be greater than the fee denominator. | |
*/ | |
function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual { | |
require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice"); | |
require(receiver != address(0), "ERC2981: invalid receiver"); | |
assembly { | |
sstore(_defaultRoyaltyInfo.slot, or(shl(160, feeNumerator), and(receiver, ADDRESS_MASK))) | |
} | |
} | |
/** | |
* @dev Removes default royalty information. | |
*/ | |
function _deleteDefaultRoyalty() internal virtual { | |
assembly { | |
sstore(_defaultRoyaltyInfo.slot, 0) | |
} | |
} | |
/** | |
* @dev Sets the royalty information for a specific token id, overriding the global default. | |
* | |
* Requirements: | |
* | |
* - `receiver` cannot be the zero address. | |
* - `feeNumerator` cannot be greater than the fee denominator. | |
*/ | |
function _setTokenRoyalty( | |
uint256 tokenId, | |
address receiver, | |
uint96 feeNumerator | |
) internal virtual { | |
require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice"); | |
require(receiver != address(0), "ERC2981: Invalid parameters"); | |
assembly { | |
mstore(0x00, tokenId) | |
mstore(0x20, _tokenRoyaltyInfo.slot) | |
let hash := keccak256(0, 0x40) | |
sstore(hash, or(shl(160, feeNumerator), and(receiver, ADDRESS_MASK))) | |
} | |
} | |
/** | |
* @dev Resets royalty information for the token id back to the global default. | |
*/ | |
function _resetTokenRoyalty(uint256 tokenId) internal virtual { | |
assembly { | |
mstore(0x00, tokenId) | |
mstore(0x20, _tokenRoyaltyInfo.slot) | |
let hash := keccak256(0, 0x40) | |
sstore(hash, 0) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment