Skip to content

Commit

Permalink
LabStart ICO V1
Browse files Browse the repository at this point in the history
  • Loading branch information
arthur-sultan-info committed Feb 19, 2018
1 parent 815b1af commit 808f3d2
Show file tree
Hide file tree
Showing 17 changed files with 802 additions and 18 deletions.
1 change: 0 additions & 1 deletion .gitignore
@@ -1,5 +1,4 @@
build
migrations
truffle-config.js
constTests.js
node_modules
5 changes: 5 additions & 0 deletions config/deployConfig.js
@@ -0,0 +1,5 @@
module.exports = Object.freeze({
LABCOIN_INITIAL_OWNER_A_ACCOUNT_NUMBER: 0,
LABCOIN_INITIAL_OWNER_B_ACCOUNT_NUMBER: 1,
AVAILABLE_ACCOUNT_NUMBER_NOT_OWNER: 2 // for TestLabCoin.js
});
11 changes: 11 additions & 0 deletions config/icoConfig.js
@@ -0,0 +1,11 @@
module.exports = Object.freeze({
ICO_CAP: 84000000000000000000000, // in wei
ICO_OWNER_NUMBER: 0, // TODO(optional): rename as ICO_OWNER_INDEX
ICO_RATE_FIRST_PHASE: 400,
ICO_RATE_SECOND_PHASE: 300,
ICO_START_TIME: 1527112800, // 24/05/2018 00:00:00
ICO_SECOND_PHASE_START_TIME: 1528495200, // 09/06/2018 00:00:00
ICO_END_TIME: 1529791200, // 24/06/2018 00:00:00
ICO_INVESTOR_NUMBER: 1 // For TestLabStartICO
// TODO(optional): rename as ICO_INVESTOR_INDEX
});
9 changes: 9 additions & 0 deletions config/presaleConfig.js
@@ -0,0 +1,9 @@
module.exports = Object.freeze({
PRESALE_CAP: 16800000000000000000000, // in wei
PRESALE_OWNER_NUMBER: 0,
PRESALE_RATE: 500,
PRESALE_START_TIME: 1521932400, // 25/03/2018 00:00:00
PRESALE_END_TIME: 1524693600,// 26/04/2018 00:00:00
PRESALE_INVESTOR_NUMBER: 1 // For TestLabStartPresale
// TODO(optional): rename as PRESALE_INVESTOR_INDEX
});
35 changes: 35 additions & 0 deletions contracts/CappedCrowdsale.sol
@@ -0,0 +1,35 @@
pragma solidity ^0.4.18;

import "zeppelin-solidity/contracts/math/SafeMath.sol";
import "./Crowdsale.sol";


/**
* @title CappedCrowdsale
* @dev Extension of Crowdsale with a max amount of funds raised
*/
contract CappedCrowdsale is Crowdsale {
using SafeMath for uint256;

uint256 public cap;

function CappedCrowdsale(uint256 _cap) public {
require(_cap > 0);
cap = _cap;
}

// overriding Crowdsale#hasEnded to add cap logic
// @return true if crowdsale event has ended
function hasEnded() public view returns (bool) {
bool capReached = weiRaised >= cap;
return capReached || super.hasEnded();
}

// overriding Crowdsale#validPurchase to add extra cap logic
// @return true if investors can buy at the moment
function validPurchase() internal view returns (bool) {
bool withinCap = weiRaised.add(msg.value) <= cap;
return withinCap && super.validPurchase();
}

}
105 changes: 105 additions & 0 deletions contracts/Crowdsale.sol
@@ -0,0 +1,105 @@
pragma solidity ^0.4.18;

import "zeppelin-solidity/contracts/token/ERC20/MintableToken.sol";
import "zeppelin-solidity/contracts/math/SafeMath.sol";


