ERC721 pausable token (#1154)

* ERC721 pausable token

* Reuse of ERC721 Basic behavior for Pausable, split view checks in paused state & style fixes

* [~] paused token behavior
pull/1226/merge
Roman Exempliarov 7 years ago committed by Nicolás Venturo
parent 48fe7b8cbf
commit 9e6307f34b
  1. 22
      contracts/mocks/ERC721PausableTokenMock.sol
  2. 42
      contracts/token/ERC721/ERC721PausableToken.sol
  3. 36
      test/token/ERC721/ERC721PausableToken.test.js
  4. 88
      test/token/ERC721/ERC721PausedToken.behavior.js

@ -0,0 +1,22 @@
pragma solidity ^0.4.24;
import "../token/ERC721/ERC721PausableToken.sol";
/**
* @title ERC721PausableTokenMock
* This mock just provides a public mint, burn and exists functions for testing purposes
*/
contract ERC721PausableTokenMock is ERC721PausableToken {
function mint(address _to, uint256 _tokenId) public {
super._mint(_to, _tokenId);
}
function burn(uint256 _tokenId) public {
super._burn(ownerOf(_tokenId), _tokenId);
}
function exists(uint256 _tokenId) public view returns (bool) {
return super._exists(_tokenId);
}
}

@ -0,0 +1,42 @@
pragma solidity ^0.4.24;
import "./ERC721BasicToken.sol";
import "../../lifecycle/Pausable.sol";
/**
* @title ERC721 Non-Fungible Pausable token
* @dev ERC721BasicToken modified with pausable transfers.
**/
contract ERC721PausableToken is ERC721BasicToken, Pausable {
function approve(
address _to,
uint256 _tokenId
)
public
whenNotPaused
{
super.approve(_to, _tokenId);
}
function setApprovalForAll(
address _to,
bool _approved
)
public
whenNotPaused
{
super.setApprovalForAll(_to, _approved);
}
function transferFrom(
address _from,
address _to,
uint256 _tokenId
)
public
whenNotPaused
{
super.transferFrom(_from, _to, _tokenId);
}
}

@ -0,0 +1,36 @@
const { shouldBehaveLikeERC721PausedToken } = require('./ERC721PausedToken.behavior');
const { shouldBehaveLikeERC721BasicToken } = require('./ERC721BasicToken.behavior');
const BigNumber = web3.BigNumber;
const ERC721PausableToken = artifacts.require('ERC721PausableTokenMock.sol');
require('chai')
.use(require('chai-bignumber')(BigNumber))
.should();
contract('ERC721PausableToken', function ([_, owner, recipient, operator, ...otherAccounts]) {
beforeEach(async function () {
this.token = await ERC721PausableToken.new({ from: owner });
});
context('when token is paused', function () {
beforeEach(async function () {
await this.token.pause({ from: owner });
});
shouldBehaveLikeERC721PausedToken(owner, [...otherAccounts]);
});
context('when token is not paused yet', function () {
shouldBehaveLikeERC721BasicToken([owner, ...otherAccounts]);
});
context('when token is paused and then unpaused', function () {
beforeEach(async function () {
await this.token.pause({ from: owner });
await this.token.unpause({ from: owner });
});
shouldBehaveLikeERC721BasicToken([owner, ...otherAccounts]);
});
});

@ -0,0 +1,88 @@
const { assertRevert } = require('../../helpers/assertRevert');
const { sendTransaction } = require('../../helpers/sendTransaction');
const BigNumber = web3.BigNumber;
require('chai')
.use(require('chai-bignumber')(BigNumber))
.should();
function shouldBehaveLikeERC721PausedToken (owner, [recipient, operator]) {
const firstTokenId = 1;
const mintedTokens = 1;
const mockData = '0x42';
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
describe('like a paused ERC721Token', function () {
beforeEach(async function () {
await this.token.mint(owner, firstTokenId, { from: owner });
});
it('reverts when trying to approve', async function () {
await assertRevert(this.token.approve(recipient, firstTokenId, { from: owner }));
});
it('reverts when trying to setApprovalForAll', async function () {
await assertRevert(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 }));
});
it('reverts when trying to safeTransferFrom', async function () {
await assertRevert(this.token.safeTransferFrom(owner, recipient, firstTokenId, { from: owner }));
});
it('reverts when trying to safeTransferFrom with data', async function () {
await assertRevert(
sendTransaction(
this.token,
'safeTransferFrom',
'address,address,uint256,bytes',
[owner, recipient, firstTokenId, mockData],
{ from: owner }
)
);
});
describe('getApproved', function () {
it('returns approved address', async function () {
const approvedAccount = await this.token.getApproved(firstTokenId);
approvedAccount.should.be.equal(ZERO_ADDRESS);
});
});
describe('balanceOf', function () {
it('returns the amount of tokens owned by the given address', async function () {
const balance = await this.token.balanceOf(owner);
balance.should.be.bignumber.equal(mintedTokens);
});
});
describe('ownerOf', function () {
it('returns the amount of tokens owned by the given address', async function () {
const ownerOfToken = await this.token.ownerOf(firstTokenId);
ownerOfToken.should.be.equal(owner);
});
});
describe('exists', function () {
it('should return token existance', async function () {
const result = await this.token.exists(firstTokenId);
result.should.eq(true);
});
});
describe('isApprovedForAll', function () {
it('returns the approval of the operator', async function () {
const isApproved = await this.token.isApprovedForAll(owner, operator);
isApproved.should.eq(false);
});
});
});
}
module.exports = {
shouldBehaveLikeERC721PausedToken,
};
Loading…
Cancel
Save