Browse Source

Move token creation outside of crowdsale contract (#690)

Fixes #358
Santiago Palladino 7 years ago
parent
commit
4d7c3cca75

+ 6 - 9
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);

+ 2 - 7
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();
-  }
-
 }

+ 3 - 2
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)
   {
   }

+ 3 - 2
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)
   {
   }
 

+ 3 - 2
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)
   {
   }

+ 3 - 3
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 () {

+ 3 - 3
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 () {

+ 5 - 3
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 () {

+ 6 - 1
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 () {

+ 5 - 2
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 () {