Skip to content

Commit

Permalink
add changes
Browse files Browse the repository at this point in the history
[x] Use back OpenZeppelin contracts for crowdsale
[x] Remove Crowdsale.sol from QiibeePresale and QiibeeCrowdsale
[x] Decouple QiibeeToken from presale and crowdsale contracts
[x] Adapt tests
[x] Add migration ability to QiibeeToken
[x] Add migration tests
[x] Update comments in code
[ ] Update README.md on how to deploy the contracts and add descriptions of each contract
[x] Add more tests
[x] Check start on vesting
[x] Fix finalize function on tests
  • Loading branch information
Federico Martín Alconada Verzini committed Nov 21, 2017
1 parent 26d5963 commit d40368c
Show file tree
Hide file tree
Showing 28 changed files with 1,217 additions and 680 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Expand Up @@ -4,4 +4,4 @@ npm-debug.log
.node-xmlhttprequest-sync-[0-9]*
coverage
coverage.json
.private.js
private.js
8 changes: 3 additions & 5 deletions .solcover.js
@@ -1,13 +1,11 @@
module.exports = {
port: 8555,
norpc: true,
// testCommand: 'node ../node_modules/.bin/truffle test --network coverage',
testCommand: 'GEN_TESTS_TIMEOUT=400 GEN_TESTS_QTY=40 truffle test --network coverage test/QiibeeToken.js test/QiibeeCrowdsale.js test/QiibeePresale.js test/WhitelistedCrowdsale.js test/QiibeePresaleGenTest.js test/QiibeeCrowdsaleGenTest.js',
copyNodeModules: true,
skipFiles: [
'test-helpers/Message.sol',
'VestedToken.sol',
'CrowdsaleImpl.sol',
'QiibeePresaleImpl.sol',
'WhitelistedCrowdsaleImpl.sol'
'Crowdsale.sol',
'QiibeeMigrationToken.sol',
]
}
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -29,7 +29,7 @@ npm install

* To run all tests: `npm test`

* To run a specific test: `npm test -- test/Crowdsale.js`
* To run a specific test: `npm test -- test/QiibeeCrowdsale.js`

There are also two environment variables (`GEN_TESTS_QTY` and `GEN_TESTS_TIMEOUT`) that regulate the duration/depth of the property-based tests, so for example:

Expand Down
58 changes: 50 additions & 8 deletions contracts/Crowdsale.sol
Expand Up @@ -2,7 +2,7 @@ pragma solidity ^0.4.11;

import "zeppelin-solidity/contracts/lifecycle/Pausable.sol";
import "zeppelin-solidity/contracts/crowdsale/RefundVault.sol";
import "./QiibeeToken.sol";
// import "./QiibeeToken.sol";

/**
@title Crowdsale for the QBX Token Generation Event
Expand All @@ -20,6 +20,23 @@ import "./QiibeeToken.sol";
The function buyTokens() does not mint tokens. This function should be overriden to add that logic.
*/

contract QiibeeToken {
function mintVestedTokens(address _to,
uint256 _value,
uint64 _start,
uint64 _cliff,
uint64 _vesting,
bool _revokable,
bool _burnsOnRevoke,
address _wallet
) returns (bool);
function mint(address _to, uint256 _amount) returns (bool);
function transferOwnership(address _wallet);
function pause();
function unpause();
function finishMinting() returns (bool);
}

