/*
* Crowdsale for Lympo Tokens.
* Raised Ether will be stored safely at the wallet and returned to the ICO in case the funding
* goal is not reached, allowing the token holders to withdraw their funds.
* Author: Justas Kregždė
*/
pragma solidity ^0.4.19;
contract token {
function transferFrom(address sender, address receiver, uint amount) returns(bool success) {}
function burn() {}
}
library SafeMath {
function mul(uint a, uint b) internal returns (uint) {
uint c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function sub(uint a, uint b) internal returns (uint) {
assert(b <= a);
return a - b;
}
function add(uint a, uint b) internal returns (uint) {
uint c = a + b;
assert(c >= a && c >= b);
return c;
}
}
contract LympoICO {
using SafeMath for uint;
// pre-ICO
// The maximum amount of tokens to be sold during pre-ICO
uint constant public pre_maxGoal = 265000000e18; // 265 Million LYM Tokens
// There are different prices and amount available in each period
uint[2] public pre_prices = [60000, 50000];
uint[1] public pre_amount_stages = [90000000e18]; // the amount available in each stage
// The start date of the pre-ICO crowdsale
uint constant public pre_start = 1516618800; // Monday, 22 January 2018 11:00:00 GMT
// The end date of the pre-ICO crowdsale
uint constant public pre_end = 1517655600; // Saturday, 3 February 2018 11:00:00 GMT
// The number of tokens already sold during pre-ICO
uint public pre_tokensSold = 0;
// ICO
// The maximum amount of tokens to be sold
uint constant public maxGoal = 385000000e18; // 385 Million LYM Tokens
// There are different prices and amount available in each period
uint[1] public prices = [40000];
// The start date of the crowdsale
uint constant public start = 1518865200; // Saturday, 17 February 2018 11:00:00 GMT
// The end date of the crowdsale
uint constant public end = 1519815600; // Wednesday, 28 February 2018 11:00:00 GMT
// The number of tokens already sold during ICO
uint public tokensSold = 0;
// If the funding goal is not reached, token holders may withdraw their funds
uint constant public fundingGoal = 150000000e18; // 15%
// How much has been raised by crowdale (in ETH)
uint public amountRaised;
// The balances (in ETH) of all token holders
mapping(address => uint) public balances;
// Indicates if the crowdsale has been ended already
bool public crowdsaleEnded = false;
// Tokens will be transfered from this address
address public tokenOwner;
// The address of the token contract
token public tokenReward;
// The wallet on which the funds will be stored
address wallet;
// Notifying transfers and the success of the crowdsale
event GoalReached(address _tokenOwner, uint _amountRaised);
event FundTransfer(address backer, uint amount, bool isContribution, uint _amountRaised);
// Constructor/initialization
function LympoICO(address tokenAddr, address walletAddr, address tokenOwnerAddr) {
tokenReward = token(tokenAddr);
wallet = walletAddr;
tokenOwner = tokenOwnerAddr;
}
// Exchange by sending ether to the contract.
function() payable {
if (msg.sender != wallet) // Do not trigger exchange if the wallet is returning the funds
exchange(msg.sender);
}
// Make an exchanegment. Only callable if the crowdsale started and hasn't been ended, also the maxGoal wasn't reached yet.
// The current token price is looked up by available amount. Bought tokens is transfered to the receiver.
// The sent value is directly forwarded to a safe wallet.
function exchange(address receiver) payable {
uint amount = msg.value;
uint price = getPrice();
uint numTokens = amount.mul(price);
bool isPreICO = (now >= pre_start && now <= pre_end);
bool isICO = (now >= start && now <= end);
require(isPreICO || isICO);
require(numTokens > 0);
if (isPreICO)
{
require(!crowdsaleEnded && pre_tokensSold.add(numTokens) <= pre_maxGoal);
if (pre_tokensSold < pre_amount_stages[0])
require(numTokens <= 6000000e18); // max threshold for pre-ICO: 6mil LYM tokens for stage-I
else
require(numTokens <= 12500000e18); // max threshold for pre-ICO: 12.5mil LYM tokens for stage-II
}
if (isICO)
{
require(!crowdsaleEnded && tokensSold.add(numTokens) <= maxGoal);
}
wallet.transfer(amount);
balances[receiver] = balances[receiver].add(amount);
// Calculate how much raised and tokens sold
amountRaised = amountRaised.add(amount);
if (isPreICO)
pre_tokensSold = pre_tokensSold.add(numTokens);
if (isICO)
tokensSold = tokensSold.add(numTokens);
assert(tokenReward.transferFrom(tokenOwner, receiver, numTokens));
FundTransfer(receiver, amount, true, amountRaised);
}
// Looks up the current token price
function getPrice() constant returns (uint price) {
// pre-ICO prices
if (now >= pre_start && now <= pre_end)
{
for(uint i = 0; i < pre_amount_stages.length; i++) {
if(pre_tokensSold < pre_amount_stages[i])
return pre_prices[i];
}
return pre_prices[pre_prices.length-1];
}
// ICO prices
return prices[prices.length-1];
}
modifier afterDeadline() { if (now >= end) _; }
// Checks if the goal or time limit has been reached and ends the campaign
function checkGoalReached() afterDeadline {
if (pre_tokensSold.add(tokensSold) >= fundingGoal){
tokenReward.burn(); // Burn remaining tokens but the reserved ones
GoalReached(tokenOwner, amountRaised);
}
crowdsaleEnded = true;
}
// Allows the funders to withdraw their funds if the goal has not been reached.
// Only works after funds have been returned from the wallet.
function safeWithdrawal() afterDeadline {
uint amount = balances[msg.sender];
if (address(this).balance >= amount) {
balances[msg.sender] = 0;
if (amount > 0) {
msg.sender.transfer(amount);
FundTransfer(msg.sender, amount, false, amountRaised);
}
}
}
}
{
"compilationTarget": {
"LympoICO.sol": "LympoICO"
},
"libraries": {},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"constant":false,"inputs":[],"name":"checkGoalReached","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"crowdsaleEnded","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"receiver","type":"address"}],"name":"exchange","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balances","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"pre_amount_stages","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"pre_maxGoal","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"tokensSold","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"tokenReward","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"fundingGoal","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"amountRaised","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"pre_tokensSold","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"pre_start","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getPrice","outputs":[{"name":"price","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"pre_end","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"tokenOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"prices","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"start","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"end","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"pre_prices","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"maxGoal","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"safeWithdrawal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"tokenAddr","type":"address"},{"name":"walletAddr","type":"address"},{"name":"tokenOwnerAddr","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_tokenOwner","type":"address"},{"indexed":false,"name":"_amountRaised","type":"uint256"}],"name":"GoalReached","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"backer","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"isContribution","type":"bool"},{"indexed":false,"name":"_amountRaised","type":"uint256"}],"name":"FundTransfer","type":"event"}]