Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added PausableCrowdsale contract #832

Merged
merged 32 commits into from
Dec 14, 2018
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
7f34509
Added PausableCrowdsale contract
TalAter Mar 22, 2018
e47775c
Merge branch 'master' into feature/pausable-crowdsale
Jun 15, 2018
3a1bbe6
Merge branch 'master' into feature/pausable-crowdsale
TalAter Jul 8, 2018
35e799c
Changed inheritance order to prevent "Linearization of inheritance gr…
TalAter Sep 2, 2018
965df41
Merge branch 'master' into feature/pausable-crowdsale
TalAter Sep 2, 2018
0661e31
Updated mock PausableCrowdsaleImpl to new constructor syntax
TalAter Sep 2, 2018
3d69c02
Broke function definition to multiple lines
TalAter Sep 2, 2018
aa48346
Rename events to past-tense in PausableCrowdsale test
TalAter Sep 2, 2018
4b9a631
Removed should.be.fullfilled from PausableCrowdsale tests
TalAter Sep 2, 2018
19f8b75
Change import assertRevert to require in PausableCrowdsale tests
TalAter Sep 2, 2018
e9181d7
Remove dependency on chai-as-promised and added BigNumber support in …
TalAter Sep 2, 2018
5f356dd
Merge branch 'master' of github.com:OpenZeppelin/openzeppelin-solidit…
frangio Dec 5, 2018
547c7c5
reindent solidity with 4 spaces
frangio Dec 11, 2018
35ade39
add missing view modifier in _preValidatePurchase
frangio Dec 11, 2018
5b74f79
convert assertRevert to new shoulFail helper
frangio Dec 11, 2018
665608a
Merge branch 'master' of github.com:OpenZeppelin/openzeppelin-solidit…
frangio Dec 11, 2018
7f49a78
add new setup helper
frangio Dec 11, 2018
17474f1
use expectEvent
frangio Dec 11, 2018
775d802
convert to assert to chai should style
frangio Dec 11, 2018
f669ea6
add description to beforeEach blocks
frangio Dec 11, 2018
d2d1ca7
extract common step to beforeEach
frangio Dec 11, 2018
f35c7e1
improve documentation
frangio Dec 11, 2018
5f3e5d7
revert inheritance error
frangio Dec 12, 2018
10f9335
move PausableCrowdsale into crowdsale/validation
frangio Dec 12, 2018
1d612fa
make documentation more specific
frangio Dec 12, 2018
61b2e85
put whitespace in line with convention
frangio Dec 12, 2018
1ea7a14
improve test suite account names
frangio Dec 12, 2018
7cf3287
undo beforeEach descriptions
frangio Dec 12, 2018
e6cbaf4
simplify tests
frangio Dec 12, 2018
268182e
fix transaction senders to be the anyone account
frangio Dec 12, 2018
1f2522e
make transaction senders more explicit
frangio Dec 13, 2018
955ac0f
remove mocha only
frangio Dec 13, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions contracts/crowdsale/PausableCrowdsale.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
pragma solidity ^0.4.18;

import "./Crowdsale.sol";
import "../lifecycle/Pausable.sol";


/**
* @title PausableCrowdsale
* @dev Extension of Crowdsale contract that can be paused and unpaused by owner
*/
contract PausableCrowdsale is Pausable, Crowdsale {

/**
* @dev Validation of an incoming purchase. Use require statements to revert state when conditions are not met. Use super to concatenate validations.
frangio marked this conversation as resolved.
Show resolved Hide resolved
* @param _beneficiary Address performing the token purchase
* @param _weiAmount Value in wei involved in the purchase
*/
function _preValidatePurchase(address _beneficiary, uint256 _weiAmount)
internal
frangio marked this conversation as resolved.
Show resolved Hide resolved
whenNotPaused
{
return super._preValidatePurchase(_beneficiary, _weiAmount);
}
}
19 changes: 19 additions & 0 deletions contracts/mocks/PausableCrowdsaleImpl.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
pragma solidity ^0.4.18;

import "../token/ERC20/ERC20.sol";
import "../crowdsale/PausableCrowdsale.sol";


contract PausableCrowdsaleImpl is PausableCrowdsale {

constructor (
uint256 _rate,
address _wallet,
ERC20 _token
)
public
Crowdsale(_rate, _wallet, _token)
{
}

}
155 changes: 155 additions & 0 deletions test/crowdsale/PausableCrowdsale.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
const { assertRevert } = require('../helpers/assertRevert');
frangio marked this conversation as resolved.
Show resolved Hide resolved

