From 70fd5e562224a5a9e921acb07db59980f1c4f824 Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Thu, 18 Jan 2018 17:41:51 -0300 Subject: [PATCH] Move token creation outside of crowdsale contract Fixes #358 --- contracts/crowdsale/Crowdsale.sol | 15 ++++++--------- contracts/examples/SampleCrowdsale.sol | 9 ++------- contracts/mocks/CappedCrowdsaleImpl.sol | 5 +++-- contracts/mocks/FinalizableCrowdsaleImpl.sol | 5 +++-- contracts/mocks/RefundableCrowdsaleImpl.sol | 5 +++-- test/crowdsale/CappedCrowdsale.test.js | 6 +++--- test/crowdsale/Crowdsale.test.js | 6 +++--- test/crowdsale/FinalizableCrowdsale.test.js | 8 +++++--- test/crowdsale/RefundableCrowdsale.test.js | 7 ++++++- test/examples/SampleCrowdsale.test.js | 7 +++++-- 10 files changed, 39 insertions(+), 34 deletions(-) diff --git a/contracts/crowdsale/Crowdsale.sol b/contracts/crowdsale/Crowdsale.sol index 012ee4eedc6..9d07388534b 100644 --- a/contracts/crowdsale/Crowdsale.sol +++ b/contracts/crowdsale/Crowdsale.sol @@ -10,7 +10,9 @@ import "../math/SafeMath.sol"; * Crowdsales have a start and end timestamps, where investors can make * token purchases and the crowdsale will assign them tokens based * on a token per ETH rate. Funds collected are forwarded to a wallet - * as they arrive. + * as they arrive. The contract requires a MintableToken that will be + * minted as contributions arrive, note that the crowdsale contract + * must be owner of the token in order to be able to mint it. */ contract Crowdsale { using SafeMath for uint256; @@ -41,17 +43,18 @@ contract Crowdsale { event TokenPurchase(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount); - function Crowdsale(uint256 _startTime, uint256 _endTime, uint256 _rate, address _wallet) public { + function Crowdsale(uint256 _startTime, uint256 _endTime, uint256 _rate, address _wallet, MintableToken _token) public { require(_startTime >= now); require(_endTime >= _startTime); require(_rate > 0); require(_wallet != address(0)); + require(_token != address(0)); - token = createTokenContract(); startTime = _startTime; endTime = _endTime; rate = _rate; wallet = _wallet; + token = _token; } // fallback function can be used to buy tokens @@ -83,12 +86,6 @@ contract Crowdsale { return now > endTime; } - // creates the token to be sold. - // override this method to have crowdsale of a specific mintable token. - function createTokenContract() internal returns (MintableToken) { - return new MintableToken(); - } - // Override this method to have a way to add business logic to your crowdsale when buying function getTokenAmount(uint256 weiAmount) internal view returns(uint256) { return weiAmount.mul(rate); diff --git a/contracts/examples/SampleCrowdsale.sol b/contracts/examples/SampleCrowdsale.sol index 9b506695f68..7c607a62c25 100644 --- a/contracts/examples/SampleCrowdsale.sol +++ b/contracts/examples/SampleCrowdsale.sol @@ -32,19 +32,14 @@ contract SampleCrowdsaleToken is MintableToken { */ contract SampleCrowdsale is CappedCrowdsale, RefundableCrowdsale { - function SampleCrowdsale(uint256 _startTime, uint256 _endTime, uint256 _rate, uint256 _goal, uint256 _cap, address _wallet) public + function SampleCrowdsale(uint256 _startTime, uint256 _endTime, uint256 _rate, uint256 _goal, uint256 _cap, address _wallet, MintableToken _token) public CappedCrowdsale(_cap) FinalizableCrowdsale() RefundableCrowdsale(_goal) - Crowdsale(_startTime, _endTime, _rate, _wallet) + Crowdsale(_startTime, _endTime, _rate, _wallet, _token) { //As goal needs to be met for a successful crowdsale //the value needs to less or equal than a cap which is limit for accepted funds require(_goal <= _cap); } - - function createTokenContract() internal returns (MintableToken) { - return new SampleCrowdsaleToken(); - } - } diff --git a/contracts/mocks/CappedCrowdsaleImpl.sol b/contracts/mocks/CappedCrowdsaleImpl.sol index 4e3620f1375..39a3bc88ed4 100644 --- a/contracts/mocks/CappedCrowdsaleImpl.sol +++ b/contracts/mocks/CappedCrowdsaleImpl.sol @@ -11,9 +11,10 @@ contract CappedCrowdsaleImpl is CappedCrowdsale { uint256 _endTime, uint256 _rate, address _wallet, - uint256 _cap + uint256 _cap, + MintableToken _token ) public - Crowdsale(_startTime, _endTime, _rate, _wallet) + Crowdsale(_startTime, _endTime, _rate, _wallet, _token) CappedCrowdsale(_cap) { } diff --git a/contracts/mocks/FinalizableCrowdsaleImpl.sol b/contracts/mocks/FinalizableCrowdsaleImpl.sol index 1e07fb25423..a03a0ad3dfd 100644 --- a/contracts/mocks/FinalizableCrowdsaleImpl.sol +++ b/contracts/mocks/FinalizableCrowdsaleImpl.sol @@ -10,9 +10,10 @@ contract FinalizableCrowdsaleImpl is FinalizableCrowdsale { uint256 _startTime, uint256 _endTime, uint256 _rate, - address _wallet + address _wallet, + MintableToken _token ) public - Crowdsale(_startTime, _endTime, _rate, _wallet) + Crowdsale(_startTime, _endTime, _rate, _wallet, _token) { } diff --git a/contracts/mocks/RefundableCrowdsaleImpl.sol b/contracts/mocks/RefundableCrowdsaleImpl.sol index e4285620127..d1744b6de75 100644 --- a/contracts/mocks/RefundableCrowdsaleImpl.sol +++ b/contracts/mocks/RefundableCrowdsaleImpl.sol @@ -11,9 +11,10 @@ contract RefundableCrowdsaleImpl is RefundableCrowdsale { uint256 _endTime, uint256 _rate, address _wallet, - uint256 _goal + uint256 _goal, + MintableToken _token ) public - Crowdsale(_startTime, _endTime, _rate, _wallet) + Crowdsale(_startTime, _endTime, _rate, _wallet, _token) RefundableCrowdsale(_goal) { } diff --git a/test/crowdsale/CappedCrowdsale.test.js b/test/crowdsale/CappedCrowdsale.test.js index 0200250008b..9f1f23d2fe4 100644 --- a/test/crowdsale/CappedCrowdsale.test.js +++ b/test/crowdsale/CappedCrowdsale.test.js @@ -29,9 +29,9 @@ contract('CappedCrowdsale', function ([_, wallet]) { this.startTime = latestTime() + duration.weeks(1); this.endTime = this.startTime + duration.weeks(1); - this.crowdsale = await CappedCrowdsale.new(this.startTime, this.endTime, rate, wallet, cap); - - this.token = MintableToken.at(await this.crowdsale.token()); + this.token = await MintableToken.new(); + this.crowdsale = await CappedCrowdsale.new(this.startTime, this.endTime, rate, wallet, cap, this.token.address); + await this.token.transferOwnership(this.crowdsale.address); }); describe('creating a valid crowdsale', function () { diff --git a/test/crowdsale/Crowdsale.test.js b/test/crowdsale/Crowdsale.test.js index ef6f248d593..340838061b8 100644 --- a/test/crowdsale/Crowdsale.test.js +++ b/test/crowdsale/Crowdsale.test.js @@ -30,9 +30,9 @@ contract('Crowdsale', function ([_, investor, wallet, purchaser]) { this.endTime = this.startTime + duration.weeks(1); this.afterEndTime = this.endTime + duration.seconds(1); - this.crowdsale = await Crowdsale.new(this.startTime, this.endTime, rate, wallet); - - this.token = MintableToken.at(await this.crowdsale.token()); + this.token = await MintableToken.new(); + this.crowdsale = await Crowdsale.new(this.startTime, this.endTime, rate, wallet, this.token.address); + await this.token.transferOwnership(this.crowdsale.address); }); it('should be token owner', async function () { diff --git a/test/crowdsale/FinalizableCrowdsale.test.js b/test/crowdsale/FinalizableCrowdsale.test.js index 39988663a29..a29a48f337d 100644 --- a/test/crowdsale/FinalizableCrowdsale.test.js +++ b/test/crowdsale/FinalizableCrowdsale.test.js @@ -26,9 +26,11 @@ contract('FinalizableCrowdsale', function ([_, owner, wallet, thirdparty]) { this.endTime = this.startTime + duration.weeks(1); this.afterEndTime = this.endTime + duration.seconds(1); - this.crowdsale = await FinalizableCrowdsale.new(this.startTime, this.endTime, rate, wallet, { from: owner }); - - this.token = MintableToken.at(await this.crowdsale.token()); + this.token = await MintableToken.new(); + this.crowdsale = await FinalizableCrowdsale.new( + this.startTime, this.endTime, rate, wallet, this.token.address, { from: owner } + ); + await this.token.transferOwnership(this.crowdsale.address); }); it('cannot be finalized before ending', async function () { diff --git a/test/crowdsale/RefundableCrowdsale.test.js b/test/crowdsale/RefundableCrowdsale.test.js index 54347826cc1..e097a0b9a4c 100644 --- a/test/crowdsale/RefundableCrowdsale.test.js +++ b/test/crowdsale/RefundableCrowdsale.test.js @@ -12,6 +12,7 @@ require('chai') .should(); const RefundableCrowdsale = artifacts.require('mocks/RefundableCrowdsaleImpl.sol'); +const MintableToken = artifacts.require('MintableToken'); contract('RefundableCrowdsale', function ([_, owner, wallet, investor]) { const rate = new BigNumber(1000); @@ -28,7 +29,11 @@ contract('RefundableCrowdsale', function ([_, owner, wallet, investor]) { this.endTime = this.startTime + duration.weeks(1); this.afterEndTime = this.endTime + duration.seconds(1); - this.crowdsale = await RefundableCrowdsale.new(this.startTime, this.endTime, rate, wallet, goal, { from: owner }); + this.token = await MintableToken.new(); + this.crowdsale = await RefundableCrowdsale.new( + this.startTime, this.endTime, rate, wallet, goal, this.token.address, { from: owner } + ); + await this.token.transferOwnership(this.crowdsale.address); }); describe('creating a valid crowdsale', function () { diff --git a/test/examples/SampleCrowdsale.test.js b/test/examples/SampleCrowdsale.test.js index b2f9ee26ef5..d14807eacc2 100644 --- a/test/examples/SampleCrowdsale.test.js +++ b/test/examples/SampleCrowdsale.test.js @@ -29,8 +29,11 @@ contract('SampleCrowdsale', function ([owner, wallet, investor]) { this.endTime = this.startTime + duration.weeks(1); this.afterEndTime = this.endTime + duration.seconds(1); - this.crowdsale = await SampleCrowdsale.new(this.startTime, this.endTime, RATE, GOAL, CAP, wallet); - this.token = SampleCrowdsaleToken.at(await this.crowdsale.token()); + this.token = await SampleCrowdsaleToken.new(); + this.crowdsale = await SampleCrowdsale.new( + this.startTime, this.endTime, RATE, GOAL, CAP, wallet, this.token.address + ); + await this.token.transferOwnership(this.crowdsale.address); }); it('should create crowdsale with correct parameters', async function () {