Permalink
Cannot retrieve contributors at this time
/** | |
* This smart contract code is Copyright 2017 TokenMarket Ltd. For more information see https://tokenmarket.net | |
* | |
* Licensed under the Apache License, version 2.0: https://github.com/TokenMarketNet/ico/blob/master/LICENSE.txt | |
*/ | |
pragma solidity ^0.4.6; | |
import "./PricingStrategy.sol"; | |
import "./Crowdsale.sol"; | |
import "./SafeMathLib.sol"; | |
import "zeppelin/contracts/ownership/Ownable.sol"; | |
/// @dev Time milestone based pricing with special support for pre-ico deals. | |
contract MilestonePricing is PricingStrategy, Ownable { | |
using SafeMathLib for uint; | |
uint public constant MAX_MILESTONE = 10; | |
// This contains all pre-ICO addresses, and their prices (weis per token) | |
mapping (address => uint) public preicoAddresses; | |
/** | |
* Define pricing schedule using milestones. | |
*/ | |
struct Milestone { | |
// UNIX timestamp when this milestone kicks in | |
uint time; | |
// How many tokens per wei you will get after this milestone has been passed | |
uint price; | |
} | |
// Store milestones in a fixed array, so that it can be seen in a blockchain explorer | |
// Milestone 0 is always (0, 0) | |
// (TODO: change this when we confirm dynamic arrays are explorable) | |
Milestone[10] public milestones; | |
// How many active milestones we have | |
uint public milestoneCount; | |
/// @dev Contruction, creating a list of milestones | |
/// @param _milestones uint[] milestones Pairs of (time, price) | |
function MilestonePricing(uint[] _milestones) { | |
// Need to have tuples, length check | |
if(_milestones.length % 2 == 1 || _milestones.length >= MAX_MILESTONE*2) { | |
throw; | |
} | |
milestoneCount = _milestones.length / 2; | |
uint lastTimestamp = 0; | |
for(uint i=0; i<_milestones.length/2; i++) { | |
milestones[i].time = _milestones[i*2]; | |
milestones[i].price = _milestones[i*2+1]; | |
// No invalid steps | |
if((lastTimestamp != 0) && (milestones[i].time <= lastTimestamp)) { | |
throw; | |
} | |
lastTimestamp = milestones[i].time; | |
} | |
// Last milestone price must be zero, terminating the crowdale | |
if(milestones[milestoneCount-1].price != 0) { | |
throw; | |
} | |
} | |
/// @dev This is invoked once for every pre-ICO address, set pricePerToken | |
/// to 0 to disable | |
/// @param preicoAddress PresaleFundCollector address | |
/// @param pricePerToken How many weis one token cost for pre-ico investors | |
function setPreicoAddress(address preicoAddress, uint pricePerToken) | |
public | |
onlyOwner | |
{ | |
preicoAddresses[preicoAddress] = pricePerToken; | |
} | |
/// @dev Iterate through milestones. You reach end of milestones when price = 0 | |
/// @return tuple (time, price) | |
function getMilestone(uint n) public constant returns (uint, uint) { | |
return (milestones[n].time, milestones[n].price); | |
} | |
function getFirstMilestone() private constant returns (Milestone) { | |
return milestones[0]; | |
} | |
function getLastMilestone() private constant returns (Milestone) { | |
return milestones[milestoneCount-1]; | |
} | |
function getPricingStartsAt() public constant returns (uint) { | |
return getFirstMilestone().time; | |
} | |
function getPricingEndsAt() public constant returns (uint) { | |
return getLastMilestone().time; | |
} | |
function isSane(address _crowdsale) public constant returns(bool) { | |
Crowdsale crowdsale = Crowdsale(_crowdsale); | |
return crowdsale.startsAt() == getPricingStartsAt() && crowdsale.endsAt() == getPricingEndsAt(); | |
} | |
/// @dev Get the current milestone or bail out if we are not in the milestone periods. | |
/// @return {[type]} [description] | |
function getCurrentMilestone() private constant returns (Milestone) { | |
uint i; | |
for(i=0; i<milestones.length; i++) { | |
if(now < milestones[i].time) { | |
return milestones[i-1]; | |
} | |
} | |
} | |
/// @dev Get the current price. | |
/// @return The current price or 0 if we are outside milestone period | |
function getCurrentPrice() public constant returns (uint result) { | |
return getCurrentMilestone().price; | |
} | |
/// @dev Calculate the current price for buy in amount. | |
function calculatePrice(uint value, uint weiRaised, uint tokensSold, address msgSender, uint decimals) public constant returns (uint) { | |
uint multiplier = 10 ** decimals; | |
// This investor is coming through pre-ico | |
if(preicoAddresses[msgSender] > 0) { | |
return value.times(multiplier) / preicoAddresses[msgSender]; | |
} | |
uint price = getCurrentPrice(); | |
return value.times(multiplier) / price; | |
} | |
function isPresalePurchase(address purchaser) public constant returns (bool) { | |
if(preicoAddresses[purchaser] > 0) | |
return true; | |
else | |
return false; | |
} | |
function() payable { | |
throw; // No money on this contract | |
} | |
} |