Crowdsale refactor and add new models (#744)

* Basic idea

* Fine tuning idea

* Add comments / tidy up Crowdsale base class

* fixed TimedCrowdsale constructor

* added simple crowdsale test

* added HODL directory under home to store unused contracts. ugly hack to solve Crowdsale selection in tests, better way?

* Capped no longer inherits from Timed, added capReached() method (replacing hasEnded())

* added SafeMath in TimedCrowdsale for safety, CHECK whether it is inherited from Crowdsale

* several fixes related to separating Capped from Timed. functions renamed, mocks changed. Capped tests passing

* added TimedCrowdsaleImpl.sol, TimedCrowdsale tests, passed

* added Whitelisted implementation and test, passed.

* removed unnecessary super constructor call in WhitelistedCrowdsale, removed unused dependencies in tests

* renamed UserCappedCrowdsale to IndividuallyCappedCrowdsale, implemented IndividuallyCappedCrowdsaleImpl.sol and corresponding tests, passed.

* homogeneized use of using SafeMath for uint256 across validation crowdsales. checked that it IS indeed inherited, but leaving it there as per Frans suggestion.

* adding questions.md where I track questions, bugs and progress

* modified VariablePriceCrowdsale, added Impl.

* finished VariablePrice, fixed sign, added test, passing.

* changed VariablePrice to IncreasingPrice, added corresponding require()

* MintedCrowdsale done, mock implemented, test passing

* PremintedCrowdsale done, mocks, tests passing

* checked FinalizableCrowdsale

* PostDeliveryCrowdsale done, mock, tests passing.

* RefundableCrowdsale done. Detached Vault. modified mock and test, passing

* renamed crowdsale-refactor to crowdsale in contracts and test

* deleted HODL old contracts

* polished variable names in tests

* fixed typos and removed comments in tests

* Renamed 'crowdsale-refactor' to 'crowdsale' in all imports

* Fix minor param naming issues in Crowdsale functions and added documentation to Crowdsale.sol

* Added documentation to Crowdsale extensions

* removed residual comments and progress tracking files

* added docs for validation crowdsales

* Made user promises in PostDeliveryCrowdsale public so that users can query their promised token balance.

* added docs for distribution crowdsales

* renamed PremintedCrowdsale to AllowanceCrowdsale

* added allowance check function and corresponding test. fixed filename in AllowanceCrowdsale mock.

* spilt Crowdsale _postValidatePurchase in _postValidatePurchase and _updatePurchasingState. changed IndividuallyCappedCrowdsale accordingly.

* polished tests for linter, salve Travis

* polished IncreasingPriceCrowdsale.sol for linter.

* renamed and polished for linter WhitelistedCrowdsale test.

* fixed indentation in IncreasingPriceCrowdsaleImpl.sol for linter

* fixed ignoring token.mint return value in MintedCrowdsale.sol

* expanded docs throughout, fixed minor issues

* extended test coverage for IndividuallyCappedCrowdsale

* Extended WhitelistedCrwodsale test coverage

* roll back decoupling of RefundVault in RefundableCrowdsale

* moved cap exceedance checks in Capped and IndividuallyCapped crowdsales to _preValidatePurchase to save gas

* revert name change, IndividuallyCapped to UserCapped

* extended docs.

* added crowd whitelisting with tests

* added group capping, plus tests

* added modifiers in TimedCrowdsale and WhitelistedCrowdsale

* polished tests for linter

* moved check of whitelisted to modifier, mainly for testing coverage

* fixed minor ordering/polishingafter review

* modified TimedCrowdsale modifier/constructor ordering

* unchanged truffle-config.js

* changed indentation of visibility modifier in mocks

* changed naming of modifier and function to use Open/Closed for TimedCrowdsale

* changed ordering of constructor calls in SampleCrowdsale

* changed startTime and endTime to openingTime and closingTime throughout

* fixed exceeding line lenght for linter

* renamed _emitTokens to _deliverTokens

* renamed addCrowdToWhitelist to addManyToWhitelist

* renamed UserCappedCrowdsale to IndividuallyCappedCrowdsale
This commit is contained in:
Alejo Salles
2018-02-20 18:05:53 -03:00
committed by Manuel Aráoz
parent 108d5f3b4a
commit c05918c3cc
36 changed files with 1321 additions and 285 deletions

View File

@ -13,6 +13,7 @@ require('chai')
const SampleCrowdsale = artifacts.require('SampleCrowdsale');
const SampleCrowdsaleToken = artifacts.require('SampleCrowdsaleToken');
const RefundVault = artifacts.require('RefundVault');
contract('SampleCrowdsale', function ([owner, wallet, investor]) {
const RATE = new BigNumber(10);
@ -25,30 +26,32 @@ contract('SampleCrowdsale', function ([owner, wallet, investor]) {
});
beforeEach(async function () {
this.startTime = latestTime() + duration.weeks(1);
this.endTime = this.startTime + duration.weeks(1);
this.afterEndTime = this.endTime + duration.seconds(1);
this.openingTime = latestTime() + duration.weeks(1);
this.closingTime = this.openingTime + duration.weeks(1);
this.afterClosingTime = this.closingTime + duration.seconds(1);
this.token = await SampleCrowdsaleToken.new();
this.token = await SampleCrowdsaleToken.new({ from: owner });
this.vault = await RefundVault.new(wallet, { from: owner });
this.crowdsale = await SampleCrowdsale.new(
this.startTime, this.endTime, RATE, GOAL, CAP, wallet, this.token.address
this.openingTime, this.closingTime, RATE, wallet, CAP, this.token.address, GOAL
);
await this.token.transferOwnership(this.crowdsale.address);
await this.vault.transferOwnership(this.crowdsale.address);
});
it('should create crowdsale with correct parameters', async function () {
this.crowdsale.should.exist;
this.token.should.exist;
const startTime = await this.crowdsale.startTime();
const endTime = await this.crowdsale.endTime();
const openingTime = await this.crowdsale.openingTime();
const closingTime = await this.crowdsale.closingTime();
const rate = await this.crowdsale.rate();
const walletAddress = await this.crowdsale.wallet();
const goal = await this.crowdsale.goal();
const cap = await this.crowdsale.cap();
startTime.should.be.bignumber.equal(this.startTime);
endTime.should.be.bignumber.equal(this.endTime);
openingTime.should.be.bignumber.equal(this.openingTime);
closingTime.should.be.bignumber.equal(this.closingTime);
rate.should.be.bignumber.equal(RATE);
walletAddress.should.be.equal(wallet);
goal.should.be.bignumber.equal(GOAL);
@ -64,7 +67,7 @@ contract('SampleCrowdsale', function ([owner, wallet, investor]) {
const investmentAmount = ether(1);
const expectedTokenAmount = RATE.mul(investmentAmount);
await increaseTimeTo(this.startTime);
await increaseTimeTo(this.openingTime);
await this.crowdsale.buyTokens(investor, { value: investmentAmount, from: investor }).should.be.fulfilled;
(await this.token.balanceOf(investor)).should.be.bignumber.equal(expectedTokenAmount);
@ -78,17 +81,17 @@ contract('SampleCrowdsale', function ([owner, wallet, investor]) {
});
it('should reject payments over cap', async function () {
await increaseTimeTo(this.startTime);
await increaseTimeTo(this.openingTime);
await this.crowdsale.send(CAP);
await this.crowdsale.send(1).should.be.rejectedWith(EVMRevert);
});
it('should allow finalization and transfer funds to wallet if the goal is reached', async function () {
await increaseTimeTo(this.startTime);
await increaseTimeTo(this.openingTime);
await this.crowdsale.send(GOAL);
const beforeFinalization = web3.eth.getBalance(wallet);
await increaseTimeTo(this.afterEndTime);
await increaseTimeTo(this.afterClosingTime);
await this.crowdsale.finalize({ from: owner });
const afterFinalization = web3.eth.getBalance(wallet);
@ -98,9 +101,9 @@ contract('SampleCrowdsale', function ([owner, wallet, investor]) {
it('should allow refunds if the goal is not reached', async function () {
const balanceBeforeInvestment = web3.eth.getBalance(investor);
await increaseTimeTo(this.startTime);
await increaseTimeTo(this.openingTime);
await this.crowdsale.sendTransaction({ value: ether(1), from: investor, gasPrice: 0 });
await increaseTimeTo(this.afterEndTime);
await increaseTimeTo(this.afterClosingTime);
await this.crowdsale.finalize({ from: owner });
await this.crowdsale.claimRefund({ from: investor, gasPrice: 0 }).should.be.fulfilled;