Skip to content

Commit

Permalink
adapt, fix and add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Federico Martín Alconada Verzini committed Nov 9, 2017
1 parent 5ceb757 commit 125c3a5
Show file tree
Hide file tree
Showing 13 changed files with 248 additions and 158 deletions.
10 changes: 6 additions & 4 deletions contracts/Crowdsale.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@ import "./QiibeeToken.sol";
@title Crowdsale for the QBX Token Generation Event
Implementation of kind of an 'abstract' QBX Token Generation Event (TGE). This contract will be
used by QiibeePresale.sol and QiibeeCrowdsale.
used by QiibeePresale.sol and QiibeeCrowdsale.sol
This TGE includes is capped and has a spam prevention technique:
This TGE is capped and has a spam prevention technique:
* investors can make purchases with a minimum request inverval of X seconds given by minBuyingRequestInterval.
* investors are limited in the gas price
In case of the goal not being reached by purchases made during the 4-week period the token will
not start operating and all funds sent during that period will be made available to be claimed
by the originating addresses.
The function buyTokens() is not minting tokens. This function should be overriden to add that logic.
*/

contract Crowdsale is Pausable {
Expand Down Expand Up @@ -84,7 +86,7 @@ contract Crowdsale is Pausable {
require(_startTime >= now);
require(_endTime >= _startTime);
require(_cap > 0);
require(_goal >= 0);
require(_goal > 0);
require(_goal <= _cap);
require(_maxGasPrice > 0);
require(_minBuyingRequestInterval >= 0);
Expand Down Expand Up @@ -114,7 +116,7 @@ contract Crowdsale is Pausable {
}

/**
* @dev Must be overridden to add buy token minting logic. The overriding function
* @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.
*/
Expand Down
2 changes: 1 addition & 1 deletion contracts/QiibeeCrowdsale.sol
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ contract QiibeeCrowdsale is Crowdsale {
Crowdsale(_startTime, _endTime, _goal, _cap, _maxGasPrice, _minBuyingRequestInterval, _wallet)
{
require(_rate > 0);
require(_minInvest >= 0);
require(_minInvest > 0);
require(_maxCumulativeInvest > 0);
require(_minInvest <= _maxCumulativeInvest);

Expand Down
8 changes: 3 additions & 5 deletions contracts/QiibeePresale.sol
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,9 @@ contract QiibeePresale is Crowdsale {
require(newBalance <= maxCumulativeInvest && msg.value >= minInvest);

if (data.cliff > 0 && data.vesting > 0) {
assert(token.mintVestedTokens(beneficiary, tokens, from, cliff, vesting, revokable, burnsOnRevoke));
require(token.mintVestedTokens(beneficiary, tokens, from, cliff, vesting, revokable, burnsOnRevoke));
} else {
assert(token.mint(this, tokens));
require(token.mint(beneficiary, tokens));
}

// update state
Expand All @@ -105,9 +105,7 @@ contract QiibeePresale is Crowdsale {
function addAccreditedInvestor(address investor, uint256 rate, uint64 cliff, uint64 vesting, bool revokable, bool burnsOnRevoke, uint256 minInvest, uint256 maxCumulativeInvest) public onlyOwner {
require(investor != address(0));
require(rate > 0);
require(cliff >= 0);
require(vesting >= 0);
require(minInvest >= 0);
require(minInvest > 0);
require(maxCumulativeInvest > 0);

accredited[investor] = AccreditedInvestor(rate, cliff, vesting, revokable, burnsOnRevoke, minInvest, maxCumulativeInvest);
Expand Down
7 changes: 2 additions & 5 deletions contracts/QiibeeToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ contract QiibeeToken is BurnableToken, PausableToken, VestedToken, MintableToken
}

/**
@dev Overrides VestedToken#grantVestedTokens(). Similar to grantVestedTokens but minting tokens
instead of transferring.
@dev Similar to grantVestedTokens but minting tokens instead of transferring.
*/
function mintVestedTokens (
address _to,
Expand All @@ -42,7 +41,7 @@ contract QiibeeToken is BurnableToken, PausableToken, VestedToken, MintableToken
uint64 _vesting,
bool _revokable,
bool _burnsOnRevoke
) onlyOwner public constant returns (bool) {
) onlyOwner public returns (bool) {
// Check for date inconsistencies that may cause unexpected behavior
require(_cliff >= _start && _vesting >= _cliff);

Expand All @@ -62,8 +61,6 @@ contract QiibeeToken is BurnableToken, PausableToken, VestedToken, MintableToken

bool minted = mint(_to, _value); //mint tokens

NewTokenGrant(msg.sender, _to, _value, count - 1);

return minted;
}

Expand Down
3 changes: 1 addition & 2 deletions contracts/WhitelistedCrowdsale.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,11 @@ contract WhitelistedCrowdsale is Crowdsale, Ownable {

// @return true if investor is whitelisted
function isWhitelisted(address investor) public constant returns (bool) {
require(investor != address(0));
return whitelist[investor];
}

// @return true if buyer investor been removed
function removeFromWhitelisted(address investor) public onlyOwner {
function removeFromWhitelist(address investor) public onlyOwner {
require(investor != address(0));
whitelist[investor] = false;
}
Expand Down
2 changes: 1 addition & 1 deletion scripts/ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ if [ "$SOLIDITY_COVERAGE" = true ]; then
else
GEN_TESTS_TIMEOUT=400 GEN_TESTS_QTY=40 yarn test test/PresaleGenTest.js test/CrowdsaleGenTest.js
yarn test test/Crowdsale.js
yarn test test/token/QiibeeToken.js test/QiibeeCrowdsale.js test/WhitelistedCrowdsale.js
yarn test test/QiibeeToken.js test/QiibeeCrowdsale.js test/WhitelistedCrowdsale.js
fi
66 changes: 34 additions & 32 deletions test/PresaleGenTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ contract('QiibeePresale property-based test', function(accounts) {
presaleContract: presale,
token: token,
balances: {},
tokenBalances: {},
ethBalances: help.getAccountsBalances(accounts),
purchases: [],
weiRaised: zero,
Expand Down Expand Up @@ -164,20 +165,7 @@ contract('QiibeePresale property-based test', function(accounts) {
await runGeneratedPresaleAndCommands({
commands: [
{ type: 'waitTime','seconds':duration.days(1)},
{ type: 'addAccredited', investor: 4, rate: 6000, cliff: 600, vesting: 600, minInvest: 1, maxCumulativeInvest: 2, fromAccount: 0 },
{ type: 'presaleSendTransaction', beneficiary: 3, account: 4, eth: 1 },
],
presale: {
maxGasPrice: 50000000000, minBuyingRequestInterval: 600, goal: 36000, cap: 240000, foundationWallet: 10, owner: 0
}
});
});

it('should allow accredited investors to buy tokens', async function () {
await runGeneratedPresaleAndCommands({
commands: [
{ type: 'waitTime','seconds':duration.days(1)},
{ type: 'addAccredited', investor: 4, rate: 6000, cliff: 600, vesting: 600, minInvest: 1, maxCumulativeInvest: 2, fromAccount: 0 },
{ type: 'addAccredited', investor: 4, rate: 6000, cliff: 600, vesting: 600, revokable: false, burnsOnTokens: false, minInvest: 1, maxCumulativeInvest: 2, fromAccount: 0 },
{ type: 'presaleSendTransaction', beneficiary: 3, account: 4, eth: 1 },
],
presale: {
Expand All @@ -190,7 +178,7 @@ contract('QiibeePresale property-based test', function(accounts) {
await runGeneratedPresaleAndCommands({
commands: [
{ type: 'waitTime','seconds':duration.days(1)},
{ type: 'addAccredited', investor: 4, rate: 6000, cliff: 0, vesting: 0, minInvest: 1, maxCumulativeInvest: 2, fromAccount: 0 },
{ type: 'addAccredited', investor: 4, rate: 6000, cliff: 0, vesting: 0, revokable: false, burnsOnTokens: false, minInvest: 1, maxCumulativeInvest: 2, fromAccount: 0 },
{ type: 'presaleSendTransaction', beneficiary: 3, account: 4, eth: 1 },
],
presale: {
Expand All @@ -203,7 +191,7 @@ contract('QiibeePresale property-based test', function(accounts) {
await runGeneratedPresaleAndCommands({
commands: [
{ type: 'waitTime','seconds':duration.days(1)},
{ type: 'addAccredited', investor: 4, rate: 6000, cliff: 600, vesting: 600, minInvest: 1, maxCumulativeInvest: 2, fromAccount: 0 },
{ type: 'addAccredited', investor: 4, rate: 6000, cliff: 600, vesting: 600, revokable: false, burnsOnTokens: false, minInvest: 1, maxCumulativeInvest: 2, fromAccount: 0 },
{ type: 'presaleBuyTokens', beneficiary: 3, account: 4, eth: 3 },
],
presale: {
Expand All @@ -216,7 +204,7 @@ contract('QiibeePresale property-based test', function(accounts) {
await runGeneratedPresaleAndCommands({
commands: [
{ type: 'waitTime','seconds':duration.days(1)},
{ type: 'addAccredited', investor: 4, rate: 6000, cliff: 600, vesting: 600, minInvest: 1, maxCumulativeInvest: 2, fromAccount: 0 },
{ type: 'addAccredited', investor: 4, rate: 6000, cliff: 600, vesting: 600, revokable: false, burnsOnTokens: false, minInvest: 1, maxCumulativeInvest: 2, fromAccount: 0 },
{ type: 'presaleBuyTokens', beneficiary: 3, account: 4, eth: 0.5 },
],
presale: {
Expand All @@ -238,101 +226,115 @@ contract('QiibeePresale property-based test', function(accounts) {
});

describe('add to accredited list', function () {

it('should NOT be able to add investor to accredited list with rate zero', async function () {
await runGeneratedPresaleAndCommands({
commands: [
{ type: 'waitTime','seconds':duration.days(1)},
{ type: 'addAccredited', investor: 4, rate: 0, cliff: 600, vesting: 600, minInvest: 1, maxCumulativeInvest: 2, fromAccount: 2 },
{ type: 'addAccredited', investor: 4, rate: 0, cliff: 600, vesting: 600, revokable: false, burnsOnTokens: false, minInvest: 1, maxCumulativeInvest: 2, fromAccount: 0 },
],
presale: {
maxGasPrice: 50000000000, minBuyingRequestInterval: 600, goal: 36000, cap: 240000, foundationWallet: 10, owner: 0
}
});
});

it('should NOT be able to add investor to accredited list with cliff less than zero', async function () {
it('should be able to add investor to accredited list with zero cliff', async function () {
await runGeneratedPresaleAndCommands({
commands: [
{ type: 'waitTime','seconds':duration.days(1)},
{ type: 'addAccredited', investor: 4, rate: 6000, cliff: -600, vesting: 600, minInvest: 1, maxCumulativeInvest: 2, fromAccount: 2 },
{ type: 'addAccredited', investor: 4, rate: 6000, cliff: 0, vesting: 600, revokable: false, burnsOnTokens: false, minInvest: 1, maxCumulativeInvest: 2, fromAccount: 0 },
],
presale: {
maxGasPrice: 50000000000, minBuyingRequestInterval: 600, goal: 36000, cap: 240000, foundationWallet: 10, owner: 0
}
});
});

it('should be able to add investor to accredited list with zero cliff', async function () {
it('should NOT be able to add investor to accredited list with maxCumulativeInvest less than zero', async function () {
await runGeneratedPresaleAndCommands({
commands: [
{ type: 'waitTime','seconds':duration.days(1)},
{ type: 'addAccredited', investor: 4, rate: 6000, cliff: 600, vesting: 600, revokable: false, burnsOnTokens: false, minInvest: 1, maxCumulativeInvest: -2, fromAccount: 0 },
],
presale: {
maxGasPrice: 50000000000, minBuyingRequestInterval: 600, goal: 36000, cap: 240000, foundationWallet: 10, owner: 0
}
});
});

it('should NOT be able to add investor to accredited list with minInvest zero', async function () {
await runGeneratedPresaleAndCommands({
commands: [
{ type: 'waitTime','seconds':duration.days(1)},
{ type: 'addAccredited', investor: 4, rate: 6000, cliff: 0, vesting: 600, minInvest: 1, maxCumulativeInvest: 2, fromAccount: 2 },
{ type: 'addAccredited', investor: 4, rate: 6000, cliff: 600, vesting: 600, revokable: false, burnsOnTokens: false, minInvest: 0, maxCumulativeInvest: 2, fromAccount: 0 },
],
presale: {
maxGasPrice: 50000000000, minBuyingRequestInterval: 600, goal: 36000, cap: 240000, foundationWallet: 10, owner: 0
}
});
});

it('should NOT be able to add investor to accredited list with vesting less than zero', async function () {
it('should NOT be able to add investor to accredited list if not owner', async function () {
await runGeneratedPresaleAndCommands({
commands: [
{ type: 'waitTime','seconds':duration.days(1)},
{ type: 'addAccredited', investor: 4, rate: 6000, cliff: 600, vesting: -600, minInvest: 1, maxCumulativeInvest: 2, fromAccount: 2 },
{ type: 'addAccredited', investor: 4, rate: 6000, cliff: 600, vesting: 600, revokable: false, burnsOnTokens: false, minInvest: 1, maxCumulativeInvest: 2, fromAccount: 2 },
],
presale: {
maxGasPrice: 50000000000, minBuyingRequestInterval: 600, goal: 36000, cap: 240000, foundationWallet: 10, owner: 0
}
});
});

it('should NOT be able to add investor to accredited list with maxCumulativeInvest less than zero', async function () {
it('should NOT be able to add investor to accredited list if address is zero', async function () {
await runGeneratedPresaleAndCommands({
commands: [
{ type: 'waitTime','seconds':duration.days(1)},
{ type: 'addAccredited', investor: 4, rate: 6000, cliff: 600, vesting: 600, minInvest: 1, maxCumulativeInvest: -2, fromAccount: 2 },
{ type: 'addAccredited', investor: 'zero', rate: 6000, cliff: 600, vesting: 600, revokable: false, burnsOnTokens: false, minInvest: 1, maxCumulativeInvest: 2, fromAccount: 0 },
],
presale: {
maxGasPrice: 50000000000, minBuyingRequestInterval: 600, goal: 36000, cap: 240000, foundationWallet: 10, owner: 0
}
});
});

it('should NOT be able to add investor to accredited list with minInvest zero', async function () {
it('should be able to remove investor from accredited list', async function () {
await runGeneratedPresaleAndCommands({
commands: [
{ type: 'waitTime','seconds':duration.days(1)},
{ type: 'addAccredited', investor: 4, rate: 6000, cliff: 600, vesting: 600, minInvest: 0, maxCumulativeInvest: 2, fromAccount: 2 },
{ type: 'removeAccredited', investor: 4, fromAccount: 0 },
],
presale: {
maxGasPrice: 50000000000, minBuyingRequestInterval: 600, goal: 36000, cap: 240000, foundationWallet: 10, owner: 0
}
});
});

it('should NOT be able to add investor to accredited list if not owner', async function () {
it('should NOT be able to remove investor from accredited list if not owner', async function () {
await runGeneratedPresaleAndCommands({
commands: [
{ type: 'waitTime','seconds':duration.days(1)},
{ type: 'addAccredited', investor: 4, rate: 6000, cliff: 600, vesting: 600, minInvest: 1, maxCumulativeInvest: 2, fromAccount: 2 },
{ type: 'removeAccredited', investor: 4, fromAccount: 2 },
],
presale: {
maxGasPrice: 50000000000, minBuyingRequestInterval: 600, goal: 36000, cap: 240000, foundationWallet: 10, owner: 0
}
});
});

it('should NOT be able to add investor to accredited list if address is zero', async function () {
it('should NOT be able to remove investor from accredited list if address is zero', async function () {
await runGeneratedPresaleAndCommands({
commands: [
{ type: 'waitTime','seconds':duration.days(1)},
{ type: 'addAccredited', investor: 'zero', rate: 6000, cliff: 600, vesting: 600, minInvest: 1, maxCumulativeInvest: 2, fromAccount: 0 },
{ type: 'removeAccredited', investor: 'zero', fromAccount: 2 },
],
presale: {
maxGasPrice: 50000000000, minBuyingRequestInterval: 600, goal: 36000, cap: 240000, foundationWallet: 10, owner: 0
}
});
});

});

it('distributes tokens correctly on any combination of bids', async function() {
Expand Down

0 comments on commit 125c3a5

Please sign in to comment.