-
Notifications
You must be signed in to change notification settings - Fork 561
/
TokenTranchePricing.sol
156 lines (122 loc) · 4.86 KB
/
TokenTranchePricing.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/**
* 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 Tranche based pricing with special support for pre-ico deals.
/// Implementing "first price" tranches, meaning, that if buyers order is
/// covering more than one tranche, the price of the lowest tranche will apply
/// to the whole order.
contract TokenTranchePricing is PricingStrategy, Ownable {
using SafeMathLib for uint;
uint public constant MAX_TRANCHES = 10;
// This contains all pre-ICO addresses, and their prices (weis per token)
mapping (address => uint) public preicoAddresses;
/**
* Define pricing schedule using tranches.
*/
struct Tranche {
// Amount in weis when this tranche becomes active
uint amount;
// How many tokens per satoshi you will get while this tranche is active
uint price;
}
// Store tranches in a fixed array, so that it can be seen in a blockchain explorer
// Tranche 0 is always (0, 0)
// (TODO: change this when we confirm dynamic arrays are explorable)
Tranche[10] public tranches;
// How many active tranches we have
uint public trancheCount;
/// @dev Contruction, creating a list of tranches
/// @param _tranches uint[] tranches Pairs of (start amount, price)
function TokenTranchePricing(uint[] _tranches) {
// Need to have tuples, length check
if(_tranches.length % 2 == 1 || _tranches.length >= MAX_TRANCHES*2) {
throw;
}
trancheCount = _tranches.length / 2;
uint highestAmount = 0;
for(uint i=0; i<_tranches.length/2; i++) {
tranches[i].amount = _tranches[i*2];
tranches[i].price = _tranches[i*2+1];
// No invalid steps
if((highestAmount != 0) && (tranches[i].amount <= highestAmount)) {
throw;
}
highestAmount = tranches[i].amount;
}
// Last tranche price must be zero, terminating the crowdale
if(tranches[trancheCount-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 tranches. You reach end of tranches when price = 0
/// @return tuple (time, price)
function getTranche(uint n) public constant returns (uint, uint) {
return (tranches[n].amount, tranches[n].price);
}
function getFirstTranche() private constant returns (Tranche) {
return tranches[0];
}
function getLastTranche() private constant returns (Tranche) {
return tranches[trancheCount-1];
}
function getPricingStartsAt() public constant returns (uint) {
return getFirstTranche().amount;
}
function getPricingEndsAt() public constant returns (uint) {
return getLastTranche().amount;
}
function isSane(address _crowdsale) public constant returns(bool) {
// Our tranches are not bound by time, so we can't really check are we sane
// so we presume we are ;)
// In the future we could save and track raised tokens, and compare it to
// the Crowdsale contract.
return true;
}
/// @dev Get the current tranche or bail out if we are not in the tranche periods.
/// @param tokensSold total amount of tokens sold, for calculating the current tranche
/// @return {[type]} [description]
function getCurrentTranche(uint tokensSold) private constant returns (Tranche) {
uint i;
for(i=0; i < tranches.length; i++) {
if(tokensSold < tranches[i].amount) {
return tranches[i-1];
}
}
}
/// @dev Get the current price.
/// @param tokensSold total amount of tokens sold, for calculating the current tranche
/// @return The current price or 0 if we are outside trache ranges
function getCurrentPrice(uint tokensSold) public constant returns (uint result) {
return getCurrentTranche(tokensSold).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(tokensSold);
return value.times(multiplier) / price;
}
function() payable {
throw; // No money on this contract
}
}