/**
* @title Crowdsale
* @dev Crowdsale is a base contract for managing a token crowdsale.
* 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.
*/
contract Crowdsale {
using SafeMath for uint256;

// The token being sold
MintableToken public token;

// start and end timestamps where investments are allowed (both inclusive)
uint256 public startTime;
uint256 public endTime;

// address where funds are collected
address public wallet;

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

// amount of raised money in wei
uint256 public weiRaised;

/**
* event for token purchase logging
* @param purchaser who paid for the tokens
* @param beneficiary who got the tokens
* @param value weis paid for purchase
* @param amount amount of tokens purchased
*/
event TokenPurchase(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount);


function Crowdsale(uint256 _startTime, uint256 _endTime, uint256 _rate, address _wallet,
address tokenAddress) public {
require(_startTime >= now);
require(_endTime >= _startTime);
require(_rate > 0);
require(_wallet != address(0));

token = MintableToken(tokenAddress);
startTime = _startTime;
endTime = _endTime;
rate = _rate;
wallet = _wallet;
}

// fallback function can be used to buy tokens
function () external payable {
buyTokens(msg.sender);
}

// low level token purchase function
function buyTokens(address beneficiary) public payable {
require(beneficiary != address(0));
require(validPurchase());

uint256 weiAmount = msg.value;

// calculate token amount to be created
uint256 tokens = getTokenAmount(weiAmount);

// update state
weiRaised = weiRaised.add(weiAmount);

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

forwardFunds();
}

// @return true if crowdsale event has ended
function hasEnded() public view returns (bool) {
return now > endTime;
}

// 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);
}

// send ether to the fund collection wallet
// override to create custom fund forwarding mechanisms
function forwardFunds() internal {
wallet.transfer(msg.value);
}

// @return true if the transaction can buy tokens
function validPurchase() internal view returns (bool) {
bool withinPeriod = now >= startTime && now <= endTime;
bool nonZeroPurchase = msg.value != 0;
return withinPeriod && nonZeroPurchase;
}

}
9 changes: 7 additions & 2 deletions contracts/LabCoin.sol
@@ -1,9 +1,14 @@
pragma solidity ^0.4.19;

import "zeppelin-solidity/contracts/token/ERC20/MintableToken.sol";
import "./SharedMintableToken.sol";

