ERC721 pausable token (#1154)
* ERC721 pausable token * Reuse of ERC721 Basic behavior for Pausable, split view checks in paused state & style fixes * [~] paused token behaviorpull/1226/merge
parent
48fe7b8cbf
commit
9e6307f34b
@ -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…
Reference in new issue