Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
307 lines (257 sloc) 9.85 KB
/*
This file is part of the eHealth First Contract.
www.ehfirst.io
An IT-platform for Personalized Health and Longevity Management
based on Blockchain, Artificial Intelligence,
Machine Learning and Natural Language Processing
The eHealth First Contract is free software: you can redistribute it and/or
modify it under the terms of the GNU lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
The eHealth First Contract is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU lesser General Public License for more details.
You should have received a copy of the GNU lesser General Public License
along with the eHealth First Contract. If not, see <http://www.gnu.org/licenses/>.
@author Ilya Svirin <i.svirin@prover.ru>
IF YOU ARE ENJOYED IT DONATE TO 0x3Ad38D1060d1c350aF29685B2b8Ec3eDE527452B ! :)
*/
pragma solidity ^0.4.19;
contract owned {
address public owner;
address public candidate;
function owned() public payable {
owner = msg.sender;
}
modifier onlyOwner {
require(owner == msg.sender);
_;
}
function changeOwner(address _owner) onlyOwner public {
require(_owner != 0);
candidate = _owner;
}
function confirmOwner() public {
require(candidate == msg.sender);
owner = candidate;
delete candidate;
}
}
/**
* @title ERC20 interface
* @dev see https://github.com/ethereum/EIPs/issues/20
*/
contract ERC20 {
uint public totalSupply;
function balanceOf(address who) public constant returns (uint);
function transfer(address to, uint value) public;
function allowance(address owner, address spender) public constant returns (uint);
function transferFrom(address from, address to, uint value) public;
function approve(address spender, uint value) public;
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
}
contract Token is owned, ERC20 {
string public standard = 'Token 0.1';
string public name = 'eHealth First';
string public symbol = "EHF";
uint8 public decimals = 8;
uint public freezedMoment;
struct TokenHolder {
uint balance;
uint balanceBeforeUpdate;
uint balanceUpdateTime;
}
mapping (address => TokenHolder) public holders;
mapping (address => uint) public vesting;
mapping (address => mapping (address => uint256)) public allowed;
address public vestingManager;
function setVestingManager(address _vestingManager) public onlyOwner {
vestingManager = _vestingManager;
}
function beforeBalanceChanges(address _who) internal {
if (holders[_who].balanceUpdateTime <= freezedMoment) {
holders[_who].balanceUpdateTime = now;
holders[_who].balanceBeforeUpdate = holders[_who].balance;
}
}
event Burned(address indexed owner, uint256 value);
function Token() public owned() {}
function balanceOf(address _who) constant public returns (uint) {
return holders[_who].balance;
}
function transfer(address _to, uint256 _value) public {
require(now > vesting[msg.sender] || msg.sender == vestingManager);
require(holders[_to].balance + _value >= holders[_to].balance); // overflow
beforeBalanceChanges(msg.sender);
beforeBalanceChanges(_to);
holders[msg.sender].balance -= _value;
holders[_to].balance += _value;
if (vesting[_to] < vesting[msg.sender]) {
vesting[_to] = vesting[msg.sender];
}
emit Transfer(msg.sender, _to, _value);
}
function transferFrom(address _from, address _to, uint256 _value) public {
require(now > vesting[_from]);
require(holders[_to].balance + _value >= holders[_to].balance); // overflow
require(allowed[_from][msg.sender] >= _value);
beforeBalanceChanges(_from);
beforeBalanceChanges(_to);
holders[_from].balance -= _value;
holders[_to].balance += _value;
allowed[_from][msg.sender] -= _value;
emit Transfer(_from, _to, _value);
}
function approve(address _spender, uint256 _value) public {
allowed[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
}
function allowance(address _owner, address _spender) public constant
returns (uint256 remaining) {
return allowed[_owner][_spender];
}
function burn(uint256 _value) public {
require(holders[msg.sender].balance >= _value);
beforeBalanceChanges(msg.sender);
holders[msg.sender].balance -= _value;
totalSupply -= _value;
emit Burned(msg.sender, _value);
}
}
contract Crowdsale is Token {
address public backend;
uint public stage;
bool public started;
uint public startTokenPriceWei;
uint public tokensForSale;
uint public startTime;
uint public lastTokenPriceWei;
uint public milliPercent; // "25" means 0.25%
uint public paymentsCount; // restart on each stage
bool public sealed;
modifier notSealed {
require(sealed == false);
_;
}
event Mint(address indexed _who, uint _tokens, uint _coinType, bytes32 _txHash);
event Stage(uint _stage, bool startNotFinish);
function Crowdsale() public Token() {
totalSupply = 100000000*100000000;
holders[this].balance = totalSupply;
}
function startStage(uint _startTokenPriceWei, uint _tokensForSale, uint _milliPercent) public onlyOwner notSealed {
require(!started);
require(_startTokenPriceWei >= lastTokenPriceWei);
startTokenPriceWei = _startTokenPriceWei;
tokensForSale = _tokensForSale * 100000000;
if(tokensForSale > holders[this].balance) {
tokensForSale = holders[this].balance;
}
milliPercent = _milliPercent;
startTime = now;
started = true;
paymentsCount = 0;
emit Stage(stage, started);
}
function currentTokenPrice() public constant returns(uint) {
uint price;
if(!sealed && started) {
uint d = (now - startTime) / 1 days;
price = startTokenPriceWei;
price += startTokenPriceWei * d * milliPercent / 100;
}
return price;
}
function stopStage() public onlyOwner notSealed {
require(started);
started = false;
lastTokenPriceWei = currentTokenPrice();
emit Stage(stage, started);
++stage;
}
function () payable public notSealed {
require(started);
uint price = currentTokenPrice();
if(paymentsCount < 100) {
price = price * 90 / 100;
}
++paymentsCount;
uint tokens = 100000000 * msg.value / price;
if(tokens > tokensForSale) {
tokens = tokensForSale;
uint sumWei = tokens * lastTokenPriceWei / 100000000;
require(msg.sender.call.gas(3000000).value(msg.value - sumWei)());
}
require(tokens > 0);
require(holders[msg.sender].balance + tokens > holders[msg.sender].balance); // overflow
tokensForSale -= tokens;
beforeBalanceChanges(msg.sender);
beforeBalanceChanges(this);
holders[msg.sender].balance += tokens;
holders[this].balance -= tokens;
emit Transfer(this, msg.sender, tokens);
}
function mintTokens1(address _who, uint _tokens, uint _coinType, bytes32 _txHash) public notSealed {
require(msg.sender == owner || msg.sender == backend);
require(started);
_tokens *= 100000000;
if(_tokens > tokensForSale) {
_tokens = tokensForSale;
}
require(_tokens > 0);
require(holders[_who].balance + _tokens > holders[_who].balance); // overflow
tokensForSale -= _tokens;
beforeBalanceChanges(_who);
beforeBalanceChanges(this);
holders[_who].balance += _tokens;
holders[this].balance -= _tokens;
emit Mint(_who, _tokens, _coinType, _txHash);
emit Transfer(this, _who, _tokens);
}
// must be called by owners only out of stage
function mintTokens2(address _who, uint _tokens, uint _vesting) public notSealed {
require(msg.sender == owner || msg.sender == backend);
require(!started);
require(_tokens > 0);
_tokens *= 100000000;
require(_tokens <= holders[this].balance);
require(holders[_who].balance + _tokens > holders[_who].balance); // overflow
if(_vesting != 0) {
vesting[_who] = _vesting;
}
beforeBalanceChanges(_who);
beforeBalanceChanges(this);
holders[_who].balance += _tokens;
holders[this].balance -= _tokens;
emit Mint(_who, _tokens, 0, 0);
emit Transfer(this, _who, _tokens);
}
// need to seal Crowdsale when it is finished completely
function seal() public onlyOwner {
sealed = true;
}
}
contract Ehfirst is Crowdsale {
function Ehfirst() payable public Crowdsale() {}
function setBackend(address _backend) public onlyOwner {
backend = _backend;
}
function withdraw() public onlyOwner {
require(owner.call.gas(3000000).value(address(this).balance)());
}
function freezeTheMoment() public onlyOwner {
freezedMoment = now;
}
/** Get balance of _who for freezed moment
* freezeTheMoment()
*/
function freezedBalanceOf(address _who) constant public returns(uint) {
if (holders[_who].balanceUpdateTime <= freezedMoment) {
return holders[_who].balance;
} else {
return holders[_who].balanceBeforeUpdate;
}
}
}