Contract Source Code:
File 1 of 1 : RC
pragma solidity ^0.4.23;
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
library SafeMath {
function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
if (a == 0) {
return 0;
}
c = a * b;
assert(c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
c = a + b;
assert(c >= a);
return c;
}
}
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address public owner;
address public newOwner;
event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);
constructor() public {
owner = msg.sender;
newOwner = address(0);
}
modifier onlyOwner() {
require(msg.sender == owner, "msg.sender == owner");
_;
}
function transferOwnership(address _newOwner) public onlyOwner {
require(address(0) != _newOwner, "address(0) != _newOwner");
newOwner = _newOwner;
}
function acceptOwnership() public {
require(msg.sender == newOwner, "msg.sender == newOwner");
emit OwnershipTransferred(owner, msg.sender);
owner = msg.sender;
newOwner = address(0);
}
}
contract tokenInterface {
function balanceOf(address _owner) public constant returns (uint256 balance);
function transfer(address _to, uint256 _value) public returns (bool);
function burn(uint256 _value) public returns(bool);
uint256 public totalSupply;
uint256 public decimals;
}
contract rateInterface {
function readRate(string _currency) public view returns (uint256 oneEtherValue);
}
contract RC {
using SafeMath for uint256;
DaicoCoinCrowd tokenSaleContract;
uint256 public startTime;
uint256 public endTime;
uint256 public etherMinimum;
uint256 public soldTokens;
uint256 public remainingTokens;
uint256 public oneTokenInFiatWei;
constructor(address _tokenSaleContract, uint256 _oneTokenInFiatWei, uint256 _remainingTokens, uint256 _etherMinimum, uint256 _startTime , uint256 _endTime) public {
require ( _tokenSaleContract != 0, "Token Sale Contract can not be 0" );
require ( _oneTokenInFiatWei != 0, "Token price can no be 0" );
require( _remainingTokens != 0, "Remaining tokens can no be 0");
tokenSaleContract = DaicoCoinCrowd(_tokenSaleContract);
soldTokens = 0;
remainingTokens = _remainingTokens;
oneTokenInFiatWei = _oneTokenInFiatWei;
etherMinimum = _etherMinimum;
setTimeRC( _startTime, _endTime );
}
function setTimeRC(uint256 _startTime, uint256 _endTime ) internal {
if( _startTime == 0 ) {
startTime = tokenSaleContract.startTime();
} else {
startTime = _startTime;
}
if( _endTime == 0 ) {
endTime = tokenSaleContract.endTime();
} else {
endTime = _endTime;
}
}
modifier onlyTokenSaleOwner() {
require(msg.sender == tokenSaleContract.owner(), "msg.sender == tokenSaleContract.owner()" );
_;
}
function setTime(uint256 _newStart, uint256 _newEnd) public onlyTokenSaleOwner {
if ( _newStart != 0 ) startTime = _newStart;
if ( _newEnd != 0 ) endTime = _newEnd;
}
function changeMinimum(uint256 _newEtherMinimum) public onlyTokenSaleOwner {
etherMinimum = _newEtherMinimum;
}
function started() public view returns(bool) {
return now > startTime || remainingTokens == 0;
}
function ended() public view returns(bool) {
return now > endTime || remainingTokens == 0;
}
function startTime() public view returns(uint) {
return startTime;
}
function endTime() public view returns(uint) {
return endTime;
}
function totalTokens() public view returns(uint) {
return remainingTokens.add(soldTokens);
}
function remainingTokens() public view returns(uint) {
return remainingTokens;
}
function price() public view returns(uint) {
uint256 oneEther = 1 ether;
return oneEther.mul(10**18).div( tokenSaleContract.tokenValueInEther(oneTokenInFiatWei) );
}
event BuyRC(address indexed buyer, bytes trackID, uint256 value, uint256 soldToken, uint256 valueTokenInUsdWei );
function () public payable {
require( now > startTime, "now > startTime" );
require( now < endTime, "now < endTime" );
require( msg.value >= etherMinimum, "msg.value >= etherMinimum");
require( remainingTokens > 0, "remainingTokens > 0" );
uint256 tokenAmount = tokenSaleContract.buyFromRC.value(msg.value)(msg.sender, oneTokenInFiatWei, remainingTokens);
remainingTokens = remainingTokens.sub(tokenAmount);
soldTokens = soldTokens.add(tokenAmount);
emit BuyRC( msg.sender, msg.data, msg.value, tokenAmount, oneTokenInFiatWei );
}
}
contract DaicoCoinCrowd is Ownable {
using SafeMath for uint256;
tokenInterface public tokenContract;
rateInterface public rateContract;
address public wallet;
uint256 public decimals;
uint256 public endTime; // seconds from 1970-01-01T00:00:00Z
uint256 public startTime; // seconds from 1970-01-01T00:00:00Z
uint256 public oneTokenInEur;
mapping(address => bool) public rc;
constructor(address _tokenAddress, address _rateAddress, uint256 _startTime, uint256 _endTime, uint256[] _time, uint256[] _funds, uint256 _oneTokenInEur, uint256 _activeSupply) public {
tokenContract = tokenInterface(_tokenAddress);
rateContract = rateInterface(_rateAddress);
setTime(_startTime, _endTime);
decimals = tokenContract.decimals();
oneTokenInEur = _oneTokenInEur;
wallet = new MilestoneSystem(_tokenAddress, _time, _funds, _oneTokenInEur, _activeSupply);
}
function tokenValueInEther(uint256 _oneTokenInFiatWei) public view returns(uint256 tknValue) {
uint256 oneEtherPrice = rateContract.readRate("eur");
tknValue = _oneTokenInFiatWei.mul(10 ** uint256(decimals)).div(oneEtherPrice);
return tknValue;
}
modifier isBuyable() {
require( wallet != address(0), "wallet != address(0)" );
require( now > startTime, "now > startTime" ); // check if started
require( now < endTime, "now < endTime"); // check if ended
require( msg.value > 0, "msg.value > 0" );
uint256 remainingTokens = tokenContract.balanceOf(this);
require( remainingTokens > 0, "remainingTokens > 0" ); // Check if there are any remaining tokens
_;
}
event Buy(address buyer, uint256 value, address indexed ambassador);
modifier onlyRC() {
require( rc[msg.sender], "rc[msg.sender]" ); //check if is an authorized rcContract
_;
}
function buyFromRC(address _buyer, uint256 _rcTokenValue, uint256 _remainingTokens) onlyRC isBuyable public payable returns(uint256) {
uint256 oneToken = 10 ** uint256(decimals);
uint256 tokenValue = tokenValueInEther(_rcTokenValue);
uint256 tokenAmount = msg.value.mul(oneToken).div(tokenValue);
address _ambassador = msg.sender;
uint256 remainingTokens = tokenContract.balanceOf(this);
if ( _remainingTokens < remainingTokens ) {
remainingTokens = _remainingTokens;
}
if ( remainingTokens < tokenAmount ) {
uint256 refund = tokenAmount.sub(remainingTokens).mul(tokenValue).div(oneToken);
tokenAmount = remainingTokens;
forward(msg.value.sub(refund));
remainingTokens = 0; // set remaining token to 0
_buyer.transfer(refund);
} else {
remainingTokens = remainingTokens.sub(tokenAmount); // update remaining token without bonus
forward(msg.value);
}
tokenContract.transfer(_buyer, tokenAmount);
emit Buy(_buyer, tokenAmount, _ambassador);
return tokenAmount;
}
function forward(uint256 _amount) internal {
wallet.transfer(_amount);
}
event NewRC(address contr);
function addRC(address _rc) onlyOwner public {
rc[ _rc ] = true;
emit NewRC(_rc);
}
function setTime(uint256 _newStart, uint256 _newEnd) public onlyOwner {
if ( _newStart != 0 ) startTime = _newStart;
if ( _newEnd != 0 ) endTime = _newEnd;
}
function withdrawTokens(address to, uint256 value) public onlyOwner returns (bool) {
return tokenContract.transfer(to, value);
}
function setTokenContract(address _tokenContract) public onlyOwner {
tokenContract = tokenInterface(_tokenContract);
}
function setRateContract(address _rateAddress) public onlyOwner {
rateContract = rateInterface(_rateAddress);
}
function claim(address _buyer, uint256 _amount) onlyRC public returns(bool) {
return tokenContract.transfer(_buyer, _amount);
}
function () public payable {
revert();
}
}
contract MilestoneSystem {
using SafeMath for uint256;
tokenInterface public tokenContract;
DaicoCoinCrowd public tokenSaleContract;
uint256[] public time;
uint256[] public funds;
bool public locked = false;
uint256 public endTimeToReturnTokens;
uint8 public step = 0;
uint256 public constant timeframeMilestone = 3 days;
uint256 public constant timeframeDeath = 30 days;
uint256 public activeSupply;
uint256 public oneTokenInEur;
mapping(address => mapping(uint8 => uint256) ) public balance;
mapping(uint8 => uint256) public tokenDistrusted;
constructor(address _tokenAddress, uint256[] _time, uint256[] _funds, uint256 _oneTokenInEur, uint256 _activeSupply) public {
require( _time.length != 0, "_time.length != 0" );
require( _time.length == _funds.length, "_time.length == _funds.length" );
tokenContract = tokenInterface(_tokenAddress);
tokenSaleContract = DaicoCoinCrowd(msg.sender);
time = _time;
funds = _funds;
activeSupply = _activeSupply;
oneTokenInEur = _oneTokenInEur;
}
modifier onlyTokenSaleOwner() {
require(msg.sender == tokenSaleContract.owner(), "msg.sender == tokenSaleContract.owner()" );
_;
}
event Distrust(address sender, uint256 amount);
event Locked();
function distrust(address _from, uint _value, bytes _data) public {
require(msg.sender == address(tokenContract), "msg.sender == address(tokenContract)");
if ( !locked ) {
uint256 startTimeMilestone = time[step].sub(timeframeMilestone);
uint256 endTimeMilestone = time[step];
uint256 startTimeProjectDeath = time[step].add(timeframeDeath);
bool unclaimedFunds = funds[step] > 0;
require(
( now > startTimeMilestone && now < endTimeMilestone ) ||
( now > startTimeProjectDeath && unclaimedFunds ),
"( now > startTimeMilestone && now < endTimeMilestone ) || ( now > startTimeProjectDeath && unclaimedFunds )"
);
} else {
require( locked && now < endTimeToReturnTokens ); //a timeframePost to deposit all tokens and then claim the refundMe method
}
balance[_from][step] = balance[_from][step].add(_value);
tokenDistrusted[step] = tokenDistrusted[step].add(_value);
emit Distrust(msg.sender, _value);
if( tokenDistrusted[step] > activeSupply && !locked ) {
locked = true;
endTimeToReturnTokens = now.add(timeframeDeath);
emit Locked();
}
}
function tokenFallback(address _from, uint _value, bytes _data) public {
distrust( _from, _value, _data);
}
function receiveApproval( address _from, uint _value, bytes _data) public {
require(msg.sender == address(tokenContract), "msg.sender == address(tokenContract)");
require(msg.sender.call(bytes4(keccak256("transferFrom(address,address,uint256)")), _from, this, _value));
distrust( _from, _value, _data);
}
event Trust(address sender, uint256 amount);
event Unlocked();
function trust(uint8 _step) public {
require( balance[msg.sender][_step] > 0 , "balance[msg.sender] > 0");
uint256 amount = balance[msg.sender][_step];
balance[msg.sender][_step] = 0;
tokenDistrusted[_step] = tokenDistrusted[_step].sub(amount);
tokenContract.transfer(msg.sender, amount);
emit Trust(msg.sender, amount);
if( tokenDistrusted[step] <= activeSupply && locked ) {
locked = false;
endTimeToReturnTokens = 0;
emit Unlocked();
}
}
event Refund(address sender, uint256 money);
function refundMe() public {
require(locked, "locked");
require( now > endTimeToReturnTokens, "now > endTimeToReturnTokens" );
uint256 ethTot = address(this).balance;
require( ethTot > 0 , "ethTot > 0");
uint256 tknAmount = balance[msg.sender][step];
require( tknAmount > 0 , "tknAmount > 0");
balance[msg.sender][step] = 0;
tokenContract.burn(tknAmount);
uint256 tknTot = tokenDistrusted[step];
uint256 rate = tknAmount.mul(1 ether).div(tknTot);
uint256 money = ethTot.mul(rate).div(1 ether);
uint256 moneyMax = tknAmount.mul( tokenSaleContract.tokenValueInEther( oneTokenInEur )).div(1 ether) ;
if ( money > moneyMax) { //This protects the project from the overvaluation of ether
money = moneyMax;
}
if( money > address(this).balance ) {
money = address(this).balance;
}
msg.sender.transfer(money);
emit Refund(msg.sender, money);
}
function OwnerWithdraw() public onlyTokenSaleOwner {
require(!locked, "!locked");
require(now > time[step], "now > time[step]");
require(funds[step] > 0, "funds[step] > 0");
uint256 amountApplied = funds[step];
funds[step] = 0;
step = step+1;
uint256 value;
if( amountApplied > address(this).balance || time.length == step+1)
value = address(this).balance;
else {
value = amountApplied;
}
msg.sender.transfer(value);
}
function OwnerWithdrawTokens(address _tokenContract, address to, uint256 value) public onlyTokenSaleOwner returns (bool) { //for airdrop reason to distribute to CoinCrowd Token Holder
require( _tokenContract != address(tokenContract), "_tokenContract != address(tokenContract)"); // the owner can withdraw tokens except CoinCrowd Tokens
return tokenInterface(_tokenContract).transfer(to, value);
}
function () public payable {
require(msg.sender == address(tokenSaleContract), "msg.sender == address(tokenSaleContract)");
}
}