contract Crowdsale is Pausable {

using SafeMath for uint256;
Expand All @@ -31,6 +48,8 @@ contract Crowdsale is Pausable {
uint256 public goal; // min amount of funds to be raised in wei
RefundVault public vault; // refund vault used to hold funds while crowdsale is running

uint256 public rate; // how many token units a buyer gets per wei

QiibeeToken public token; // token being sold
uint256 public tokensSold; // qbx minted (and sold)
uint256 public weiRaised; // raised money in wei
Expand Down Expand Up @@ -66,6 +85,7 @@ contract Crowdsale is Pausable {
* @dev Constructor. Creates the token in a paused state
* @param _startTime see `startTimestamp`
* @param _endTime see `endTimestamp`
* @param _rate see `see rate`
* @param _goal see `see goal`
* @param _cap see `see cap`
* @param _maxGasPrice see `see maxGasPrice`
Expand All @@ -75,6 +95,7 @@ contract Crowdsale is Pausable {
function Crowdsale (
uint256 _startTime,
uint256 _endTime,
uint256 _rate,
uint256 _goal,
uint256 _cap,
uint256 _maxGasPrice,
Expand All @@ -84,6 +105,7 @@ contract Crowdsale is Pausable {
{
require(_startTime >= now);
require(_endTime >= _startTime);
require(_rate > 0);
require(_cap > 0);
require(_goal > 0);
require(_goal <= _cap);
Expand All @@ -94,16 +116,17 @@ contract Crowdsale is Pausable {

startTime = _startTime;
endTime = _endTime;
rate = _rate;
cap = _cap;
goal = _goal;
maxGasPrice = _maxGasPrice;
minBuyingRequestInterval = _minBuyingRequestInterval;
wallet = _wallet;

token = new QiibeeToken();
// token = new QiibeeToken();
vault = new RefundVault(wallet);

token.pause();
// token.pause();

}

Expand All @@ -114,17 +137,26 @@ contract Crowdsale is Pausable {
buyTokens(msg.sender);
}

/**
* @dev Must be overridden to add token minting logic. The overriding function
* should call super.finalization() to ensure the chain of buy tokens is
* executed entirely.
/*
* @dev Low level token purchase function.
* @param beneficiary address where tokens are sent to
*/
function buyTokens(address beneficiary) public payable whenNotPaused {
require(beneficiary != address(0));
require(validPurchase());

uint256 weiAmount = msg.value;

// calculate token amount to be created
uint256 tokens = weiAmount.mul(rate);

// update state
weiRaised = weiRaised.add(weiAmount);
tokensSold = tokensSold.add(tokens);
lastCallTime[msg.sender] = now;

token.mint(beneficiary, tokens);
TokenPurchase(msg.sender, beneficiary, weiAmount, tokens);

forwardFunds();
}
Expand Down Expand Up @@ -177,7 +209,7 @@ contract Crowdsale is Pausable {
* @dev Must be called after crowdsale ends, to do some extra finalization
* work. Calls the contract's finalization function.
*/
function finalize() public {
function finalize() public onlyOwner {
require(!isFinalized);
require(hasEnded());

Expand Down Expand Up @@ -210,4 +242,14 @@ contract Crowdsale is Pausable {
WalletChange(_wallet);
}

/**
@dev changes the token owner
*/
//TODO: EXECUTE BEFORE START CROWDSALE
function setToken(address tokenAddress) onlyOwner {
require(now < startTime);
token = QiibeeToken(tokenAddress);
}


}
53 changes: 53 additions & 0 deletions contracts/MigrationAgent.sol
@@ -0,0 +1,53 @@
pragma solidity ^0.4.11;

import "zeppelin-solidity/contracts/ownership/Ownable.sol";
import "./QiibeeToken.sol";

// interface
contract QiibeeMigrationTokenInterface {
function createToken(address _target, uint256 _amount);
function finalizeMigration();
function totalSupply() returns (uint256);
}

contract MigrationAgent is Ownable {

address public qbxSourceToken;
address public qbxTargetToken;
uint256 public tokenSupply;

function MigrationAgent(address _qbxSourceToken) {
require(QiibeeToken(_qbxSourceToken).migrationAgent() == address(0));
tokenSupply = QiibeeToken(_qbxSourceToken).totalSupply();
qbxSourceToken = _qbxSourceToken;
}

function safetyInvariantCheck(uint256 _value) internal {
require(QiibeeToken(qbxSourceToken).totalSupply() + QiibeeMigrationTokenInterface(qbxTargetToken).totalSupply() == tokenSupply - _value);
}

function setTargetToken(address _qbxTargetToken) public onlyOwner {
require(qbxTargetToken == address(0)); //Allow this change once only
qbxTargetToken = _qbxTargetToken;
}

function migrateFrom(address _from, uint256 _value) public {
require(msg.sender == qbxSourceToken);
require(qbxTargetToken != address(0));

safetyInvariantCheck(_value); // qbxSourceToken has already been updated, but corresponding QBX have not been created in the qbxTargetToken contract yet
QiibeeMigrationTokenInterface(qbxTargetToken).createToken(_from, _value);
safetyInvariantCheck(0); // totalSupply invariant must hold
}

function finalizeMigration() public onlyOwner {
require(qbxTargetToken != address(0));
require(QiibeeToken(qbxSourceToken).totalSupply() == 0); //only finlize if all tokens have been migrated
safetyInvariantCheck(0);
QiibeeMigrationTokenInterface(qbxTargetToken).finalizeMigration();

qbxSourceToken = address(0);
qbxTargetToken = address(0);
tokenSupply = 0;
}
}

0 comments on commit d40368c

Please sign in to comment.