Merge tag 'v2.1.1' of github.com:OpenZeppelin/openzeppelin-solidity
v2.1.1
This commit is contained in:
@ -1,15 +1,11 @@
|
||||
const expectEvent = require('../../helpers/expectEvent');
|
||||
const { shouldSupportInterfaces } = require('../../introspection/SupportsInterface.behavior');
|
||||
const { assertRevert } = require('../../helpers/assertRevert');
|
||||
const { decodeLogs } = require('../../helpers/decodeLogs');
|
||||
const { sendTransaction } = require('../../helpers/sendTransaction');
|
||||
const _ = require('lodash');
|
||||
const shouldFail = require('../../helpers/shouldFail');
|
||||
const { ZERO_ADDRESS } = require('../../helpers/constants');
|
||||
const send = require('../../helpers/send');
|
||||
|
||||
const ERC721Receiver = artifacts.require('ERC721ReceiverMock.sol');
|
||||
const BigNumber = web3.BigNumber;
|
||||
|
||||
require('chai')
|
||||
.use(require('chai-bignumber')(BigNumber))
|
||||
.should();
|
||||
const ERC721ReceiverMock = artifacts.require('ERC721ReceiverMock.sol');
|
||||
require('../../helpers/setup');
|
||||
|
||||
function shouldBehaveLikeERC721 (
|
||||
creator,
|
||||
@ -19,7 +15,6 @@ function shouldBehaveLikeERC721 (
|
||||
const firstTokenId = 1;
|
||||
const secondTokenId = 2;
|
||||
const unknownTokenId = 3;
|
||||
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
|
||||
const RECEIVER_MAGIC_VALUE = '0x150b7a02';
|
||||
|
||||
describe('like an ERC721', function () {
|
||||
@ -44,7 +39,7 @@ function shouldBehaveLikeERC721 (
|
||||
|
||||
context('when querying the zero address', function () {
|
||||
it('throws', async function () {
|
||||
await assertRevert(this.token.balanceOf(0));
|
||||
await shouldFail.reverting(this.token.balanceOf(0));
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -62,7 +57,7 @@ function shouldBehaveLikeERC721 (
|
||||
const tokenId = unknownTokenId;
|
||||
|
||||
it('reverts', async function () {
|
||||
await assertRevert(this.token.ownerOf(tokenId));
|
||||
await shouldFail.reverting(this.token.ownerOf(tokenId));
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -89,19 +84,19 @@ function shouldBehaveLikeERC721 (
|
||||
|
||||
if (approved) {
|
||||
it('emit only a transfer event', async function () {
|
||||
logs.length.should.be.equal(1);
|
||||
logs[0].event.should.be.equal('Transfer');
|
||||
logs[0].args.from.should.be.equal(owner);
|
||||
logs[0].args.to.should.be.equal(this.toWhom);
|
||||
logs[0].args.tokenId.should.be.bignumber.equal(tokenId);
|
||||
expectEvent.inLogs(logs, 'Transfer', {
|
||||
from: owner,
|
||||
to: this.toWhom,
|
||||
tokenId: tokenId,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
it('emits only a transfer event', async function () {
|
||||
logs.length.should.be.equal(1);
|
||||
logs[0].event.should.be.equal('Transfer');
|
||||
logs[0].args.from.should.be.equal(owner);
|
||||
logs[0].args.to.should.be.equal(this.toWhom);
|
||||
logs[0].args.tokenId.should.be.bignumber.equal(tokenId);
|
||||
expectEvent.inLogs(logs, 'Transfer', {
|
||||
from: owner,
|
||||
to: this.toWhom,
|
||||
tokenId: tokenId,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -162,11 +157,11 @@ function shouldBehaveLikeERC721 (
|
||||
});
|
||||
|
||||
it('emits only a transfer event', async function () {
|
||||
logs.length.should.be.equal(1);
|
||||
logs[0].event.should.be.equal('Transfer');
|
||||
logs[0].args.from.should.be.equal(owner);
|
||||
logs[0].args.to.should.be.equal(owner);
|
||||
logs[0].args.tokenId.should.be.bignumber.equal(tokenId);
|
||||
expectEvent.inLogs(logs, 'Transfer', {
|
||||
from: owner,
|
||||
to: owner,
|
||||
tokenId: tokenId,
|
||||
});
|
||||
});
|
||||
|
||||
it('keeps the owner balance', async function () {
|
||||
@ -175,35 +170,37 @@ function shouldBehaveLikeERC721 (
|
||||
|
||||
it('keeps same tokens by index', async function () {
|
||||
if (!this.token.tokenOfOwnerByIndex) return;
|
||||
const tokensListed = await Promise.all(_.range(2).map(i => this.token.tokenOfOwnerByIndex(owner, i)));
|
||||
const tokensListed = await Promise.all(
|
||||
[0, 1].map(i => this.token.tokenOfOwnerByIndex(owner, i))
|
||||
);
|
||||
tokensListed.map(t => t.toNumber()).should.have.members([firstTokenId, secondTokenId]);
|
||||
});
|
||||
});
|
||||
|
||||
context('when the address of the previous owner is incorrect', function () {
|
||||
it('reverts', async function () {
|
||||
await assertRevert(transferFunction.call(this, anyone, anyone, tokenId, { from: owner })
|
||||
await shouldFail.reverting(transferFunction.call(this, anyone, anyone, tokenId, { from: owner })
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('when the sender is not authorized for the token id', function () {
|
||||
it('reverts', async function () {
|
||||
await assertRevert(transferFunction.call(this, owner, anyone, tokenId, { from: anyone })
|
||||
await shouldFail.reverting(transferFunction.call(this, owner, anyone, tokenId, { from: anyone })
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('when the given token ID does not exist', function () {
|
||||
it('reverts', async function () {
|
||||
await assertRevert(transferFunction.call(this, owner, anyone, unknownTokenId, { from: owner })
|
||||
await shouldFail.reverting(transferFunction.call(this, owner, anyone, unknownTokenId, { from: owner })
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('when the address to transfer the token to is the zero address', function () {
|
||||
it('reverts', async function () {
|
||||
await assertRevert(transferFunction.call(this, owner, ZERO_ADDRESS, tokenId, { from: owner }));
|
||||
await shouldFail.reverting(transferFunction.call(this, owner, ZERO_ADDRESS, tokenId, { from: owner }));
|
||||
});
|
||||
});
|
||||
};
|
||||
@ -216,7 +213,7 @@ function shouldBehaveLikeERC721 (
|
||||
|
||||
describe('via safeTransferFrom', function () {
|
||||
const safeTransferFromWithData = function (from, to, tokenId, opts) {
|
||||
return sendTransaction(
|
||||
return send.transaction(
|
||||
this.token,
|
||||
'safeTransferFrom',
|
||||
'address,address,uint256,bytes',
|
||||
@ -236,43 +233,37 @@ function shouldBehaveLikeERC721 (
|
||||
|
||||
describe('to a valid receiver contract', function () {
|
||||
beforeEach(async function () {
|
||||
this.receiver = await ERC721Receiver.new(RECEIVER_MAGIC_VALUE, false);
|
||||
this.receiver = await ERC721ReceiverMock.new(RECEIVER_MAGIC_VALUE, false);
|
||||
this.toWhom = this.receiver.address;
|
||||
});
|
||||
|
||||
shouldTransferTokensByUsers(transferFun);
|
||||
|
||||
it('should call onERC721Received', async function () {
|
||||
const result = await transferFun.call(this, owner, this.receiver.address, tokenId, { from: owner });
|
||||
result.receipt.logs.length.should.be.equal(2);
|
||||
const [log] = decodeLogs([result.receipt.logs[1]], ERC721Receiver, this.receiver.address);
|
||||
log.event.should.be.equal('Received');
|
||||
log.args.operator.should.be.equal(owner);
|
||||
log.args.from.should.be.equal(owner);
|
||||
log.args.tokenId.toNumber().should.be.equal(tokenId);
|
||||
log.args.data.should.be.equal(data);
|
||||
const receipt = await transferFun.call(this, owner, this.receiver.address, tokenId, { from: owner });
|
||||
|
||||
await expectEvent.inTransaction(receipt.tx, ERC721ReceiverMock, 'Received', {
|
||||
operator: owner,
|
||||
from: owner,
|
||||
tokenId: tokenId,
|
||||
data: data,
|
||||
});
|
||||
});
|
||||
|
||||
it('should call onERC721Received from approved', async function () {
|
||||
const result = await transferFun.call(this, owner, this.receiver.address, tokenId, {
|
||||
from: approved,
|
||||
const receipt = await transferFun.call(this, owner, this.receiver.address, tokenId, { from: approved });
|
||||
|
||||
await expectEvent.inTransaction(receipt.tx, ERC721ReceiverMock, 'Received', {
|
||||
operator: approved,
|
||||
from: owner,
|
||||
tokenId: tokenId,
|
||||
data: data,
|
||||
});
|
||||
result.receipt.logs.length.should.be.equal(2);
|
||||
const [log] = decodeLogs(
|
||||
[result.receipt.logs[1]],
|
||||
ERC721Receiver,
|
||||
this.receiver.address
|
||||
);
|
||||
log.event.should.be.equal('Received');
|
||||
log.args.operator.should.be.equal(approved);
|
||||
log.args.from.should.be.equal(owner);
|
||||
log.args.tokenId.toNumber().should.be.equal(tokenId);
|
||||
log.args.data.should.be.equal(data);
|
||||
});
|
||||
|
||||
describe('with an invalid token id', function () {
|
||||
it('reverts', async function () {
|
||||
await assertRevert(
|
||||
await shouldFail.reverting(
|
||||
transferFun.call(
|
||||
this,
|
||||
owner,
|
||||
@ -296,22 +287,28 @@ function shouldBehaveLikeERC721 (
|
||||
|
||||
describe('to a receiver contract returning unexpected value', function () {
|
||||
it('reverts', async function () {
|
||||
const invalidReceiver = await ERC721Receiver.new('0x42', false);
|
||||
await assertRevert(this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner }));
|
||||
const invalidReceiver = await ERC721ReceiverMock.new('0x42', false);
|
||||
await shouldFail.reverting(
|
||||
this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner })
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('to a receiver contract that throws', function () {
|
||||
it('reverts', async function () {
|
||||
const invalidReceiver = await ERC721Receiver.new(RECEIVER_MAGIC_VALUE, true);
|
||||
await assertRevert(this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner }));
|
||||
const invalidReceiver = await ERC721ReceiverMock.new(RECEIVER_MAGIC_VALUE, true);
|
||||
await shouldFail.reverting(
|
||||
this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner })
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('to a contract that does not implement the required function', function () {
|
||||
it('reverts', async function () {
|
||||
const invalidReceiver = this.token;
|
||||
await assertRevert(this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner }));
|
||||
await shouldFail.reverting(
|
||||
this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner })
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -336,11 +333,11 @@ function shouldBehaveLikeERC721 (
|
||||
|
||||
const itEmitsApprovalEvent = function (address) {
|
||||
it('emits an approval event', async function () {
|
||||
logs.length.should.be.equal(1);
|
||||
logs[0].event.should.be.equal('Approval');
|
||||
logs[0].args.owner.should.be.equal(owner);
|
||||
logs[0].args.approved.should.be.equal(address);
|
||||
logs[0].args.tokenId.should.be.bignumber.equal(tokenId);
|
||||
expectEvent.inLogs(logs, 'Approval', {
|
||||
owner: owner,
|
||||
approved: address,
|
||||
tokenId: tokenId,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@ -398,7 +395,7 @@ function shouldBehaveLikeERC721 (
|
||||
|
||||
context('when the address that receives the approval is the owner', function () {
|
||||
it('reverts', async function () {
|
||||
await assertRevert(
|
||||
await shouldFail.reverting(
|
||||
this.token.approve(owner, tokenId, { from: owner })
|
||||
);
|
||||
});
|
||||
@ -406,14 +403,14 @@ function shouldBehaveLikeERC721 (
|
||||
|
||||
context('when the sender does not own the given token ID', function () {
|
||||
it('reverts', async function () {
|
||||
await assertRevert(this.token.approve(approved, tokenId, { from: anyone }));
|
||||
await shouldFail.reverting(this.token.approve(approved, tokenId, { from: anyone }));
|
||||
});
|
||||
});
|
||||
|
||||
context('when the sender is approved for the given token ID', function () {
|
||||
it('reverts', async function () {
|
||||
await this.token.approve(approved, tokenId, { from: owner });
|
||||
await assertRevert(this.token.approve(anotherApproved, tokenId, { from: approved }));
|
||||
await shouldFail.reverting(this.token.approve(anotherApproved, tokenId, { from: approved }));
|
||||
});
|
||||
});
|
||||
|
||||
@ -429,7 +426,7 @@ function shouldBehaveLikeERC721 (
|
||||
|
||||
context('when the given token ID does not exist', function () {
|
||||
it('reverts', async function () {
|
||||
await assertRevert(this.token.approve(approved, unknownTokenId, { from: operator }));
|
||||
await shouldFail.reverting(this.token.approve(approved, unknownTokenId, { from: operator }));
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -446,11 +443,11 @@ function shouldBehaveLikeERC721 (
|
||||
it('emits an approval event', async function () {
|
||||
const { logs } = await this.token.setApprovalForAll(operator, true, { from: owner });
|
||||
|
||||
logs.length.should.be.equal(1);
|
||||
logs[0].event.should.be.equal('ApprovalForAll');
|
||||
logs[0].args.owner.should.be.equal(owner);
|
||||
logs[0].args.operator.should.be.equal(operator);
|
||||
logs[0].args.approved.should.equal(true);
|
||||
expectEvent.inLogs(logs, 'ApprovalForAll', {
|
||||
owner: owner,
|
||||
operator: operator,
|
||||
approved: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -468,11 +465,11 @@ function shouldBehaveLikeERC721 (
|
||||
it('emits an approval event', async function () {
|
||||
const { logs } = await this.token.setApprovalForAll(operator, true, { from: owner });
|
||||
|
||||
logs.length.should.be.equal(1);
|
||||
logs[0].event.should.be.equal('ApprovalForAll');
|
||||
logs[0].args.owner.should.be.equal(owner);
|
||||
logs[0].args.operator.should.be.equal(operator);
|
||||
logs[0].args.approved.should.equal(true);
|
||||
expectEvent.inLogs(logs, 'ApprovalForAll', {
|
||||
owner: owner,
|
||||
operator: operator,
|
||||
approved: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('can unset the operator approval', async function () {
|
||||
@ -496,18 +493,18 @@ function shouldBehaveLikeERC721 (
|
||||
it('emits an approval event', async function () {
|
||||
const { logs } = await this.token.setApprovalForAll(operator, true, { from: owner });
|
||||
|
||||
logs.length.should.be.equal(1);
|
||||
logs[0].event.should.be.equal('ApprovalForAll');
|
||||
logs[0].args.owner.should.be.equal(owner);
|
||||
logs[0].args.operator.should.be.equal(operator);
|
||||
logs[0].args.approved.should.equal(true);
|
||||
expectEvent.inLogs(logs, 'ApprovalForAll', {
|
||||
owner: owner,
|
||||
operator: operator,
|
||||
approved: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('when the operator is the owner', function () {
|
||||
it('reverts', async function () {
|
||||
await assertRevert(this.token.setApprovalForAll(owner, true, { from: owner }));
|
||||
await shouldFail.reverting(this.token.setApprovalForAll(owner, true, { from: owner }));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,16 +1,112 @@
|
||||
require('../../helpers/setup');
|
||||
const { ZERO_ADDRESS } = require('../../helpers/constants');
|
||||
const expectEvent = require('../../helpers/expectEvent');
|
||||
const send = require('../../helpers/send');
|
||||
const shouldFail = require('../../helpers/shouldFail');
|
||||
|
||||
const { shouldBehaveLikeERC721 } = require('./ERC721.behavior');
|
||||
const ERC721Mock = artifacts.require('ERC721Mock.sol');
|
||||
|
||||
const BigNumber = web3.BigNumber;
|
||||
const ERC721 = artifacts.require('ERC721Mock.sol');
|
||||
|
||||
require('chai')
|
||||
.use(require('chai-bignumber')(BigNumber))
|
||||
.should();
|
||||
|
||||
contract('ERC721', function ([_, creator, ...accounts]) {
|
||||
contract('ERC721', function ([_, creator, tokenOwner, anyone, ...accounts]) {
|
||||
beforeEach(async function () {
|
||||
this.token = await ERC721.new({ from: creator });
|
||||
this.token = await ERC721Mock.new({ from: creator });
|
||||
});
|
||||
|
||||
shouldBehaveLikeERC721(creator, creator, accounts);
|
||||
|
||||
describe('internal functions', function () {
|
||||
const tokenId = 5042;
|
||||
|
||||
describe('_mint(address, uint256)', function () {
|
||||
it('reverts with a null destination address', async function () {
|
||||
await shouldFail.reverting(this.token.mint(ZERO_ADDRESS, tokenId));
|
||||
});
|
||||
|
||||
context('with minted token', async function () {
|
||||
beforeEach(async function () {
|
||||
({ logs: this.logs } = await this.token.mint(tokenOwner, tokenId));
|
||||
});
|
||||
|
||||
it('emits a Transfer event', function () {
|
||||
expectEvent.inLogs(this.logs, 'Transfer', { from: ZERO_ADDRESS, to: tokenOwner, tokenId });
|
||||
});
|
||||
|
||||
it('creates the token', async function () {
|
||||
(await this.token.balanceOf(tokenOwner)).should.be.bignumber.equal(1);
|
||||
(await this.token.ownerOf(tokenId)).should.equal(tokenOwner);
|
||||
});
|
||||
|
||||
it('reverts when adding a token id that already exists', async function () {
|
||||
await shouldFail.reverting(this.token.mint(tokenOwner, tokenId));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('_burn(address, uint256)', function () {
|
||||
it('reverts when burning a non-existent token id', async function () {
|
||||
await shouldFail.reverting(send.transaction(this.token, 'burn', 'address,uint256', [tokenOwner, tokenId]));
|
||||
});
|
||||
|
||||
context('with minted token', function () {
|
||||
beforeEach(async function () {
|
||||
await this.token.mint(tokenOwner, tokenId);
|
||||
});
|
||||
|
||||
it('reverts when the account is not the owner', async function () {
|
||||
await shouldFail.reverting(send.transaction(this.token, 'burn', 'address,uint256', [anyone, tokenId]));
|
||||
});
|
||||
|
||||
context('with burnt token', function () {
|
||||
beforeEach(async function () {
|
||||
({ logs: this.logs } =
|
||||
await send.transaction(this.token, 'burn', 'address,uint256', [tokenOwner, tokenId]));
|
||||
});
|
||||
|
||||
it('emits a Transfer event', function () {
|
||||
expectEvent.inLogs(this.logs, 'Transfer', { from: tokenOwner, to: ZERO_ADDRESS, tokenId });
|
||||
});
|
||||
|
||||
it('deletes the token', async function () {
|
||||
(await this.token.balanceOf(tokenOwner)).should.be.bignumber.equal(0);
|
||||
await shouldFail.reverting(this.token.ownerOf(tokenId));
|
||||
});
|
||||
|
||||
it('reverts when burning a token id that has been deleted', async function () {
|
||||
await shouldFail.reverting(send.transaction(this.token, 'burn', 'address,uint256', [tokenOwner, tokenId]));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('_burn(uint256)', function () {
|
||||
it('reverts when burning a non-existent token id', async function () {
|
||||
await shouldFail.reverting(send.transaction(this.token, 'burn', 'uint256', [tokenId]));
|
||||
});
|
||||
|
||||
context('with minted token', function () {
|
||||
beforeEach(async function () {
|
||||
await this.token.mint(tokenOwner, tokenId);
|
||||
});
|
||||
|
||||
context('with burnt token', function () {
|
||||
beforeEach(async function () {
|
||||
({ logs: this.logs } = await send.transaction(this.token, 'burn', 'uint256', [tokenId]));
|
||||
});
|
||||
|
||||
it('emits a Transfer event', function () {
|
||||
expectEvent.inLogs(this.logs, 'Transfer', { from: tokenOwner, to: ZERO_ADDRESS, tokenId });
|
||||
});
|
||||
|
||||
it('deletes the token', async function () {
|
||||
(await this.token.balanceOf(tokenOwner)).should.be.bignumber.equal(0);
|
||||
await shouldFail.reverting(this.token.ownerOf(tokenId));
|
||||
});
|
||||
|
||||
it('reverts when burning a token id that has been deleted', async function () {
|
||||
await shouldFail.reverting(send.transaction(this.token, 'burn', 'uint256', [tokenId]));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -3,18 +3,15 @@ const {
|
||||
shouldBehaveLikeMintAndBurnERC721,
|
||||
} = require('./ERC721MintBurn.behavior');
|
||||
|
||||
const BigNumber = web3.BigNumber;
|
||||
const ERC721Burnable = artifacts.require('ERC721MintableBurnableImpl.sol');
|
||||
const ERC721BurnableImpl = artifacts.require('ERC721MintableBurnableImpl.sol');
|
||||
|
||||
require('chai')
|
||||
.use(require('chai-bignumber')(BigNumber))
|
||||
.should();
|
||||
require('../../helpers/setup');
|
||||
|
||||
contract('ERC721Burnable', function ([_, creator, ...accounts]) {
|
||||
const minter = creator;
|
||||
|
||||
beforeEach(async function () {
|
||||
this.token = await ERC721Burnable.new({ from: creator });
|
||||
this.token = await ERC721BurnableImpl.new({ from: creator });
|
||||
});
|
||||
|
||||
shouldBehaveLikeERC721(creator, minter, accounts);
|
||||
|
||||
@ -1,14 +1,10 @@
|
||||
const { assertRevert } = require('../../helpers/assertRevert');
|
||||
const shouldFail = require('../../helpers/shouldFail');
|
||||
const { shouldBehaveLikeERC721 } = require('./ERC721.behavior');
|
||||
const { shouldSupportInterfaces } = require('../../introspection/SupportsInterface.behavior');
|
||||
const _ = require('lodash');
|
||||
|
||||
const BigNumber = web3.BigNumber;
|
||||
const ERC721FullMock = artifacts.require('ERC721FullMock.sol');
|
||||
|
||||
require('chai')
|
||||
.use(require('chai-bignumber')(BigNumber))
|
||||
.should();
|
||||
require('../../helpers/setup');
|
||||
|
||||
contract('ERC721Full', function ([
|
||||
creator,
|
||||
@ -27,7 +23,6 @@ contract('ERC721Full', function ([
|
||||
owner,
|
||||
newOwner,
|
||||
another,
|
||||
anyone,
|
||||
] = accounts;
|
||||
|
||||
beforeEach(async function () {
|
||||
@ -70,37 +65,7 @@ contract('ERC721Full', function ([
|
||||
it('burns all tokens', async function () {
|
||||
await this.token.burn(secondTokenId, { from: owner });
|
||||
(await this.token.totalSupply()).toNumber().should.be.equal(0);
|
||||
await assertRevert(this.token.tokenByIndex(0));
|
||||
});
|
||||
});
|
||||
|
||||
describe('removeTokenFrom', function () {
|
||||
it('reverts if the correct owner is not passed', async function () {
|
||||
await assertRevert(
|
||||
this.token.removeTokenFrom(anyone, firstTokenId, { from: owner })
|
||||
);
|
||||
});
|
||||
|
||||
context('once removed', function () {
|
||||
beforeEach(async function () {
|
||||
await this.token.removeTokenFrom(owner, firstTokenId, { from: owner });
|
||||
});
|
||||
|
||||
it('has been removed', async function () {
|
||||
await assertRevert(this.token.tokenOfOwnerByIndex(owner, 1));
|
||||
});
|
||||
|
||||
it('adjusts token list', async function () {
|
||||
(await this.token.tokenOfOwnerByIndex(owner, 0)).toNumber().should.be.equal(secondTokenId);
|
||||
});
|
||||
|
||||
it('adjusts owner count', async function () {
|
||||
(await this.token.balanceOf(owner)).toNumber().should.be.equal(1);
|
||||
});
|
||||
|
||||
it('does not adjust supply', async function () {
|
||||
(await this.token.totalSupply()).toNumber().should.be.equal(2);
|
||||
});
|
||||
await shouldFail.reverting(this.token.tokenByIndex(0));
|
||||
});
|
||||
});
|
||||
|
||||
@ -121,7 +86,7 @@ contract('ERC721Full', function ([
|
||||
});
|
||||
|
||||
it('reverts when setting metadata for non existent token id', async function () {
|
||||
await assertRevert(this.token.setTokenURI(nonExistentTokenId, sampleUri));
|
||||
await shouldFail.reverting(this.token.setTokenURI(nonExistentTokenId, sampleUri));
|
||||
});
|
||||
|
||||
it('can burn token with metadata', async function () {
|
||||
@ -135,7 +100,16 @@ contract('ERC721Full', function ([
|
||||
});
|
||||
|
||||
it('reverts when querying metadata for non existent token id', async function () {
|
||||
await assertRevert(this.token.tokenURI(nonExistentTokenId));
|
||||
await shouldFail.reverting(this.token.tokenURI(nonExistentTokenId));
|
||||
});
|
||||
});
|
||||
|
||||
describe('tokensOfOwner', function () {
|
||||
it('returns total tokens of owner', async function () {
|
||||
const tokenIds = await this.token.tokensOfOwner(owner);
|
||||
tokenIds.length.should.equal(2);
|
||||
tokenIds[0].should.be.bignumber.equal(firstTokenId);
|
||||
tokenIds[1].should.be.bignumber.equal(secondTokenId);
|
||||
});
|
||||
});
|
||||
|
||||
@ -154,13 +128,13 @@ contract('ERC721Full', function ([
|
||||
|
||||
describe('when the index is greater than or equal to the total tokens owned by the given address', function () {
|
||||
it('reverts', async function () {
|
||||
await assertRevert(this.token.tokenOfOwnerByIndex(owner, 2));
|
||||
await shouldFail.reverting(this.token.tokenOfOwnerByIndex(owner, 2));
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the given address does not own any token', function () {
|
||||
it('reverts', async function () {
|
||||
await assertRevert(this.token.tokenOfOwnerByIndex(another, 0));
|
||||
await shouldFail.reverting(this.token.tokenOfOwnerByIndex(another, 0));
|
||||
});
|
||||
});
|
||||
|
||||
@ -172,25 +146,29 @@ contract('ERC721Full', function ([
|
||||
|
||||
it('returns correct token IDs for target', async function () {
|
||||
(await this.token.balanceOf(another)).toNumber().should.be.equal(2);
|
||||
const tokensListed = await Promise.all(_.range(2).map(i => this.token.tokenOfOwnerByIndex(another, i)));
|
||||
const tokensListed = await Promise.all(
|
||||
[0, 1].map(i => this.token.tokenOfOwnerByIndex(another, i))
|
||||
);
|
||||
tokensListed.map(t => t.toNumber()).should.have.members([firstTokenId, secondTokenId]);
|
||||
});
|
||||
|
||||
it('returns empty collection for original owner', async function () {
|
||||
(await this.token.balanceOf(owner)).toNumber().should.be.equal(0);
|
||||
await assertRevert(this.token.tokenOfOwnerByIndex(owner, 0));
|
||||
await shouldFail.reverting(this.token.tokenOfOwnerByIndex(owner, 0));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('tokenByIndex', function () {
|
||||
it('should return all tokens', async function () {
|
||||
const tokensListed = await Promise.all(_.range(2).map(i => this.token.tokenByIndex(i)));
|
||||
const tokensListed = await Promise.all(
|
||||
[0, 1].map(i => this.token.tokenByIndex(i))
|
||||
);
|
||||
tokensListed.map(t => t.toNumber()).should.have.members([firstTokenId, secondTokenId]);
|
||||
});
|
||||
|
||||
it('should revert if index is greater than supply', async function () {
|
||||
await assertRevert(this.token.tokenByIndex(2));
|
||||
await shouldFail.reverting(this.token.tokenByIndex(2));
|
||||
});
|
||||
|
||||
[firstTokenId, secondTokenId].forEach(function (tokenId) {
|
||||
@ -204,9 +182,10 @@ contract('ERC721Full', function ([
|
||||
|
||||
(await this.token.totalSupply()).toNumber().should.be.equal(3);
|
||||
|
||||
const tokensListed = await Promise.all(_.range(3).map(i => this.token.tokenByIndex(i)));
|
||||
const expectedTokens = _.filter(
|
||||
[firstTokenId, secondTokenId, newTokenId, anotherNewTokenId],
|
||||
const tokensListed = await Promise.all(
|
||||
[0, 1, 2].map(i => this.token.tokenByIndex(i))
|
||||
);
|
||||
const expectedTokens = [firstTokenId, secondTokenId, newTokenId, anotherNewTokenId].filter(
|
||||
x => (x !== tokenId)
|
||||
);
|
||||
tokensListed.map(t => t.toNumber()).should.have.members(expectedTokens);
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
const ERC721Holder = artifacts.require('ERC721Holder.sol');
|
||||
const ERC721Mintable = artifacts.require('ERC721MintableBurnableImpl.sol');
|
||||
|
||||
require('chai')
|
||||
.should();
|
||||
require('../../helpers/setup');
|
||||
|
||||
contract('ERC721Holder', function ([creator]) {
|
||||
it('receives an ERC721 token', async function () {
|
||||
|
||||
@ -1,10 +1,7 @@
|
||||
const { assertRevert } = require('../../helpers/assertRevert');
|
||||
const shouldFail = require('../../helpers/shouldFail');
|
||||
const expectEvent = require('../../helpers/expectEvent');
|
||||
const BigNumber = web3.BigNumber;
|
||||
|
||||
require('chai')
|
||||
.use(require('chai-bignumber')(BigNumber))
|
||||
.should();
|
||||
const { ZERO_ADDRESS } = require('../../helpers/constants');
|
||||
require('../../helpers/setup');
|
||||
|
||||
function shouldBehaveLikeMintAndBurnERC721 (
|
||||
creator,
|
||||
@ -15,7 +12,6 @@ function shouldBehaveLikeMintAndBurnERC721 (
|
||||
const secondTokenId = 2;
|
||||
const thirdTokenId = 3;
|
||||
const unknownTokenId = 4;
|
||||
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
|
||||
const MOCK_URI = 'https://example.com';
|
||||
|
||||
describe('like a mintable and burnable ERC721', function () {
|
||||
@ -42,23 +38,23 @@ function shouldBehaveLikeMintAndBurnERC721 (
|
||||
});
|
||||
|
||||
it('emits a transfer and minted event', async function () {
|
||||
await expectEvent.inLogs(logs, 'Transfer', {
|
||||
expectEvent.inLogs(logs, 'Transfer', {
|
||||
from: ZERO_ADDRESS,
|
||||
to: newOwner,
|
||||
tokenId: thirdTokenId,
|
||||
});
|
||||
logs[0].args.tokenId.should.be.bignumber.equal(thirdTokenId);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the given owner address is the zero address', function () {
|
||||
it('reverts', async function () {
|
||||
await assertRevert(this.token.mint(ZERO_ADDRESS, thirdTokenId, { from: minter }));
|
||||
await shouldFail.reverting(this.token.mint(ZERO_ADDRESS, thirdTokenId, { from: minter }));
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the given token ID was already tracked by this contract', function () {
|
||||
it('reverts', async function () {
|
||||
await assertRevert(this.token.mint(owner, firstTokenId, { from: minter }));
|
||||
await shouldFail.reverting(this.token.mint(owner, firstTokenId, { from: minter }));
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -82,16 +78,16 @@ function shouldBehaveLikeMintAndBurnERC721 (
|
||||
});
|
||||
|
||||
it('burns the given token ID and adjusts the balance of the owner', async function () {
|
||||
await assertRevert(this.token.ownerOf(tokenId));
|
||||
await shouldFail.reverting(this.token.ownerOf(tokenId));
|
||||
(await this.token.balanceOf(owner)).should.be.bignumber.equal(1);
|
||||
});
|
||||
|
||||
it('emits a burn event', async function () {
|
||||
logs.length.should.be.equal(1);
|
||||
logs[0].event.should.be.equal('Transfer');
|
||||
logs[0].args.from.should.be.equal(owner);
|
||||
logs[0].args.to.should.be.equal(ZERO_ADDRESS);
|
||||
logs[0].args.tokenId.should.be.bignumber.equal(tokenId);
|
||||
expectEvent.inLogs(logs, 'Transfer', {
|
||||
from: owner,
|
||||
to: ZERO_ADDRESS,
|
||||
tokenId: tokenId,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -104,14 +100,14 @@ function shouldBehaveLikeMintAndBurnERC721 (
|
||||
|
||||
context('getApproved', function () {
|
||||
it('reverts', async function () {
|
||||
await assertRevert(this.token.getApproved(tokenId));
|
||||
await shouldFail.reverting(this.token.getApproved(tokenId));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the given token ID was not tracked by this contract', function () {
|
||||
it('reverts', async function () {
|
||||
await assertRevert(
|
||||
await shouldFail.reverting(
|
||||
this.token.burn(unknownTokenId, { from: creator })
|
||||
);
|
||||
});
|
||||
|
||||
@ -3,18 +3,15 @@ const {
|
||||
shouldBehaveLikeMintAndBurnERC721,
|
||||
} = require('./ERC721MintBurn.behavior');
|
||||
|
||||
const BigNumber = web3.BigNumber;
|
||||
const ERC721Mintable = artifacts.require('ERC721MintableBurnableImpl.sol');
|
||||
const ERC721MintableImpl = artifacts.require('ERC721MintableBurnableImpl.sol');
|
||||
|
||||
require('chai')
|
||||
.use(require('chai-bignumber')(BigNumber))
|
||||
.should();
|
||||
require('../../helpers/setup');
|
||||
|
||||
contract('ERC721Mintable', function ([_, creator, ...accounts]) {
|
||||
const minter = creator;
|
||||
|
||||
beforeEach(async function () {
|
||||
this.token = await ERC721Mintable.new({
|
||||
this.token = await ERC721MintableImpl.new({
|
||||
from: creator,
|
||||
});
|
||||
});
|
||||
|
||||
@ -2,12 +2,9 @@ const { shouldBehaveLikeERC721PausedToken } = require('./ERC721PausedToken.behav
|
||||
const { shouldBehaveLikeERC721 } = require('./ERC721.behavior');
|
||||
const { shouldBehaveLikePublicRole } = require('../../access/roles/PublicRole.behavior');
|
||||
|
||||
const BigNumber = web3.BigNumber;
|
||||
const ERC721Pausable = artifacts.require('ERC721PausableMock.sol');
|
||||
const ERC721PausableMock = artifacts.require('ERC721PausableMock.sol');
|
||||
|
||||
require('chai')
|
||||
.use(require('chai-bignumber')(BigNumber))
|
||||
.should();
|
||||
require('../../helpers/setup');
|
||||
|
||||
contract('ERC721Pausable', function ([
|
||||
_,
|
||||
@ -18,7 +15,7 @@ contract('ERC721Pausable', function ([
|
||||
...accounts
|
||||
]) {
|
||||
beforeEach(async function () {
|
||||
this.token = await ERC721Pausable.new({ from: creator });
|
||||
this.token = await ERC721PausableMock.new({ from: creator });
|
||||
});
|
||||
|
||||
describe('pauser role', function () {
|
||||
|
||||
@ -1,17 +1,13 @@
|
||||
const { assertRevert } = require('../../helpers/assertRevert');
|
||||
const { sendTransaction } = require('../../helpers/sendTransaction');
|
||||
const shouldFail = require('../../helpers/shouldFail');
|
||||
const send = require('../../helpers/send');
|
||||
const { ZERO_ADDRESS } = require('../../helpers/constants');
|
||||
|
||||
const BigNumber = web3.BigNumber;
|
||||
|
||||
require('chai')
|
||||
.use(require('chai-bignumber')(BigNumber))
|
||||
.should();
|
||||
require('../../helpers/setup');
|
||||
|
||||
function shouldBehaveLikeERC721PausedToken (owner, [recipient, operator]) {
|
||||
const firstTokenId = 1;
|
||||
const mintedTokens = 1;
|
||||
const mockData = '0x42';
|
||||
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
|
||||
|
||||
describe('like a paused ERC721', function () {
|
||||
beforeEach(async function () {
|
||||
@ -19,24 +15,24 @@ function shouldBehaveLikeERC721PausedToken (owner, [recipient, operator]) {
|
||||
});
|
||||
|
||||
it('reverts when trying to approve', async function () {
|
||||
await assertRevert(this.token.approve(recipient, firstTokenId, { from: owner }));
|
||||
await shouldFail.reverting(this.token.approve(recipient, firstTokenId, { from: owner }));
|
||||
});
|
||||
|
||||
it('reverts when trying to setApprovalForAll', async function () {
|
||||
await assertRevert(this.token.setApprovalForAll(operator, true, { from: owner }));
|
||||
await shouldFail.reverting(this.token.setApprovalForAll(operator, true, { from: owner }));
|
||||
});
|
||||
|
||||
it('reverts when trying to transferFrom', async function () {
|
||||
await assertRevert(this.token.transferFrom(owner, recipient, firstTokenId, { from: owner }));
|
||||
await shouldFail.reverting(this.token.transferFrom(owner, recipient, firstTokenId, { from: owner }));
|
||||
});
|
||||
|
||||
it('reverts when trying to safeTransferFrom', async function () {
|
||||
await assertRevert(this.token.safeTransferFrom(owner, recipient, firstTokenId, { from: owner }));
|
||||
await shouldFail.reverting(this.token.safeTransferFrom(owner, recipient, firstTokenId, { from: owner }));
|
||||
});
|
||||
|
||||
it('reverts when trying to safeTransferFrom with data', async function () {
|
||||
await assertRevert(
|
||||
sendTransaction(
|
||||
await shouldFail.reverting(
|
||||
send.transaction(
|
||||
this.token,
|
||||
'safeTransferFrom',
|
||||
'address,address,uint256,bytes',
|
||||
|
||||
Reference in New Issue
Block a user