Merge tag 'v2.2.0' of github.com:OpenZeppelin/openzeppelin-solidity
v2.2.0
This commit is contained in:
@ -54,7 +54,7 @@ contract('AllowanceCrowdsale', function ([_, investor, wallet, purchaser, tokenW
|
||||
});
|
||||
|
||||
describe('check remaining allowance', function () {
|
||||
it('should report correct allowace left', async function () {
|
||||
it('should report correct allowance left', async function () {
|
||||
const remainingAllowance = tokenAllowance.sub(expectedTokenAmount);
|
||||
await this.crowdsale.buyTokens(investor, { value: value, from: purchaser });
|
||||
(await this.crowdsale.remainingTokens()).should.be.bignumber.equal(remainingAllowance);
|
||||
@ -72,7 +72,7 @@ contract('AllowanceCrowdsale', function ([_, investor, wallet, purchaser, tokenW
|
||||
});
|
||||
});
|
||||
|
||||
describe('when token wallet is different from token address', function () {
|
||||
describe('when token wallet is the zero address', function () {
|
||||
it('creation reverts', async function () {
|
||||
this.token = await SimpleToken.new({ from: tokenWallet });
|
||||
await shouldFail.reverting(AllowanceCrowdsaleImpl.new(rate, wallet, this.token.address, ZERO_ADDRESS));
|
||||
|
||||
@ -31,7 +31,7 @@ contract('IncreasingPriceCrowdsale', function ([_, investor, wallet, purchaser])
|
||||
));
|
||||
});
|
||||
|
||||
it('reverts with a final equal to the initial rate', async function () {
|
||||
it('reverts with a final rate equal to the initial rate', async function () {
|
||||
await shouldFail.reverting(IncreasingPriceCrowdsaleImpl.new(
|
||||
this.startTime, this.closingTime, wallet, this.token.address, initialRate, initialRate
|
||||
));
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
const { BN, ether, shouldFail, time } = require('openzeppelin-test-helpers');
|
||||
const { BN, ether, expectEvent, shouldFail, time } = require('openzeppelin-test-helpers');
|
||||
|
||||
const TimedCrowdsaleImpl = artifacts.require('TimedCrowdsaleImpl');
|
||||
const SimpleToken = artifacts.require('SimpleTokenMock');
|
||||
@ -73,5 +73,62 @@ contract('TimedCrowdsale', function ([_, investor, wallet, purchaser]) {
|
||||
await shouldFail.reverting(this.crowdsale.buyTokens(investor, { value: value, from: purchaser }));
|
||||
});
|
||||
});
|
||||
|
||||
describe('extending closing time', function () {
|
||||
it('should not reduce duration', async function () {
|
||||
// Same date
|
||||
await shouldFail.reverting(this.crowdsale.extendTime(this.closingTime));
|
||||
|
||||
// Prescending date
|
||||
const newClosingTime = this.closingTime.sub(time.duration.seconds(1));
|
||||
await shouldFail.reverting(this.crowdsale.extendTime(newClosingTime));
|
||||
});
|
||||
|
||||
context('before crowdsale start', function () {
|
||||
beforeEach(async function () {
|
||||
(await this.crowdsale.isOpen()).should.equal(false);
|
||||
await shouldFail.reverting(this.crowdsale.send(value));
|
||||
});
|
||||
|
||||
it('it extends end time', async function () {
|
||||
const newClosingTime = this.closingTime.add(time.duration.days(1));
|
||||
const { logs } = await this.crowdsale.extendTime(newClosingTime);
|
||||
expectEvent.inLogs(logs, 'TimedCrowdsaleExtended', {
|
||||
prevClosingTime: this.closingTime,
|
||||
newClosingTime: newClosingTime,
|
||||
});
|
||||
(await this.crowdsale.closingTime()).should.be.bignumber.equal(newClosingTime);
|
||||
});
|
||||
});
|
||||
|
||||
context('after crowdsale start', function () {
|
||||
beforeEach(async function () {
|
||||
await time.increaseTo(this.openingTime);
|
||||
(await this.crowdsale.isOpen()).should.equal(true);
|
||||
await this.crowdsale.send(value);
|
||||
});
|
||||
|
||||
it('it extends end time', async function () {
|
||||
const newClosingTime = this.closingTime.add(time.duration.days(1));
|
||||
const { logs } = await this.crowdsale.extendTime(newClosingTime);
|
||||
expectEvent.inLogs(logs, 'TimedCrowdsaleExtended', {
|
||||
prevClosingTime: this.closingTime,
|
||||
newClosingTime: newClosingTime,
|
||||
});
|
||||
(await this.crowdsale.closingTime()).should.be.bignumber.equal(newClosingTime);
|
||||
});
|
||||
});
|
||||
|
||||
context('after crowdsale end', function () {
|
||||
beforeEach(async function () {
|
||||
await time.increaseTo(this.afterClosingTime);
|
||||
});
|
||||
|
||||
it('it reverts', async function () {
|
||||
const newClosingTime = await time.latest();
|
||||
await shouldFail.reverting(this.crowdsale.extendTime(newClosingTime));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
const { shouldFail } = require('openzeppelin-test-helpers');
|
||||
const { signMessage, toEthSignedMessageHash } = require('../helpers/sign');
|
||||
const { constants, shouldFail } = require('openzeppelin-test-helpers');
|
||||
const { ZERO_ADDRESS } = constants;
|
||||
const { toEthSignedMessageHash, fixSignature } = require('../helpers/sign');
|
||||
|
||||
const ECDSAMock = artifacts.require('ECDSAMock');
|
||||
|
||||
@ -19,10 +20,10 @@ contract('ECDSA', function ([_, anyone]) {
|
||||
const signatureWithoutVersion = '0x5d99b6f7f6d1f73d1a26497f2b1c89b24c0993913f86e9a2d02cd69887d9c94f3c880358579d811b21dd1b7fd9bb01c1d81d10e69f0384e675c32b39643be892';
|
||||
|
||||
context('with 00 as version value', function () {
|
||||
it('works', async function () {
|
||||
it('returns 0', async function () {
|
||||
const version = '00';
|
||||
const signature = signatureWithoutVersion + version;
|
||||
(await this.ecdsa.recover(TEST_MESSAGE, signature)).should.equal(signer);
|
||||
(await this.ecdsa.recover(TEST_MESSAGE, signature)).should.equal(ZERO_ADDRESS);
|
||||
});
|
||||
});
|
||||
|
||||
@ -40,8 +41,7 @@ contract('ECDSA', function ([_, anyone]) {
|
||||
// The only valid values are 0, 1, 27 and 28.
|
||||
const version = '02';
|
||||
const signature = signatureWithoutVersion + version;
|
||||
(await this.ecdsa.recover(TEST_MESSAGE, signature)).should.equal(
|
||||
'0x0000000000000000000000000000000000000000');
|
||||
(await this.ecdsa.recover(TEST_MESSAGE, signature)).should.equal(ZERO_ADDRESS);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -52,14 +52,14 @@ contract('ECDSA', function ([_, anyone]) {
|
||||
const signatureWithoutVersion = '0x331fe75a821c982f9127538858900d87d3ec1f9f737338ad67cad133fa48feff48e6fa0c18abc62e42820f05943e47af3e9fbe306ce74d64094bdf1691ee53e0';
|
||||
|
||||
context('with 01 as version value', function () {
|
||||
it('works', async function () {
|
||||
it('returns 0', async function () {
|
||||
const version = '01';
|
||||
const signature = signatureWithoutVersion + version;
|
||||
(await this.ecdsa.recover(TEST_MESSAGE, signature)).should.equal(signer);
|
||||
(await this.ecdsa.recover(TEST_MESSAGE, signature)).should.equal(ZERO_ADDRESS);
|
||||
});
|
||||
});
|
||||
|
||||
context('with 28 signature', function () {
|
||||
context('with 28 as version value', function () {
|
||||
it('works', async function () {
|
||||
const version = '1c'; // 28 = 1c.
|
||||
const signature = signatureWithoutVersion + version;
|
||||
@ -73,17 +73,26 @@ contract('ECDSA', function ([_, anyone]) {
|
||||
// The only valid values are 0, 1, 27 and 28.
|
||||
const version = '02';
|
||||
const signature = signatureWithoutVersion + version;
|
||||
(await this.ecdsa.recover(TEST_MESSAGE, signature)).should.equal(
|
||||
'0x0000000000000000000000000000000000000000');
|
||||
(await this.ecdsa.recover(TEST_MESSAGE, signature)).should.equal(ZERO_ADDRESS);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('with high-s value signature', function () {
|
||||
it('returns 0', async function () {
|
||||
const message = '0xb94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9';
|
||||
// eslint-disable-next-line max-len
|
||||
const highSSignature = '0xe742ff452d41413616a5bf43fe15dd88294e983d3d36206c2712f39083d638bde0a0fc89be718fbc1033e1d30d78be1c68081562ed2e97af876f286f3453231d1b';
|
||||
|
||||
(await this.ecdsa.recover(message, highSSignature)).should.equal(ZERO_ADDRESS);
|
||||
});
|
||||
});
|
||||
|
||||
context('using web3.eth.sign', function () {
|
||||
context('with correct signature', function () {
|
||||
it('returns signer address', async function () {
|
||||
// Create the signature
|
||||
const signature = await signMessage(anyone, TEST_MESSAGE);
|
||||
const signature = fixSignature(await web3.eth.sign(TEST_MESSAGE, anyone));
|
||||
|
||||
// Recover the signer address from the generated message and signature.
|
||||
(await this.ecdsa.recover(
|
||||
@ -96,23 +105,23 @@ contract('ECDSA', function ([_, anyone]) {
|
||||
context('with wrong signature', function () {
|
||||
it('does not return signer address', async function () {
|
||||
// Create the signature
|
||||
const signature = await signMessage(anyone, TEST_MESSAGE);
|
||||
const signature = await web3.eth.sign(TEST_MESSAGE, anyone);
|
||||
|
||||
// Recover the signer address from the generated message and wrong signature.
|
||||
(await this.ecdsa.recover(WRONG_MESSAGE, signature)).should.not.equal(anyone);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('with small hash', function () {
|
||||
// @TODO - remove `skip` once we upgrade to solc^0.5
|
||||
it.skip('reverts', async function () {
|
||||
// Create the signature
|
||||
const signature = await signMessage(anyone, TEST_MESSAGE);
|
||||
await shouldFail.reverting(
|
||||
this.ecdsa.recover(TEST_MESSAGE.substring(2), signature)
|
||||
);
|
||||
context('with small hash', function () {
|
||||
// @TODO - remove `skip` once we upgrade to solc^0.5
|
||||
it.skip('reverts', async function () {
|
||||
// Create the signature
|
||||
const signature = await web3.eth.sign(TEST_MESSAGE, anyone);
|
||||
await shouldFail.reverting(
|
||||
this.ecdsa.recover(TEST_MESSAGE.substring(2), signature)
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -1,37 +0,0 @@
|
||||
const { BN } = require('openzeppelin-test-helpers');
|
||||
|
||||
const CounterImpl = artifacts.require('CounterImpl');
|
||||
|
||||
const EXPECTED = [new BN(1), new BN(2), new BN(3), new BN(4)];
|
||||
const KEY1 = web3.utils.sha3('key1');
|
||||
const KEY2 = web3.utils.sha3('key2');
|
||||
|
||||
contract('Counter', function ([_, owner]) {
|
||||
beforeEach(async function () {
|
||||
this.mock = await CounterImpl.new({ from: owner });
|
||||
});
|
||||
|
||||
context('custom key', async function () {
|
||||
it('should return expected values', async function () {
|
||||
for (const expectedId of EXPECTED) {
|
||||
await this.mock.doThing(KEY1, { from: owner });
|
||||
const actualId = await this.mock.theId();
|
||||
actualId.should.be.bignumber.equal(expectedId);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
context('parallel keys', async function () {
|
||||
it('should return expected values for each counter', async function () {
|
||||
for (const expectedId of EXPECTED) {
|
||||
await this.mock.doThing(KEY1, { from: owner });
|
||||
let actualId = await this.mock.theId();
|
||||
actualId.should.be.bignumber.equal(expectedId);
|
||||
|
||||
await this.mock.doThing(KEY2, { from: owner });
|
||||
actualId = await this.mock.theId();
|
||||
actualId.should.be.bignumber.equal(expectedId);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
58
test/drafts/Counters.test.js
Normal file
58
test/drafts/Counters.test.js
Normal file
@ -0,0 +1,58 @@
|
||||
const { shouldFail } = require('openzeppelin-test-helpers');
|
||||
|
||||
const CountersImpl = artifacts.require('CountersImpl');
|
||||
|
||||
contract('Counters', function () {
|
||||
beforeEach(async function () {
|
||||
this.counter = await CountersImpl.new();
|
||||
});
|
||||
|
||||
it('starts at zero', async function () {
|
||||
(await this.counter.current()).should.be.bignumber.equal('0');
|
||||
});
|
||||
|
||||
describe('increment', function () {
|
||||
it('increments the current value by one', async function () {
|
||||
await this.counter.increment();
|
||||
(await this.counter.current()).should.be.bignumber.equal('1');
|
||||
});
|
||||
|
||||
it('can be called multiple times', async function () {
|
||||
await this.counter.increment();
|
||||
await this.counter.increment();
|
||||
await this.counter.increment();
|
||||
|
||||
(await this.counter.current()).should.be.bignumber.equal('3');
|
||||
});
|
||||
});
|
||||
|
||||
describe('decrement', function () {
|
||||
beforeEach(async function () {
|
||||
await this.counter.increment();
|
||||
(await this.counter.current()).should.be.bignumber.equal('1');
|
||||
});
|
||||
|
||||
it('decrements the current value by one', async function () {
|
||||
await this.counter.decrement();
|
||||
(await this.counter.current()).should.be.bignumber.equal('0');
|
||||
});
|
||||
|
||||
it('reverts if the current value is 0', async function () {
|
||||
await this.counter.decrement();
|
||||
await shouldFail.reverting(this.counter.decrement());
|
||||
});
|
||||
|
||||
it('can be called multiple times', async function () {
|
||||
await this.counter.increment();
|
||||
await this.counter.increment();
|
||||
|
||||
(await this.counter.current()).should.be.bignumber.equal('3');
|
||||
|
||||
await this.counter.decrement();
|
||||
await this.counter.decrement();
|
||||
await this.counter.decrement();
|
||||
|
||||
(await this.counter.current()).should.be.bignumber.equal('0');
|
||||
});
|
||||
});
|
||||
});
|
||||
23
test/drafts/ERC1046/ERC20Metadata.test.js
Normal file
23
test/drafts/ERC1046/ERC20Metadata.test.js
Normal file
@ -0,0 +1,23 @@
|
||||
require('openzeppelin-test-helpers');
|
||||
|
||||
const ERC20MetadataMock = artifacts.require('ERC20MetadataMock');
|
||||
|
||||
const metadataURI = 'https://example.com';
|
||||
|
||||
describe('ERC20Metadata', function () {
|
||||
beforeEach(async function () {
|
||||
this.token = await ERC20MetadataMock.new(metadataURI);
|
||||
});
|
||||
|
||||
it('responds with the metadata', async function () {
|
||||
(await this.token.tokenURI()).should.equal(metadataURI);
|
||||
});
|
||||
|
||||
describe('setTokenURI', function () {
|
||||
it('changes the original URI', async function () {
|
||||
const newMetadataURI = 'https://betterexample.com';
|
||||
await this.token.setTokenURI(newMetadataURI);
|
||||
(await this.token.tokenURI()).should.equal(newMetadataURI);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1,15 +0,0 @@
|
||||
require('openzeppelin-test-helpers');
|
||||
|
||||
const ERC20WithMetadataMock = artifacts.require('ERC20WithMetadataMock');
|
||||
|
||||
const metadataURI = 'https://example.com';
|
||||
|
||||
describe('ERC20WithMetadata', function () {
|
||||
beforeEach(async function () {
|
||||
this.token = await ERC20WithMetadataMock.new(metadataURI);
|
||||
});
|
||||
|
||||
it('responds with the metadata', async function () {
|
||||
(await this.token.tokenURI()).should.equal(metadataURI);
|
||||
});
|
||||
});
|
||||
@ -44,6 +44,40 @@ contract('ERC20Migrator', function ([_, owner, recipient, anotherAccount]) {
|
||||
});
|
||||
});
|
||||
|
||||
context('before starting the migration', function () {
|
||||
it('returns the zero address for the new token', async function () {
|
||||
(await this.migrator.newToken()).should.be.equal(ZERO_ADDRESS);
|
||||
});
|
||||
|
||||
describe('migrateAll', function () {
|
||||
const amount = totalSupply;
|
||||
|
||||
describe('when the approved balance is equal to the owned balance', function () {
|
||||
beforeEach('approving the whole balance to the new contract', async function () {
|
||||
await this.legacyToken.approve(this.migrator.address, amount, { from: owner });
|
||||
});
|
||||
|
||||
it('reverts', async function () {
|
||||
await shouldFail.reverting(this.migrator.migrateAll(owner));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('migrate', function () {
|
||||
const amount = new BN(50);
|
||||
|
||||
describe('when the amount is equal to the approved value', function () {
|
||||
beforeEach('approving tokens to the new contract', async function () {
|
||||
await this.legacyToken.approve(this.migrator.address, amount, { from: owner });
|
||||
});
|
||||
|
||||
it('reverts', async function () {
|
||||
await shouldFail.reverting(this.migrator.migrate(owner, amount));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('once migration began', function () {
|
||||
beforeEach('beginning migration', async function () {
|
||||
await this.newToken.addMinter(this.migrator.address);
|
||||
|
||||
197
test/drafts/ERC20Snapshot.test.js
Normal file
197
test/drafts/ERC20Snapshot.test.js
Normal file
@ -0,0 +1,197 @@
|
||||
const { BN, expectEvent, shouldFail } = require('openzeppelin-test-helpers');
|
||||
const ERC20SnapshotMock = artifacts.require('ERC20SnapshotMock');
|
||||
|
||||
contract('ERC20Snapshot', function ([_, initialHolder, recipient, anyone]) {
|
||||
const initialSupply = new BN(100);
|
||||
|
||||
beforeEach(async function () {
|
||||
this.token = await ERC20SnapshotMock.new(initialHolder, initialSupply);
|
||||
});
|
||||
|
||||
describe('snapshot', function () {
|
||||
it('emits a snapshot event', async function () {
|
||||
const { logs } = await this.token.snapshot();
|
||||
expectEvent.inLogs(logs, 'Snapshot');
|
||||
});
|
||||
|
||||
it('creates increasing snapshots ids, starting from 1', async function () {
|
||||
for (const id of ['1', '2', '3', '4', '5']) {
|
||||
const { logs } = await this.token.snapshot();
|
||||
expectEvent.inLogs(logs, 'Snapshot', { id });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('totalSupplyAt', function () {
|
||||
it('reverts with a snapshot id of 0', async function () {
|
||||
await shouldFail.reverting(this.token.totalSupplyAt(0));
|
||||
});
|
||||
|
||||
it('reverts with a not-yet-created snapshot id', async function () {
|
||||
await shouldFail.reverting(this.token.totalSupplyAt(1));
|
||||
});
|
||||
|
||||
context('with initial snapshot', function () {
|
||||
beforeEach(async function () {
|
||||
this.initialSnapshotId = new BN('1');
|
||||
|
||||
const { logs } = await this.token.snapshot();
|
||||
expectEvent.inLogs(logs, 'Snapshot', { id: this.initialSnapshotId });
|
||||
});
|
||||
|
||||
context('with no supply changes after the snapshot', function () {
|
||||
it('returns the current total supply', async function () {
|
||||
(await this.token.totalSupplyAt(this.initialSnapshotId)).should.be.bignumber.equal(initialSupply);
|
||||
});
|
||||
});
|
||||
|
||||
context('with supply changes after the snapshot', function () {
|
||||
beforeEach(async function () {
|
||||
await this.token.mint(anyone, new BN('50'));
|
||||
await this.token.burn(initialHolder, new BN('20'));
|
||||
});
|
||||
|
||||
it('returns the total supply before the changes', async function () {
|
||||
(await this.token.totalSupplyAt(this.initialSnapshotId)).should.be.bignumber.equal(initialSupply);
|
||||
});
|
||||
|
||||
context('with a second snapshot after supply changes', function () {
|
||||
beforeEach(async function () {
|
||||
this.secondSnapshotId = new BN('2');
|
||||
|
||||
const { logs } = await this.token.snapshot();
|
||||
expectEvent.inLogs(logs, 'Snapshot', { id: this.secondSnapshotId });
|
||||
});
|
||||
|
||||
it('snapshots return the supply before and after the changes', async function () {
|
||||
(await this.token.totalSupplyAt(this.initialSnapshotId)).should.be.bignumber.equal(initialSupply);
|
||||
|
||||
(await this.token.totalSupplyAt(this.secondSnapshotId)).should.be.bignumber.equal(
|
||||
await this.token.totalSupply()
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('with multiple snapshots after supply changes', function () {
|
||||
beforeEach(async function () {
|
||||
this.secondSnapshotIds = ['2', '3', '4'];
|
||||
|
||||
for (const id of this.secondSnapshotIds) {
|
||||
const { logs } = await this.token.snapshot();
|
||||
expectEvent.inLogs(logs, 'Snapshot', { id });
|
||||
}
|
||||
});
|
||||
|
||||
it('all posterior snapshots return the supply after the changes', async function () {
|
||||
(await this.token.totalSupplyAt(this.initialSnapshotId)).should.be.bignumber.equal(initialSupply);
|
||||
|
||||
const currentSupply = await this.token.totalSupply();
|
||||
|
||||
for (const id of this.secondSnapshotIds) {
|
||||
(await this.token.totalSupplyAt(id)).should.be.bignumber.equal(currentSupply);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('balanceOfAt', function () {
|
||||
it('reverts with a snapshot id of 0', async function () {
|
||||
await shouldFail.reverting(this.token.balanceOfAt(anyone, 0));
|
||||
});
|
||||
|
||||
it('reverts with a not-yet-created snapshot id', async function () {
|
||||
await shouldFail.reverting(this.token.balanceOfAt(anyone, 1));
|
||||
});
|
||||
|
||||
context('with initial snapshot', function () {
|
||||
beforeEach(async function () {
|
||||
this.initialSnapshotId = new BN('1');
|
||||
|
||||
const { logs } = await this.token.snapshot();
|
||||
expectEvent.inLogs(logs, 'Snapshot', { id: this.initialSnapshotId });
|
||||
});
|
||||
|
||||
context('with no balance changes after the snapshot', function () {
|
||||
it('returns the current balance for all accounts', async function () {
|
||||
(await this.token.balanceOfAt(initialHolder, this.initialSnapshotId))
|
||||
.should.be.bignumber.equal(initialSupply);
|
||||
(await this.token.balanceOfAt(recipient, this.initialSnapshotId)).should.be.bignumber.equal('0');
|
||||
(await this.token.balanceOfAt(anyone, this.initialSnapshotId)).should.be.bignumber.equal('0');
|
||||
});
|
||||
});
|
||||
|
||||
context('with balance changes after the snapshot', function () {
|
||||
beforeEach(async function () {
|
||||
await this.token.transfer(recipient, new BN('10'), { from: initialHolder });
|
||||
await this.token.mint(recipient, new BN('50'));
|
||||
await this.token.burn(initialHolder, new BN('20'));
|
||||
});
|
||||
|
||||
it('returns the balances before the changes', async function () {
|
||||
(await this.token.balanceOfAt(initialHolder, this.initialSnapshotId))
|
||||
.should.be.bignumber.equal(initialSupply);
|
||||
(await this.token.balanceOfAt(recipient, this.initialSnapshotId)).should.be.bignumber.equal('0');
|
||||
(await this.token.balanceOfAt(anyone, this.initialSnapshotId)).should.be.bignumber.equal('0');
|
||||
});
|
||||
|
||||
context('with a second snapshot after supply changes', function () {
|
||||
beforeEach(async function () {
|
||||
this.secondSnapshotId = new BN('2');
|
||||
|
||||
const { logs } = await this.token.snapshot();
|
||||
expectEvent.inLogs(logs, 'Snapshot', { id: this.secondSnapshotId });
|
||||
});
|
||||
|
||||
it('snapshots return the balances before and after the changes', async function () {
|
||||
(await this.token.balanceOfAt(initialHolder, this.initialSnapshotId))
|
||||
.should.be.bignumber.equal(initialSupply);
|
||||
(await this.token.balanceOfAt(recipient, this.initialSnapshotId)).should.be.bignumber.equal('0');
|
||||
(await this.token.balanceOfAt(anyone, this.initialSnapshotId)).should.be.bignumber.equal('0');
|
||||
|
||||
(await this.token.balanceOfAt(initialHolder, this.secondSnapshotId)).should.be.bignumber.equal(
|
||||
await this.token.balanceOf(initialHolder)
|
||||
);
|
||||
(await this.token.balanceOfAt(recipient, this.secondSnapshotId)).should.be.bignumber.equal(
|
||||
await this.token.balanceOf(recipient)
|
||||
);
|
||||
(await this.token.balanceOfAt(anyone, this.secondSnapshotId)).should.be.bignumber.equal(
|
||||
await this.token.balanceOf(anyone)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('with multiple snapshots after supply changes', function () {
|
||||
beforeEach(async function () {
|
||||
this.secondSnapshotIds = ['2', '3', '4'];
|
||||
|
||||
for (const id of this.secondSnapshotIds) {
|
||||
const { logs } = await this.token.snapshot();
|
||||
expectEvent.inLogs(logs, 'Snapshot', { id });
|
||||
}
|
||||
});
|
||||
|
||||
it('all posterior snapshots return the supply after the changes', async function () {
|
||||
(await this.token.balanceOfAt(initialHolder, this.initialSnapshotId))
|
||||
.should.be.bignumber.equal(initialSupply);
|
||||
(await this.token.balanceOfAt(recipient, this.initialSnapshotId)).should.be.bignumber.equal('0');
|
||||
(await this.token.balanceOfAt(anyone, this.initialSnapshotId)).should.be.bignumber.equal('0');
|
||||
|
||||
for (const id of this.secondSnapshotIds) {
|
||||
(await this.token.balanceOfAt(initialHolder, id)).should.be.bignumber.equal(
|
||||
await this.token.balanceOf(initialHolder)
|
||||
);
|
||||
(await this.token.balanceOfAt(recipient, id)).should.be.bignumber.equal(
|
||||
await this.token.balanceOf(recipient)
|
||||
);
|
||||
(await this.token.balanceOfAt(anyone, id)).should.be.bignumber.equal(
|
||||
await this.token.balanceOf(anyone)
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -8,34 +8,43 @@ contract('SignedSafeMath', function () {
|
||||
this.safeMath = await SignedSafeMathMock.new();
|
||||
});
|
||||
|
||||
async function testCommutative (fn, lhs, rhs, expected) {
|
||||
(await fn(lhs, rhs)).should.be.bignumber.equal(expected);
|
||||
(await fn(rhs, lhs)).should.be.bignumber.equal(expected);
|
||||
}
|
||||
|
||||
async function testFailsCommutative (fn, lhs, rhs) {
|
||||
await shouldFail.reverting(fn(lhs, rhs));
|
||||
await shouldFail.reverting(fn(rhs, lhs));
|
||||
}
|
||||
|
||||
describe('add', function () {
|
||||
it('adds correctly if it does not overflow and the result is positve', async function () {
|
||||
it('adds correctly if it does not overflow and the result is positive', async function () {
|
||||
const a = new BN('1234');
|
||||
const b = new BN('5678');
|
||||
|
||||
(await this.safeMath.add(a, b)).should.be.bignumber.equal(a.add(b));
|
||||
await testCommutative(this.safeMath.add, a, b, a.add(b));
|
||||
});
|
||||
|
||||
it('adds correctly if it does not overflow and the result is negative', async function () {
|
||||
const a = MAX_INT256;
|
||||
const b = MIN_INT256;
|
||||
|
||||
const result = await this.safeMath.add(a, b);
|
||||
result.should.be.bignumber.equal(a.add(b));
|
||||
await testCommutative(this.safeMath.add, a, b, a.add(b));
|
||||
});
|
||||
|
||||
it('reverts on positive addition overflow', async function () {
|
||||
const a = MAX_INT256;
|
||||
const b = new BN('1');
|
||||
|
||||
await shouldFail.reverting(this.safeMath.add(a, b));
|
||||
await testFailsCommutative(this.safeMath.add, a, b);
|
||||
});
|
||||
|
||||
it('reverts on negative addition overflow', async function () {
|
||||
const a = MIN_INT256;
|
||||
const b = new BN('-1');
|
||||
|
||||
await shouldFail.reverting(this.safeMath.add(a, b));
|
||||
await testFailsCommutative(this.safeMath.add, a, b);
|
||||
});
|
||||
});
|
||||
|
||||
@ -76,37 +85,28 @@ contract('SignedSafeMath', function () {
|
||||
const a = new BN('5678');
|
||||
const b = new BN('-1234');
|
||||
|
||||
const result = await this.safeMath.mul(a, b);
|
||||
result.should.be.bignumber.equal(a.mul(b));
|
||||
await testCommutative(this.safeMath.mul, a, b, a.mul(b));
|
||||
});
|
||||
|
||||
it('handles a zero product correctly', async function () {
|
||||
it('multiplies by zero correctly', async function () {
|
||||
const a = new BN('0');
|
||||
const b = new BN('5678');
|
||||
|
||||
const result = await this.safeMath.mul(a, b);
|
||||
result.should.be.bignumber.equal(a.mul(b));
|
||||
await testCommutative(this.safeMath.mul, a, b, '0');
|
||||
});
|
||||
|
||||
it('reverts on multiplication overflow, positive operands', async function () {
|
||||
const a = MAX_INT256;
|
||||
const b = new BN('2');
|
||||
|
||||
await shouldFail.reverting(this.safeMath.mul(a, b));
|
||||
await testFailsCommutative(this.safeMath.mul, a, b);
|
||||
});
|
||||
|
||||
it('reverts when minimum integer is multiplied by -1', async function () {
|
||||
const a = MIN_INT256;
|
||||
const b = new BN('-1');
|
||||
|
||||
await shouldFail.reverting(this.safeMath.mul(a, b));
|
||||
});
|
||||
|
||||
it('reverts when -1 is multiplied by minimum integer', async function () {
|
||||
const a = new BN('-1');
|
||||
const b = MIN_INT256;
|
||||
|
||||
await shouldFail.reverting(this.safeMath.mul(a, b));
|
||||
await testFailsCommutative(this.safeMath.mul, a, b);
|
||||
});
|
||||
});
|
||||
|
||||
@ -119,7 +119,21 @@ contract('SignedSafeMath', function () {
|
||||
result.should.be.bignumber.equal(a.div(b));
|
||||
});
|
||||
|
||||
it('reverts on zero division', async function () {
|
||||
it('divides zero correctly', async function () {
|
||||
const a = new BN('0');
|
||||
const b = new BN('5678');
|
||||
|
||||
(await this.safeMath.div(a, b)).should.be.bignumber.equal('0');
|
||||
});
|
||||
|
||||
it('returns complete number result on non-even division', async function () {
|
||||
const a = new BN('7000');
|
||||
const b = new BN('5678');
|
||||
|
||||
(await this.safeMath.div(a, b)).should.be.bignumber.equal('1');
|
||||
});
|
||||
|
||||
it('reverts on division by zero', async function () {
|
||||
const a = new BN('-5678');
|
||||
const b = new BN('0');
|
||||
|
||||
|
||||
@ -9,9 +9,21 @@ function toEthSignedMessageHash (messageHex) {
|
||||
return web3.utils.sha3(Buffer.concat([prefix, messageBuffer]));
|
||||
}
|
||||
|
||||
function fixSignature (signature) {
|
||||
// in geth its always 27/28, in ganache its 0/1. Change to 27/28 to prevent
|
||||
// signature malleability if version is 0/1
|
||||
// see https://github.com/ethereum/go-ethereum/blob/v1.8.23/internal/ethapi/api.go#L465
|
||||
let v = parseInt(signature.slice(130, 132), 16);
|
||||
if (v < 27) {
|
||||
v += 27;
|
||||
}
|
||||
const vHex = v.toString(16);
|
||||
return signature.slice(0, 130) + vHex;
|
||||
}
|
||||
|
||||
// signs message in node (ganache auto-applies "Ethereum Signed Message" prefix)
|
||||
const signMessage = (signer, messageHex = '0x') => {
|
||||
return web3.eth.sign(messageHex, signer);
|
||||
async function signMessage (signer, messageHex = '0x') {
|
||||
return fixSignature(await web3.eth.sign(messageHex, signer));
|
||||
};
|
||||
|
||||
/**
|
||||
@ -50,5 +62,6 @@ const getSignFor = (contract, signer) => (redeemer, methodName, methodArgs = [])
|
||||
module.exports = {
|
||||
signMessage,
|
||||
toEthSignedMessageHash,
|
||||
fixSignature,
|
||||
getSignFor,
|
||||
};
|
||||
|
||||
@ -17,7 +17,7 @@ contract('Pausable', function ([_, pauser, otherPauser, anyone, ...otherAccounts
|
||||
shouldBehaveLikePublicRole(pauser, otherPauser, otherAccounts, 'pauser');
|
||||
});
|
||||
|
||||
context('when unapused', function () {
|
||||
context('when unpaused', function () {
|
||||
beforeEach(async function () {
|
||||
(await this.pausable.paused()).should.equal(false);
|
||||
});
|
||||
|
||||
@ -8,19 +8,29 @@ contract('SafeMath', function () {
|
||||
this.safeMath = await SafeMathMock.new();
|
||||
});
|
||||
|
||||
async function testCommutative (fn, lhs, rhs, expected) {
|
||||
(await fn(lhs, rhs)).should.be.bignumber.equal(expected);
|
||||
(await fn(rhs, lhs)).should.be.bignumber.equal(expected);
|
||||
}
|
||||
|
||||
async function testFailsCommutative (fn, lhs, rhs) {
|
||||
await shouldFail.reverting(fn(lhs, rhs));
|
||||
await shouldFail.reverting(fn(rhs, lhs));
|
||||
}
|
||||
|
||||
describe('add', function () {
|
||||
it('adds correctly', async function () {
|
||||
const a = new BN('5678');
|
||||
const b = new BN('1234');
|
||||
|
||||
(await this.safeMath.add(a, b)).should.be.bignumber.equal(a.add(b));
|
||||
await testCommutative(this.safeMath.add, a, b, a.add(b));
|
||||
});
|
||||
|
||||
it('reverts on addition overflow', async function () {
|
||||
const a = MAX_UINT256;
|
||||
const b = new BN('1');
|
||||
|
||||
await shouldFail.reverting(this.safeMath.add(a, b));
|
||||
await testFailsCommutative(this.safeMath.add, a, b);
|
||||
});
|
||||
});
|
||||
|
||||
@ -45,28 +55,21 @@ contract('SafeMath', function () {
|
||||
const a = new BN('1234');
|
||||
const b = new BN('5678');
|
||||
|
||||
(await this.safeMath.mul(a, b)).should.be.bignumber.equal(a.mul(b));
|
||||
await testCommutative(this.safeMath.mul, a, b, a.mul(b));
|
||||
});
|
||||
|
||||
it('handles a zero product correctly (first number as zero)', async function () {
|
||||
it('multiplies by zero correctly', async function () {
|
||||
const a = new BN('0');
|
||||
const b = new BN('5678');
|
||||
|
||||
(await this.safeMath.mul(a, b)).should.be.bignumber.equal(a.mul(b));
|
||||
});
|
||||
|
||||
it('handles a zero product correctly (second number as zero)', async function () {
|
||||
const a = new BN('5678');
|
||||
const b = new BN('0');
|
||||
|
||||
(await this.safeMath.mul(a, b)).should.be.bignumber.equal(a.mul(b));
|
||||
await testCommutative(this.safeMath.mul, a, b, '0');
|
||||
});
|
||||
|
||||
it('reverts on multiplication overflow', async function () {
|
||||
const a = MAX_UINT256;
|
||||
const b = new BN('2');
|
||||
|
||||
await shouldFail.reverting(this.safeMath.mul(a, b));
|
||||
await testFailsCommutative(this.safeMath.mul, a, b);
|
||||
});
|
||||
});
|
||||
|
||||
@ -92,7 +95,7 @@ contract('SafeMath', function () {
|
||||
(await this.safeMath.div(a, b)).should.be.bignumber.equal('1');
|
||||
});
|
||||
|
||||
it('reverts on zero division', async function () {
|
||||
it('reverts on divison by zero', async function () {
|
||||
const a = new BN('5678');
|
||||
const b = new BN('0');
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ function shouldBehaveLikeOwnable (owner, [anyone]) {
|
||||
(await this.ownable.isOwner({ from: anyone })).should.be.equal(true);
|
||||
});
|
||||
|
||||
it('should prevent non-owners from transfering', async function () {
|
||||
it('should prevent non-owners from transferring', async function () {
|
||||
await shouldFail.reverting(this.ownable.transferOwnership(anyone, { from: anyone }));
|
||||
});
|
||||
|
||||
|
||||
@ -29,7 +29,7 @@ contract('Secondary', function ([_, primary, newPrimary, anyone]) {
|
||||
(await this.secondary.primary()).should.equal(newPrimary);
|
||||
});
|
||||
|
||||
it('reverts when transfering to the null address', async function () {
|
||||
it('reverts when transferring to the null address', async function () {
|
||||
await shouldFail.reverting(this.secondary.transferPrimary(ZERO_ADDRESS, { from: primary }));
|
||||
});
|
||||
|
||||
|
||||
@ -84,19 +84,19 @@ contract('PaymentSplitter', function ([_, owner, payee1, payee2, payee3, nonpaye
|
||||
const initAmount1 = await balance.current(payee1);
|
||||
const { logs: logs1 } = await this.contract.release(payee1, { gasPrice: 0 });
|
||||
const profit1 = (await balance.current(payee1)).sub(initAmount1);
|
||||
profit1.should.be.bignumber.equal(ether('0.20', 'ether'));
|
||||
profit1.should.be.bignumber.equal(ether('0.20'));
|
||||
expectEvent.inLogs(logs1, 'PaymentReleased', { to: payee1, amount: profit1 });
|
||||
|
||||
const initAmount2 = await balance.current(payee2);
|
||||
const { logs: logs2 } = await this.contract.release(payee2, { gasPrice: 0 });
|
||||
const profit2 = (await balance.current(payee2)).sub(initAmount2);
|
||||
profit2.should.be.bignumber.equal(ether('0.10', 'ether'));
|
||||
profit2.should.be.bignumber.equal(ether('0.10'));
|
||||
expectEvent.inLogs(logs2, 'PaymentReleased', { to: payee2, amount: profit2 });
|
||||
|
||||
const initAmount3 = await balance.current(payee3);
|
||||
const { logs: logs3 } = await this.contract.release(payee3, { gasPrice: 0 });
|
||||
const profit3 = (await balance.current(payee3)).sub(initAmount3);
|
||||
profit3.should.be.bignumber.equal(ether('0.70', 'ether'));
|
||||
profit3.should.be.bignumber.equal(ether('0.70'));
|
||||
expectEvent.inLogs(logs3, 'PaymentReleased', { to: payee3, amount: profit3 });
|
||||
|
||||
// end balance should be zero
|
||||
|
||||
@ -73,89 +73,6 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) {
|
||||
});
|
||||
});
|
||||
|
||||
describe('approve', function () {
|
||||
describe('when the spender is not the zero address', function () {
|
||||
const spender = recipient;
|
||||
|
||||
describe('when the sender has enough balance', function () {
|
||||
const amount = initialSupply;
|
||||
|
||||
it('emits an approval event', async function () {
|
||||
const { logs } = await this.token.approve(spender, amount, { from: initialHolder });
|
||||
|
||||
expectEvent.inLogs(logs, 'Approval', {
|
||||
owner: initialHolder,
|
||||
spender: spender,
|
||||
value: amount,
|
||||
});
|
||||
});
|
||||
|
||||
describe('when there was no approved amount before', function () {
|
||||
it('approves the requested amount', async function () {
|
||||
await this.token.approve(spender, amount, { from: initialHolder });
|
||||
|
||||
(await this.token.allowance(initialHolder, spender)).should.be.bignumber.equal(amount);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the spender had an approved amount', function () {
|
||||
beforeEach(async function () {
|
||||
await this.token.approve(spender, new BN(1), { from: initialHolder });
|
||||
});
|
||||
|
||||
it('approves the requested amount and replaces the previous one', async function () {
|
||||
await this.token.approve(spender, amount, { from: initialHolder });
|
||||
|
||||
(await this.token.allowance(initialHolder, spender)).should.be.bignumber.equal(amount);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the sender does not have enough balance', function () {
|
||||
const amount = initialSupply.addn(1);
|
||||
|
||||
it('emits an approval event', async function () {
|
||||
const { logs } = await this.token.approve(spender, amount, { from: initialHolder });
|
||||
|
||||
expectEvent.inLogs(logs, 'Approval', {
|
||||
owner: initialHolder,
|
||||
spender: spender,
|
||||
value: amount,
|
||||
});
|
||||
});
|
||||
|
||||
describe('when there was no approved amount before', function () {
|
||||
it('approves the requested amount', async function () {
|
||||
await this.token.approve(spender, amount, { from: initialHolder });
|
||||
|
||||
(await this.token.allowance(initialHolder, spender)).should.be.bignumber.equal(amount);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the spender had an approved amount', function () {
|
||||
beforeEach(async function () {
|
||||
await this.token.approve(spender, new BN(1), { from: initialHolder });
|
||||
});
|
||||
|
||||
it('approves the requested amount and replaces the previous one', async function () {
|
||||
await this.token.approve(spender, amount, { from: initialHolder });
|
||||
|
||||
(await this.token.allowance(initialHolder, spender)).should.be.bignumber.equal(amount);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the spender is the zero address', function () {
|
||||
const amount = initialSupply;
|
||||
const spender = ZERO_ADDRESS;
|
||||
|
||||
it('reverts', async function () {
|
||||
await shouldFail.reverting(this.token.approve(spender, amount, { from: initialHolder }));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('transfer from', function () {
|
||||
const spender = recipient;
|
||||
|
||||
@ -546,4 +463,100 @@ contract('ERC20', function ([_, initialHolder, recipient, anotherAccount]) {
|
||||
describeBurnFrom('for less amount than allowance', allowance.subn(1));
|
||||
});
|
||||
});
|
||||
|
||||
describe('approve', function () {
|
||||
testApprove(initialHolder, recipient, initialSupply, function (owner, spender, amount) {
|
||||
return this.token.approve(spender, amount, { from: owner });
|
||||
});
|
||||
});
|
||||
|
||||
describe('_approve', function () {
|
||||
testApprove(initialHolder, recipient, initialSupply, function (owner, spender, amount) {
|
||||
return this.token.approveInternal(owner, spender, amount);
|
||||
});
|
||||
|
||||
describe('when the owner is the zero address', function () {
|
||||
it('reverts', async function () {
|
||||
await shouldFail.reverting(this.token.approveInternal(ZERO_ADDRESS, recipient, initialSupply));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function testApprove (owner, spender, supply, approve) {
|
||||
describe('when the spender is not the zero address', function () {
|
||||
describe('when the sender has enough balance', function () {
|
||||
const amount = supply;
|
||||
|
||||
it('emits an approval event', async function () {
|
||||
const { logs } = await approve.call(this, owner, spender, amount);
|
||||
|
||||
expectEvent.inLogs(logs, 'Approval', {
|
||||
owner: owner,
|
||||
spender: spender,
|
||||
value: amount,
|
||||
});
|
||||
});
|
||||
|
||||
describe('when there was no approved amount before', function () {
|
||||
it('approves the requested amount', async function () {
|
||||
await approve.call(this, owner, spender, amount);
|
||||
|
||||
(await this.token.allowance(owner, spender)).should.be.bignumber.equal(amount);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the spender had an approved amount', function () {
|
||||
beforeEach(async function () {
|
||||
await approve.call(this, owner, spender, new BN(1));
|
||||
});
|
||||
|
||||
it('approves the requested amount and replaces the previous one', async function () {
|
||||
await approve.call(this, owner, spender, amount);
|
||||
|
||||
(await this.token.allowance(owner, spender)).should.be.bignumber.equal(amount);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the sender does not have enough balance', function () {
|
||||
const amount = supply.addn(1);
|
||||
|
||||
it('emits an approval event', async function () {
|
||||
const { logs } = await approve.call(this, owner, spender, amount);
|
||||
|
||||
expectEvent.inLogs(logs, 'Approval', {
|
||||
owner: owner,
|
||||
spender: spender,
|
||||
value: amount,
|
||||
});
|
||||
});
|
||||
|
||||
describe('when there was no approved amount before', function () {
|
||||
it('approves the requested amount', async function () {
|
||||
await approve.call(this, owner, spender, amount);
|
||||
|
||||
(await this.token.allowance(owner, spender)).should.be.bignumber.equal(amount);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the spender had an approved amount', function () {
|
||||
beforeEach(async function () {
|
||||
await approve.call(this, owner, spender, new BN(1));
|
||||
});
|
||||
|
||||
it('approves the requested amount and replaces the previous one', async function () {
|
||||
await approve.call(this, owner, spender, amount);
|
||||
|
||||
(await this.token.allowance(owner, spender)).should.be.bignumber.equal(amount);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the spender is the zero address', function () {
|
||||
it('reverts', async function () {
|
||||
await shouldFail.reverting(approve.call(this, owner, ZERO_ADDRESS, supply));
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,91 +1,122 @@
|
||||
const { shouldFail } = require('openzeppelin-test-helpers');
|
||||
|
||||
const SafeERC20Helper = artifacts.require('SafeERC20Helper');
|
||||
const ERC20ReturnFalseMock = artifacts.require('ERC20ReturnFalseMock');
|
||||
const ERC20ReturnTrueMock = artifacts.require('ERC20ReturnTrueMock');
|
||||
const ERC20NoReturnMock = artifacts.require('ERC20NoReturnMock');
|
||||
const SafeERC20Wrapper = artifacts.require('SafeERC20Wrapper');
|
||||
|
||||
contract('SafeERC20', function () {
|
||||
beforeEach(async function () {
|
||||
this.helper = await SafeERC20Helper.new();
|
||||
contract('SafeERC20', function ([_, hasNoCode]) {
|
||||
describe('with address that has no contract code', function () {
|
||||
beforeEach(async function () {
|
||||
this.wrapper = await SafeERC20Wrapper.new(hasNoCode);
|
||||
});
|
||||
|
||||
shouldRevertOnAllCalls();
|
||||
});
|
||||
|
||||
describe('with token that returns false on all calls', function () {
|
||||
it('reverts on transfer', async function () {
|
||||
await shouldFail.reverting(this.helper.doFailingTransfer());
|
||||
beforeEach(async function () {
|
||||
this.wrapper = await SafeERC20Wrapper.new((await ERC20ReturnFalseMock.new()).address);
|
||||
});
|
||||
|
||||
it('reverts on transferFrom', async function () {
|
||||
await shouldFail.reverting(this.helper.doFailingTransferFrom());
|
||||
});
|
||||
|
||||
it('reverts on approve', async function () {
|
||||
await shouldFail.reverting(this.helper.doFailingApprove());
|
||||
});
|
||||
|
||||
it('reverts on increaseAllowance', async function () {
|
||||
await shouldFail.reverting(this.helper.doFailingIncreaseAllowance());
|
||||
});
|
||||
|
||||
it('reverts on decreaseAllowance', async function () {
|
||||
await shouldFail.reverting(this.helper.doFailingDecreaseAllowance());
|
||||
});
|
||||
shouldRevertOnAllCalls();
|
||||
});
|
||||
|
||||
describe('with token that returns true on all calls', function () {
|
||||
it('doesn\'t revert on transfer', async function () {
|
||||
await this.helper.doSucceedingTransfer();
|
||||
beforeEach(async function () {
|
||||
this.wrapper = await SafeERC20Wrapper.new((await ERC20ReturnTrueMock.new()).address);
|
||||
});
|
||||
|
||||
it('doesn\'t revert on transferFrom', async function () {
|
||||
await this.helper.doSucceedingTransferFrom();
|
||||
shouldOnlyRevertOnErrors();
|
||||
});
|
||||
|
||||
describe('with token that returns no boolean values', function () {
|
||||
beforeEach(async function () {
|
||||
this.wrapper = await SafeERC20Wrapper.new((await ERC20NoReturnMock.new()).address);
|
||||
});
|
||||
|
||||
describe('approvals', function () {
|
||||
context('with zero allowance', function () {
|
||||
beforeEach(async function () {
|
||||
await this.helper.setAllowance(0);
|
||||
});
|
||||
shouldOnlyRevertOnErrors();
|
||||
});
|
||||
});
|
||||
|
||||
it('doesn\'t revert when approving a non-zero allowance', async function () {
|
||||
await this.helper.doSucceedingApprove(100);
|
||||
});
|
||||
function shouldRevertOnAllCalls () {
|
||||
it('reverts on transfer', async function () {
|
||||
await shouldFail.reverting(this.wrapper.transfer());
|
||||
});
|
||||
|
||||
it('doesn\'t revert when approving a zero allowance', async function () {
|
||||
await this.helper.doSucceedingApprove(0);
|
||||
});
|
||||
it('reverts on transferFrom', async function () {
|
||||
await shouldFail.reverting(this.wrapper.transferFrom());
|
||||
});
|
||||
|
||||
it('doesn\'t revert when increasing the allowance', async function () {
|
||||
await this.helper.doSucceedingIncreaseAllowance(10);
|
||||
});
|
||||
it('reverts on approve', async function () {
|
||||
await shouldFail.reverting(this.wrapper.approve(0));
|
||||
});
|
||||
|
||||
it('reverts when decreasing the allowance', async function () {
|
||||
await shouldFail.reverting(this.helper.doSucceedingDecreaseAllowance(10));
|
||||
});
|
||||
it('reverts on increaseAllowance', async function () {
|
||||
await shouldFail.reverting(this.wrapper.increaseAllowance(0));
|
||||
});
|
||||
|
||||
it('reverts on decreaseAllowance', async function () {
|
||||
await shouldFail.reverting(this.wrapper.decreaseAllowance(0));
|
||||
});
|
||||
}
|
||||
|
||||
function shouldOnlyRevertOnErrors () {
|
||||
it('doesn\'t revert on transfer', async function () {
|
||||
await this.wrapper.transfer();
|
||||
});
|
||||
|
||||
it('doesn\'t revert on transferFrom', async function () {
|
||||
await this.wrapper.transferFrom();
|
||||
});
|
||||
|
||||
describe('approvals', function () {
|
||||
context('with zero allowance', function () {
|
||||
beforeEach(async function () {
|
||||
await this.wrapper.setAllowance(0);
|
||||
});
|
||||
|
||||
context('with non-zero allowance', function () {
|
||||
beforeEach(async function () {
|
||||
await this.helper.setAllowance(100);
|
||||
});
|
||||
it('doesn\'t revert when approving a non-zero allowance', async function () {
|
||||
await this.wrapper.approve(100);
|
||||
});
|
||||
|
||||
it('reverts when approving a non-zero allowance', async function () {
|
||||
await shouldFail.reverting(this.helper.doSucceedingApprove(20));
|
||||
});
|
||||
it('doesn\'t revert when approving a zero allowance', async function () {
|
||||
await this.wrapper.approve(0);
|
||||
});
|
||||
|
||||
it('doesn\'t revert when approving a zero allowance', async function () {
|
||||
await this.helper.doSucceedingApprove(0);
|
||||
});
|
||||
it('doesn\'t revert when increasing the allowance', async function () {
|
||||
await this.wrapper.increaseAllowance(10);
|
||||
});
|
||||
|
||||
it('doesn\'t revert when increasing the allowance', async function () {
|
||||
await this.helper.doSucceedingIncreaseAllowance(10);
|
||||
});
|
||||
it('reverts when decreasing the allowance', async function () {
|
||||
await shouldFail.reverting(this.wrapper.decreaseAllowance(10));
|
||||
});
|
||||
});
|
||||
|
||||
it('doesn\'t revert when decreasing the allowance to a positive value', async function () {
|
||||
await this.helper.doSucceedingDecreaseAllowance(50);
|
||||
});
|
||||
context('with non-zero allowance', function () {
|
||||
beforeEach(async function () {
|
||||
await this.wrapper.setAllowance(100);
|
||||
});
|
||||
|
||||
it('reverts when decreasing the allowance to a negative value', async function () {
|
||||
await shouldFail.reverting(this.helper.doSucceedingDecreaseAllowance(200));
|
||||
});
|
||||
it('reverts when approving a non-zero allowance', async function () {
|
||||
await shouldFail.reverting(this.wrapper.approve(20));
|
||||
});
|
||||
|
||||
it('doesn\'t revert when approving a zero allowance', async function () {
|
||||
await this.wrapper.approve(0);
|
||||
});
|
||||
|
||||
it('doesn\'t revert when increasing the allowance', async function () {
|
||||
await this.wrapper.increaseAllowance(10);
|
||||
});
|
||||
|
||||
it('doesn\'t revert when decreasing the allowance to a positive value', async function () {
|
||||
await this.wrapper.decreaseAllowance(50);
|
||||
});
|
||||
|
||||
it('reverts when decreasing the allowance to a negative value', async function () {
|
||||
await shouldFail.reverting(this.wrapper.decreaseAllowance(200));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ function shouldBehaveLikeERC721PausedToken (owner, [recipient, operator]) {
|
||||
});
|
||||
|
||||
describe('exists', function () {
|
||||
it('should return token existance', async function () {
|
||||
it('should return token existence', async function () {
|
||||
(await this.token.exists(firstTokenId)).should.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user