const PausableCrowdsale = artifacts.require('PausableCrowdsaleImpl');
const SimpleToken = artifacts.require('SimpleToken');

const BigNumber = web3.BigNumber;

require('chai')
.use(require('chai-bignumber')(BigNumber))
.should();

contract('PausableCrowdsale', function ([owner, wallet, stranger]) {
frangio marked this conversation as resolved.
Show resolved Hide resolved
const rate = 1;
const value = 1;

beforeEach(async function () {
this.token = await SimpleToken.new();
frangio marked this conversation as resolved.
Show resolved Hide resolved
this.crowdsale = await PausableCrowdsale.new(rate, wallet, this.token.address);
await this.token.transfer(this.crowdsale.address, value);
});

describe('pause()', function () {
describe('when the sender is the crowdsale owner', function () {
frangio marked this conversation as resolved.
Show resolved Hide resolved
const from = owner;

describe('when the crowdsale is unpaused', function () {
it('pauses the crowdsale', async function () {
await this.crowdsale.pause({ from });
frangio marked this conversation as resolved.
Show resolved Hide resolved
const paused = await this.crowdsale.paused();
assert.equal(paused, true);
frangio marked this conversation as resolved.
Show resolved Hide resolved
});

it('emits a Pause event', async function () {
const { logs } = await this.crowdsale.pause({ from });
assert.equal(logs.length, 1);
frangio marked this conversation as resolved.
Show resolved Hide resolved
assert.equal(logs[0].event, 'Paused');
});
});

describe('when the crowdsale is paused', function () {
beforeEach(async function () {
await this.crowdsale.pause({ from });
});

it('reverts', async function () {
await assertRevert(this.crowdsale.pause({ from }));
});
});
});

describe('when the sender is not the crowdsale owner', function () {
const from = stranger;

it('reverts', async function () {
await assertRevert(this.crowdsale.pause({ from }));
});
});
});

describe('unpause()', function () {
describe('when the sender is the crowdsale owner', function () {
const from = owner;

describe('when the crowdsale is paused', function () {
beforeEach(async function () {
await this.crowdsale.pause({ from });
});

it('unpauses the crowdsale', async function () {
await this.crowdsale.unpause({ from });
const paused = await this.crowdsale.paused();
assert.equal(paused, false);
});

it('emits an Unpause event', async function () {
const { logs } = await this.crowdsale.unpause({ from });
assert.equal(logs.length, 1);
assert.equal(logs[0].event, 'Unpaused');
});
});

describe('when the crowdsale is unpaused', function () {
it('reverts', async function () {
await assertRevert(this.crowdsale.unpause({ from }));
});
});
});

describe('when the sender is not the crowdsale owner', function () {
const from = stranger;

it('reverts', async function () {
await assertRevert(this.crowdsale.unpause({ from }));
});
});
});

describe('paused', function () {
const from = owner;

it('is not paused by default', async function () {
const paused = await this.crowdsale.paused({ from });
assert.equal(paused, false);
});

it('is paused after being paused', async function () {
await this.crowdsale.pause({ from });
const paused = await this.crowdsale.paused({ from });
assert.equal(paused, true);
});

it('is not paused after being paused and then unpaused', async function () {
await this.crowdsale.pause({ from });
await this.crowdsale.unpause({ from });
const paused = await this.crowdsale.paused({ from });
assert.equal(paused, false);
});
});

describe('when the crowdsale is paused', function () {
frangio marked this conversation as resolved.
Show resolved Hide resolved
const from = owner;

beforeEach(async function () {
await this.crowdsale.pause({ from });
});

describe('high-level purchase using fallback function', function () {
it('reverts', async function () {
await assertRevert(this.crowdsale.sendTransaction({ from, value }));
});
});

describe('buyTokens()', function () {
it('reverts', async function () {
await assertRevert(this.crowdsale.buyTokens(from, { from, value }));
});
});
});

describe('when the crowdsale is unpaused', function () {
frangio marked this conversation as resolved.
Show resolved Hide resolved
const from = owner;

describe('high-level purchase using fallback function', function () {
it('should accept payments', async function () {
await this.crowdsale.sendTransaction({ from, value });
});
});

describe('buyTokens()', function () {
it('should accept payments', async function () {
await this.crowdsale.buyTokens(from, { from, value });
});
});
});
});