You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

156 lines
6.3 KiB
JavaScript

const { deployContract, getBlockTimestamp, mineBlockTimestamp } = require('../helpers.js');
const { expect } = require('chai');
const { constants } = require('@openzeppelin/test-helpers');
const { ZERO_ADDRESS } = constants;
const createTestSuite = ({ contract, constructorArgs }) =>
function () {
context(`${contract}`, function () {
beforeEach(async function () {
this.erc4097a = await deployContract(contract, constructorArgs);
});
describe('EIP-165 support', async function () {
it('supports ERC165', async function () {
expect(await this.erc4097a.supportsInterface('0x01ffc9a7')).to.eq(true);
});
it('supports IERC721', async function () {
expect(await this.erc4097a.supportsInterface('0x80ac58cd')).to.eq(true);
});
it('supports ERC721Metadata', async function () {
expect(await this.erc4097a.supportsInterface('0x5b5e139f')).to.eq(true);
});
it('supports ERC4907', async function () {
expect(await this.erc4097a.supportsInterface('0xad092b5c')).to.eq(true);
});
it('does not support random interface', async function () {
expect(await this.erc4097a.supportsInterface('0x00000042')).to.eq(false);
});
});
context('with minted tokens', async function () {
beforeEach(async function () {
const [owner, addr1] = await ethers.getSigners();
this.owner = owner;
this.addr1 = addr1;
await this.erc4097a['mint(address,uint256)'](this.owner.address, 1);
await this.erc4097a['mint(address,uint256)'](this.addr1.address, 2);
this.expires = (await getBlockTimestamp()) + 123;
this.tokenId = 2;
this.user = this.owner;
});
it('explicitUserOf returns zero address after minting', async function () {
expect(await this.erc4097a.explicitUserOf(0)).to.equal(ZERO_ADDRESS);
expect(await this.erc4097a.explicitUserOf(1)).to.equal(ZERO_ADDRESS);
expect(await this.erc4097a.explicitUserOf(2)).to.equal(ZERO_ADDRESS);
});
it('userOf returns zero address after minting', async function () {
expect(await this.erc4097a.userOf(0)).to.equal(ZERO_ADDRESS);
expect(await this.erc4097a.userOf(1)).to.equal(ZERO_ADDRESS);
expect(await this.erc4097a.userOf(2)).to.equal(ZERO_ADDRESS);
});
it('userExpires returns zero timestamp after minting', async function () {
expect(await this.erc4097a.userExpires(0)).to.equal(0);
expect(await this.erc4097a.userExpires(1)).to.equal(0);
expect(await this.erc4097a.userExpires(2)).to.equal(0);
});
describe('setUser', async function () {
beforeEach(async function () {
this.setUser = async () => await this.erc4097a.connect(this.addr1)
.setUser(this.tokenId, this.user.address, this.expires);
this.setupAuthTest = async () => {
this.tokenId = 0;
await expect(this.setUser()).to.be.revertedWith('SetUserCallerNotOwnerNorApproved');
};
});
it('correctly changes the return value of explicitUserOf', async function () {
await this.setUser();
expect(await this.erc4097a.explicitUserOf(this.tokenId)).to.equal(this.user.address);
});
it('correctly changes the return value of userOf', async function () {
await this.setUser();
expect(await this.erc4097a.userOf(this.tokenId)).to.equal(this.user.address);
});
it('correctly changes the return value of expires', async function () {
await this.setUser();
expect(await this.erc4097a.userExpires(this.tokenId)).to.equal(this.expires);
});
it('emits the UpdateUser event properly', async function () {
await expect(await this.setUser())
.to.emit(this.erc4097a, 'UpdateUser')
.withArgs(this.tokenId, this.user.address, this.expires);
});
it('reverts for an invalid token', async function () {
this.tokenId = 123;
await expect(this.setUser()).to.be.revertedWith('OwnerQueryForNonexistentToken');
});
it('requires token ownership', async function () {
await this.setupAuthTest();
await this.erc4097a.transferFrom(this.owner.address, this.addr1.address, this.tokenId);
await this.setUser();
});
it('requires token approval', async function () {
await this.setupAuthTest();
await this.erc4097a.approve(this.addr1.address, this.tokenId);
await this.setUser();
});
it('requires operator approval', async function () {
await this.setupAuthTest();
await this.erc4097a.setApprovalForAll(this.addr1.address, 1);
await this.setUser();
});
});
describe('after expiry', async function () {
beforeEach(async function () {
await this.erc4097a.connect(this.addr1)
.setUser(this.tokenId, this.user.address, this.expires);
});
it('userOf returns zero address after expires', async function () {
expect(await this.erc4097a.userOf(this.tokenId)).to.equal(this.user.address);
await mineBlockTimestamp(this.expires);
expect(await this.erc4097a.userOf(this.tokenId)).to.equal(this.user.address);
await mineBlockTimestamp(this.expires + 1);
expect(await this.erc4097a.userOf(this.tokenId)).to.equal(ZERO_ADDRESS);
});
it('explicitUserOf returns correct address after expiry', async function () {
expect(await this.erc4097a.explicitUserOf(this.tokenId)).to.equal(this.user.address);
await mineBlockTimestamp(this.expires);
expect(await this.erc4097a.explicitUserOf(this.tokenId)).to.equal(this.user.address);
await mineBlockTimestamp(this.expires + 1);
expect(await this.erc4097a.explicitUserOf(this.tokenId)).to.equal(this.user.address);
});
});
});
});
};
describe(
'ERC4907A',
createTestSuite({
contract: 'ERC4907AMock',
constructorArgs: ['Azuki', 'AZUKI'],
})
);