diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..1ad899d Binary files /dev/null and b/.DS_Store differ diff --git a/test/ERC721RolesRegistry.spec.ts b/test/ERC721RolesRegistry.spec.ts index 22f11d8..d4c9f47 100644 --- a/test/ERC721RolesRegistry.spec.ts +++ b/test/ERC721RolesRegistry.spec.ts @@ -1,123 +1,231 @@ import hre, { ethers } from 'hardhat' -import { Contract, utils } from 'ethers' +import { Contract } from 'ethers' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' import { expect } from 'chai' -import { randomString, randomHash } from './utils' +import { randomHash } from './utils' const { HashZero } = ethers.constants +const ONE_DAY = 60 * 60 * 24 describe('Roles Registry', () => { - let rolesManagement: Contract let rolesRegistry: Contract let mockERC721: Contract - let account: SignerWithAddress - const name = randomString() - const desc = randomString() + // eslint-disable-next-line @typescript-eslint/no-unused-vars + let deployer: SignerWithAddress + let roleCreator: SignerWithAddress + let userOne: SignerWithAddress + let userTwo: SignerWithAddress + const role = randomHash() before(async function () { - const signers = await ethers.getSigners() - account = signers[0] + ;[deployer, roleCreator, userOne, userTwo] = await ethers.getSigners() }) beforeEach(async () => { - const RoleManagementFactory = await ethers.getContractFactory('RoleManagement') - rolesManagement = await RoleManagementFactory.deploy() - const RoleRegistryFactory = await ethers.getContractFactory('ERC721RolesRegistry') rolesRegistry = await RoleRegistryFactory.deploy() const MockERC721Factory = await ethers.getContractFactory('MockERC721') mockERC721 = await MockERC721Factory.deploy('Mock ERC721', 'mERC721') - - await expect(rolesManagement.createRole(role, name, desc, HashZero)) - .to.emit(rolesManagement, 'RoleCreated') - .withArgs(account.address, role, name, desc, HashZero) }) describe('Role registry', async () => { - it('should create a role with data', async () => { - const user = (await ethers.getSigners())[1] - const beneficiaries = [account.address] - const shares = [1000] - const data = utils.defaultAbiCoder.encode(['address[]', 'uint256[]'], [beneficiaries, shares]) - - const tokenId = 1 - await mockERC721.mint(account.address, tokenId) + let expirationDate: number + const tokenId = 1 + const data = HashZero - const ONE_DAY = 60 * 60 * 24 + beforeEach(async () => { const blockNumber = await hre.ethers.provider.getBlockNumber() const block = await hre.ethers.provider.getBlock(blockNumber) - const expirationDate = block.timestamp + ONE_DAY - - await expect( - rolesRegistry.connect(account).grantRole(role, user.address, mockERC721.address, tokenId, expirationDate, data), - ) - .to.emit(rolesRegistry, 'RoleGranted') - .withArgs(role, user.address, expirationDate, mockERC721.address, tokenId, data) - - const returnedData = await rolesRegistry.roleData( - role, - account.address, - user.address, - mockERC721.address, - tokenId, - ) - - expect(returnedData.data_).to.equal(data) + expirationDate = block.timestamp + ONE_DAY + + await mockERC721.mint(roleCreator.address, tokenId) }) - it('should create a role that not support multiple users', async () => { - const userOne = (await ethers.getSigners())[1] - const userTwo = (await ethers.getSigners())[2] - const tokenId = 1 - await mockERC721.mint(account.address, tokenId) + describe('Grant role', async () => { + it('should grant role', async () => { + await expect( + rolesRegistry + .connect(roleCreator) + .grantRole(role, userOne.address, mockERC721.address, tokenId, expirationDate, data), + ) + .to.emit(rolesRegistry, 'RoleGranted') + .withArgs(role, userOne.address, expirationDate, mockERC721.address, tokenId, data) + }) + it('should NOT grant role if not nft owner', async () => { + await expect( + rolesRegistry + .connect(userOne) + .grantRole(role, userOne.address, mockERC721.address, tokenId, expirationDate, HashZero), + ).to.be.revertedWith('ERC721RolesRegistry: msg.sender is not owner of the NFT') + }) + it('should NOT grant role if expiration date is in the past', async () => { + const blockNumber = await hre.ethers.provider.getBlockNumber() + const block = await hre.ethers.provider.getBlock(blockNumber) + const expirationDateInThePast = block.timestamp - ONE_DAY + + await expect( + rolesRegistry + .connect(roleCreator) + .grantRole(role, userOne.address, mockERC721.address, tokenId, expirationDateInThePast, HashZero), + ).to.be.revertedWith('ERC721RolesRegistry: expiration date must be in the future') + }) + }) - const ONE_DAY = 60 * 60 * 24 - const blockNumber = await hre.ethers.provider.getBlockNumber() - const block = await hre.ethers.provider.getBlock(blockNumber) + describe('Revoke role', async () => { + it('should revoke role', async () => { + await expect(rolesRegistry.connect(roleCreator).revokeRole(role, userOne.address, mockERC721.address, tokenId)) + .to.emit(rolesRegistry, 'RoleRevoked') + .withArgs(role, userOne.address, mockERC721.address, tokenId) + }) + it('should NOT revoke role if not nft owner', async () => { + await expect( + rolesRegistry.connect(userOne).revokeRole(role, userOne.address, mockERC721.address, tokenId), + ).to.be.revertedWith('ERC721RolesRegistry: msg.sender is not owner of the NFT') + }) + }) + + describe('Has role', async () => { + beforeEach(async () => { + await expect( + rolesRegistry + .connect(roleCreator) + .grantRole(role, userOne.address, mockERC721.address, tokenId, expirationDate, HashZero), + ) + .to.emit(rolesRegistry, 'RoleGranted') + .withArgs(role, userOne.address, expirationDate, mockERC721.address, tokenId, HashZero) + + await expect( + rolesRegistry + .connect(roleCreator) + .grantRole(role, userTwo.address, mockERC721.address, tokenId, expirationDate, HashZero), + ) + .to.emit(rolesRegistry, 'RoleGranted') + .withArgs(role, userTwo.address, expirationDate, mockERC721.address, tokenId, HashZero) + }) + + describe('Single User Roles', async () => { + const supportMultipleUsers = false + + it('should return true for the last user granted, and false for the others', async () => { + expect( + await rolesRegistry.hasRole( + role, + roleCreator.address, + userOne.address, + mockERC721.address, + tokenId, + supportMultipleUsers, + ), + ).to.be.equal(false) + + expect( + await rolesRegistry.hasRole( + role, + roleCreator.address, + userTwo.address, + mockERC721.address, + tokenId, + supportMultipleUsers, + ), + ).to.be.equal(true) + }) + it('should NOT return true for the last user if role is expired', async () => { + await hre.ethers.provider.send('evm_increaseTime', [ONE_DAY + 1]) + await hre.ethers.provider.send('evm_mine', []) + + expect( + await rolesRegistry.hasRole( + role, + roleCreator.address, + userOne.address, + mockERC721.address, + tokenId, + supportMultipleUsers, + ), + ).to.be.equal(false) + }) + }) + + describe('Multiple Users Roles', async () => { + const supportMultipleUsers = true + + it('should return true for all users', async () => { + expect( + await rolesRegistry.hasRole( + role, + roleCreator.address, + userOne.address, + mockERC721.address, + tokenId, + supportMultipleUsers, + ), + ).to.be.equal(true) + + expect( + await rolesRegistry.hasRole( + role, + roleCreator.address, + userTwo.address, + mockERC721.address, + tokenId, + supportMultipleUsers, + ), + ).to.be.equal(true) + }) + it("should NOT return true for all users if role is expired'", async () => { + await hre.ethers.provider.send('evm_increaseTime', [ONE_DAY + 1]) + await hre.ethers.provider.send('evm_mine', []) + + expect( + await rolesRegistry.hasRole( + role, + roleCreator.address, + userOne.address, + mockERC721.address, + tokenId, + supportMultipleUsers, + ), + ).to.be.equal(false) + + expect( + await rolesRegistry.hasRole( + role, + roleCreator.address, + userTwo.address, + mockERC721.address, + tokenId, + supportMultipleUsers, + ), + ).to.be.equal(false) + }) + }) + }) + + describe('Role Data', async () => { + it('should grant role with data', async () => { + const customData = '0x1234' - const expirationDate = block.timestamp + ONE_DAY - - await expect( - rolesRegistry - .connect(account) - .grantRole(role, userOne.address, mockERC721.address, tokenId, expirationDate, HashZero), - ) - .to.emit(rolesRegistry, 'RoleGranted') - .withArgs(role, userOne.address, expirationDate, mockERC721.address, tokenId, HashZero) - - await expect( - rolesRegistry - .connect(account) - .grantRole(role, userTwo.address, mockERC721.address, tokenId, expirationDate, HashZero), - ) - .to.emit(rolesRegistry, 'RoleGranted') - .withArgs(role, userTwo.address, expirationDate, mockERC721.address, tokenId, HashZero) - - const supportMultipleUsers = false - expect( - await rolesRegistry.hasRole( + await expect( + rolesRegistry + .connect(roleCreator) + .grantRole(role, userOne.address, mockERC721.address, tokenId, expirationDate, customData), + ) + .to.emit(rolesRegistry, 'RoleGranted') + .withArgs(role, userOne.address, expirationDate, mockERC721.address, tokenId, customData) + + const returnedData = await rolesRegistry.roleData( role, - account.address, + roleCreator.address, userOne.address, mockERC721.address, tokenId, - supportMultipleUsers, - ), - ).to.be.equal(false) + ) - expect( - await rolesRegistry.hasRole( - role, - account.address, - userTwo.address, - mockERC721.address, - tokenId, - supportMultipleUsers, - ), - ).to.be.equal(true) + expect(returnedData.data_).to.equal(customData) + }) }) }) })