Skip to content

Commit

Permalink
Adding support to EIP-2981
Browse files Browse the repository at this point in the history
  • Loading branch information
aaitor committed Jan 13, 2022
1 parent ba7f7c7 commit 04a0d0c
Show file tree
Hide file tree
Showing 7 changed files with 164 additions and 13 deletions.
6 changes: 5 additions & 1 deletion contracts/registry/DIDRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,9 @@ contract DIDRegistry is DIDFactory {
returns (bool success)
{
didRegisterList.initializeNftConfig(_did, _cap, _royalties);


erc1155.setTokenRoyalty(uint256(_did), msg.sender, _royalties);

if (_mint) {
mint(_did, _cap);
}
Expand All @@ -167,6 +169,8 @@ contract DIDRegistry is DIDFactory {
{
didRegisterList.initializeNft721Config(_did, _royalties);

erc721.setTokenRoyalty(uint256(_did), msg.sender, _royalties);

if (_mint) {
mint721(_did);
}
Expand Down
2 changes: 1 addition & 1 deletion contracts/registry/DIDRegistryLibrary.sol
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ library DIDRegistryLibrary {

require(!_self.didRegisters[_did].nftInitialized, 'NFT already initialized');

require(_royalties < 100, 'Invalid royalties number');
require(_royalties <= 100, 'Invalid royalties number');
require(_royalties >= _self.didRegisters[_did].royalties, 'Cannot decrease royalties');

_self.didRegisters[_did].mintCap = _cap;
Expand Down
36 changes: 31 additions & 5 deletions contracts/token/erc1155/NFTUpgradeable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,18 @@ pragma solidity ^0.8.0;
import '@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol';
import '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol';
import '@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol';
import "../erc2981/ERC2981.sol";

/**
*
* @dev Implementation of the basic standard multi-token.
* See https://eips.ethereum.org/EIPS/eip-1155
*/
contract NFTUpgradeable is ERC1155Upgradeable, OwnableUpgradeable, AccessControlUpgradeable {
contract NFTUpgradeable is ERC1155Upgradeable, ERC2981, OwnableUpgradeable, AccessControlUpgradeable {

// Mapping from account to proxy approvals
mapping (address => bool) private _proxyApprovals;

bytes32 public constant MINTER_ROLE = keccak256('MINTER_ROLE');

/**
Expand All @@ -35,7 +36,6 @@ contract NFTUpgradeable is ERC1155Upgradeable, OwnableUpgradeable, AccessControl
AccessControlUpgradeable.__AccessControl_init();
AccessControlUpgradeable._setupRole(MINTER_ROLE, msg.sender);
}


function setProxyApproval(address operator, bool approved) public onlyOwner virtual {
_proxyApprovals[operator] = approved;
Expand Down Expand Up @@ -63,9 +63,35 @@ contract NFTUpgradeable is ERC1155Upgradeable, OwnableUpgradeable, AccessControl
AccessControlUpgradeable._setupRole(MINTER_ROLE, account);
}

function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControlUpgradeable, ERC1155Upgradeable) returns (bool) {
/**
* @dev Record the asset royalties
* @param tokenId the id of the asset with the royalties associated
* @param receiver the receiver of the royalties (the original creator)
* @param royaltyAmount percentage (no decimals, between 0 and 100)
*/
function setTokenRoyalty(
uint256 tokenId,
address receiver,
uint256 royaltyAmount
)
public
{
require(hasRole(MINTER_ROLE, msg.sender), 'only minter');
_setTokenRoyalty(tokenId, receiver, royaltyAmount);
}

function supportsInterface(
bytes4 interfaceId
)
public
view
virtual
override(AccessControlUpgradeable, ERC1155Upgradeable, ERC2981)
returns (bool)
{
return AccessControlUpgradeable.supportsInterface(interfaceId)
|| ERC1155Upgradeable.supportsInterface(interfaceId);
|| ERC1155Upgradeable.supportsInterface(interfaceId)
|| ERC2981.supportsInterface(interfaceId);
}

}
63 changes: 63 additions & 0 deletions contracts/token/erc2981/ERC2981.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
pragma solidity ^0.8.0;
// Copyright 2020 Keyko GmbH.
// SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
// Code is Apache-2.0 and docs are CC-BY-4.0

import '@openzeppelin/contracts-upgradeable/interfaces/IERC2981Upgradeable.sol';

/**
*
* @dev Implementation of the Royalties EIP-2981 base contract
* See https://eips.ethereum.org/EIPS/eip-2981
*/
abstract contract ERC2981 is IERC2981Upgradeable {

struct RoyaltyInfo {
address receiver;
uint256 royaltyAmount;
}

// Mapping of Royalties per tokenId (DID)
mapping(uint256 => RoyaltyInfo) internal _royalties;

function supportsInterface(bytes4 interfaceId)
public
view
virtual
override
returns (bool)
{
return
interfaceId == type(IERC2981Upgradeable).interfaceId ||
supportsInterface(interfaceId);
}

function _setTokenRoyalty(
uint256 tokenId,
address receiver,
uint256 royaltyAmount
)
internal
{
require(royaltyAmount <= 100, 'ERC2981Royalties: Too high');
_royalties[tokenId] = RoyaltyInfo(receiver, royaltyAmount);
}

/**
* @inheritdoc IERC2981Upgradeable
*/
function royaltyInfo(
uint256 tokenId,
uint256 value
)
external
view
override
returns (address receiver, uint256 royaltyAmount)
{
RoyaltyInfo memory royalties = _royalties[tokenId];
receiver = royalties.receiver;
royaltyAmount = (value * royalties.royaltyAmount) / 100;
}

}
39 changes: 33 additions & 6 deletions contracts/token/erc721/NFT721Upgradeable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ pragma solidity ^0.8.0;
import '@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol';
import '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol';
import '@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol';
import "../erc2981/ERC2981.sol";

/**
*
* @dev Implementation of the basic standard multi-token.
*/
contract NFT721Upgradeable is ERC721Upgradeable, OwnableUpgradeable, AccessControlUpgradeable {
contract NFT721Upgradeable is ERC721Upgradeable, ERC2981, OwnableUpgradeable, AccessControlUpgradeable {

// Mapping from account to proxy approvals
mapping (address => bool) private _proxyApprovals;
Expand Down Expand Up @@ -47,7 +48,11 @@ contract NFT721Upgradeable is ERC721Upgradeable, OwnableUpgradeable, AccessContr
function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {
return super.isApprovedForAll(account, operator) || _proxyApprovals[operator];
}


function addMinter(address account) public onlyOwner {
AccessControlUpgradeable._setupRole(MINTER_ROLE, account);
}

function mint(address to, uint256 id) public {
require(hasRole(MINTER_ROLE, msg.sender), 'only minter can mint');
_mint(to, id);
Expand All @@ -58,13 +63,35 @@ contract NFT721Upgradeable is ERC721Upgradeable, OwnableUpgradeable, AccessContr
_burn(id);
}

function addMinter(address account) public onlyOwner {
AccessControlUpgradeable._setupRole(MINTER_ROLE, account);
/**
* @dev Record the asset royalties
* @param tokenId the id of the asset with the royalties associated
* @param receiver the receiver of the royalties (the original creator)
* @param royaltyAmount percentage (no decimals, between 0 and 100)
*/
function setTokenRoyalty(
uint256 tokenId,
address receiver,
uint256 royaltyAmount
)
public
{
require(hasRole(MINTER_ROLE, msg.sender), 'only minter');
_setTokenRoyalty(tokenId, receiver, royaltyAmount);
}

function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControlUpgradeable, ERC721Upgradeable) returns (bool) {
function supportsInterface(
bytes4 interfaceId
)
public
view
virtual
override(AccessControlUpgradeable, ERC721Upgradeable, ERC2981)
returns (bool)
{
return AccessControlUpgradeable.supportsInterface(interfaceId)
|| ERC721Upgradeable.supportsInterface(interfaceId);
|| ERC721Upgradeable.supportsInterface(interfaceId)
|| ERC2981.supportsInterface(interfaceId);
}

}
17 changes: 17 additions & 0 deletions test/unit/registry/Mintable721DIDRegistry.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,23 @@ contract('Mintable DIDRegistry (ERC-721)', (accounts) => {
await assert.isRejected(nft.ownerOf(did))
})

it('The royalties should be initialized and retrieved (ERC-2981)', async () => {
const didSeed = testUtils.generateId()
const did = await didRegistry.hashDID(didSeed, owner)
const checksum = testUtils.generateId()
await didRegistry.registerAttribute(
didSeed, checksum, [], value, { from: owner })

await didRegistry.enableAndMintDidNft721(did, 10, true, { from: owner })

const nftOwner = await nft.ownerOf(did)
assert.strictEqual(owner, nftOwner)

const { receiver, royaltyAmount } = await nft.royaltyInfo(did, 500)
assert.strictEqual(owner, receiver)
assert.strictEqual(50, royaltyAmount.toNumber())
})

it('Should Mint automatically if is configured that way', async () => {
const didSeed = testUtils.generateId()
const did = await didRegistry.hashDID(didSeed, owner)
Expand Down
14 changes: 14 additions & 0 deletions test/unit/registry/MintableDIDRegistry.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,18 @@ contract('Mintable DIDRegistry', (accounts) => {
assert.strictEqual(10, balance.toNumber())
})

it('The royalties should be initialized and retrieved (ERC-2981)', async () => {
const didSeed = testUtils.generateId()
const did = await didRegistry.hashDID(didSeed, owner)
const checksum = testUtils.generateId()
await didRegistry.registerMintableDID(
didSeed, checksum, [], value, 999, 10, constants.activities.GENERATED, '', { from: owner })

const { receiver, royaltyAmount } = await nft.royaltyInfo(did, 500)
assert.strictEqual(owner, receiver)
assert.strictEqual(50, royaltyAmount.toNumber())
})

it('Should Mint automatically if is configured that way', async () => {
const didSeed = testUtils.generateId()
const did = await didRegistry.hashDID(didSeed, owner)
Expand All @@ -141,6 +153,7 @@ contract('Mintable DIDRegistry', (accounts) => {
assert.strictEqual(5, balanceOwner.toNumber())
})


it('Should mint if is not capped', async () => {
const didSeed = testUtils.generateId()
const did = await didRegistry.hashDID(didSeed, owner)
Expand Down Expand Up @@ -233,6 +246,7 @@ contract('Mintable DIDRegistry', (accounts) => {

assert.isNotOk( // MUST BE FALSE. Original creator is not getting royalties
await didRegistryLibraryProxy.areRoyaltiesValid(did, [100], [other]))

})
})
})

0 comments on commit 04a0d0c

Please sign in to comment.