contract LabCoin is MintableToken {
contract LabCoin is SharedMintableToken {
string public constant name = "LabCoin";
string public constant symbol = "LAB";
uint8 public constant decimals = 18;

function LabCoin(address ownerA, address ownerB)
SharedMintableToken(ownerA, ownerB) public {

}
}
18 changes: 7 additions & 11 deletions contracts/LabStartCrowdsale.sol
@@ -1,21 +1,17 @@
pragma solidity ^0.4.19;

import "zeppelin-solidity/contracts/crowdsale/Crowdsale.sol";
import "./Crowdsale.sol";
import "./CappedCrowdsale.sol";
import "zeppelin-solidity/contracts/token/ERC20/MintableToken.sol";

import "./LabCoin.sol";

contract LabStartCrowdsale is Crowdsale {
contract LabStartCrowdsale is CappedCrowdsale {
function LabStartCrowdsale(uint256 startTime, uint256 endTime, uint256 rate,
address wallet)
Crowdsale(startTime, endTime, rate, wallet) public {
address wallet, uint256 cap, address labcoinAddress)
Crowdsale(startTime, endTime, rate, wallet, labcoinAddress)
CappedCrowdsale(cap) public {

}

// creates the token to be sold.
// override this method to have crowdsale of a specific mintable token.
function createTokenContract() internal returns (MintableToken) {
return new LabCoin();
}


}
30 changes: 30 additions & 0 deletions contracts/LabStartICO.sol
@@ -0,0 +1,30 @@
pragma solidity ^0.4.19;

import "zeppelin-solidity/contracts/math/SafeMath.sol";
import "./LabStartCrowdsale.sol";

contract LabStartICO is LabStartCrowdsale {
uint256 public _rateFirstPhase;
uint256 public _rateSecondPhase;
uint256 public _secondPhaseStartTime;

function LabStartICO(uint256 startTime, uint256 secondPhaseStartTime,
uint256 endTime, uint256 rateFirstPhase, uint256 rateSecondPhase,
address wallet, uint256 cap, address labcoinAddress)
LabStartCrowdsale(startTime, endTime, rateFirstPhase, wallet,
cap, labcoinAddress) public {
_rateFirstPhase = rateFirstPhase;
_rateSecondPhase = rateSecondPhase;
_secondPhaseStartTime = secondPhaseStartTime;
}

// Override this method to have a way to add business logic to your crowdsale when buying
function getTokenAmount(uint256 weiAmount) internal view returns(uint256) {
if(now >= _secondPhaseStartTime) {
return weiAmount.mul(_rateSecondPhase);
}
else {
return weiAmount.mul(_rateFirstPhase);
}
}
}
7 changes: 3 additions & 4 deletions contracts/LabStartPresale.sol
Expand Up @@ -3,10 +3,9 @@ pragma solidity ^0.4.19;
import "./LabStartCrowdsale.sol";

contract LabStartPresale is LabStartCrowdsale {
uint256 private constant _rate = 500;

function LabStartPresale(uint256 startTime, uint256 endTime, address wallet)
LabStartCrowdsale(startTime, endTime, _rate, wallet) public {
function LabStartPresale(uint256 startTime, uint256 endTime, uint256 rate,
address wallet, uint256 cap, address labcoinAddress)
LabStartCrowdsale(startTime, endTime, rate, wallet, cap, labcoinAddress) public {

}
}
52 changes: 52 additions & 0 deletions contracts/SharedMintableToken.sol
@@ -0,0 +1,52 @@
pragma solidity ^0.4.18;

import "zeppelin-solidity/contracts/token/ERC20/StandardToken.sol";
import "./SharedOwnership.sol";


/**
* @title Mintable token
* @dev Simple ERC20 Token example, with mintable token creation
* @dev Issue: * https://github.com/OpenZeppelin/zeppelin-solidity/issues/120
* Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol
*/
contract SharedMintableToken is StandardToken, SharedOwnership {
event Mint(address indexed to, uint256 amount);
event MintFinished();

bool public mintingFinished = false;

function SharedMintableToken(address ownerA, address ownerB)
SharedOwnership(ownerA, ownerB) public {
}


modifier canMint() {
require(!mintingFinished);
_;
}

/**
* @dev Function to mint tokens
* @param _to The address that will receive the minted tokens.
* @param _amount The amount of tokens to mint.
* @return A boolean that indicates if the operation was successful.
*/
function mint(address _to, uint256 _amount) onlyOwners canMint public returns (bool) {
totalSupply_ = totalSupply_.add(_amount);
balances[_to] = balances[_to].add(_amount);
Mint(_to, _amount);
Transfer(address(0), _to, _amount);
return true;
}

/**
* @dev Function to stop minting new tokens.
* @return True if the operation was successful.
*/
function finishMinting() onlyOwners canMint public returns (bool) {
mintingFinished = true;
MintFinished();
return true;
}
}
54 changes: 54 additions & 0 deletions contracts/SharedOwnership.sol
@@ -0,0 +1,54 @@
pragma solidity ^0.4.18;


/**
* @title SharedOwnership
* @dev A version of Ownable with two owners
*/
contract SharedOwnership {
address public _ownerA;
address public _ownerB;


event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);


/**
* @dev The SharedOwnership constructor sets the original `owners` of the contract
*/
function SharedOwnership(address ownerA, address ownerB) public {
require(ownerA != ownerB);
_ownerA = ownerA;
_ownerB = ownerB;
}

/**
* @dev Throws if called by any account other than one of the two owners
*/
modifier onlyOwners() {
require(msg.sender == _ownerA || msg.sender == _ownerB);
_;
}

/**
* @dev Allows one of the two owners to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) public onlyOwners {
require(newOwner != address(0));
require(newOwner != _ownerA && newOwner != _ownerB);
if(msg.sender == _ownerA) {
OwnershipTransferred(_ownerA, newOwner);
_ownerA = newOwner;
}
else if(msg.sender == _ownerB) {
OwnershipTransferred(_ownerB, newOwner);
_ownerB = newOwner;
}
else {
revert();
}

}

}
5 changes: 5 additions & 0 deletions migrations/1_initial_migration.js
@@ -0,0 +1,5 @@
var Migrations = artifacts.require("./Migrations.sol");

module.exports = function(deployer) {
deployer.deploy(Migrations);
};

0 comments on commit 808f3d2

Please sign in to comment.