/
Crowdsale.sol
165 lines (141 loc) · 5.45 KB
/
Crowdsale.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
157
158
159
160
161
162
163
164
165
/**
* 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.8;
import "./SafeMathLib.sol";
import "./PricingStrategy.sol";
import "./FinalizeAgent.sol";
import "./FractionalERC20.sol";
import "./CrowdsaleBase.sol";
/**
* Abstract base contract for token sales with the default buy entry points.
*
* Handle
* - start and end dates
* - accepting investments
* - minimum funding goal and refund
* - various statistics during the crowdfund
* - different pricing strategies
* - different investment policies (require server side customer id, allow only whitelisted addresses)
*
* Does not Handle
*
* - Token allocation (minting vs. transfer)
* - Cap rules
*
*/
contract Crowdsale is CrowdsaleBase {
/* Do we need to have unique contributor id for each customer */
bool public requireCustomerId;
/**
* Do we verify that contributor has been cleared on the server side (accredited investors only).
* This method was first used in FirstBlood crowdsale to ensure all contributors have accepted terms on sale (on the web).
*/
bool public requiredSignedAddress;
/* Server side address that signed allowed contributors (Ethereum addresses) that can participate the crowdsale */
address public signerAddress;
function Crowdsale(address _token, PricingStrategy _pricingStrategy, address _multisigWallet, uint _start, uint _end, uint _minimumFundingGoal) CrowdsaleBase(_token, _pricingStrategy, _multisigWallet, _start, _end, _minimumFundingGoal) {
}
/**
* Preallocate tokens for the early investors.
*
* Preallocated tokens have been sold before the actual crowdsale opens.
* This function mints the tokens and moves the crowdsale needle.
*
* Investor count is not handled; it is assumed this goes for multiple investors
* and the token distribution happens outside the smart contract flow.
*
* No money is exchanged, as the crowdsale team already have received the payment.
*
* @param fullTokens tokens as full tokens - decimal places added internally
* @param weiPrice Price of a single full token in wei
*
*/
function preallocate(address receiver, uint fullTokens, uint weiPrice) public onlyOwner {
uint tokenAmount = fullTokens * 10**token.decimals();
uint weiAmount = weiPrice * fullTokens; // This can be also 0, we give out tokens for free
weiRaised = weiRaised.plus(weiAmount);
tokensSold = tokensSold.plus(tokenAmount);
investedAmountOf[receiver] = investedAmountOf[receiver].plus(weiAmount);
tokenAmountOf[receiver] = tokenAmountOf[receiver].plus(tokenAmount);
assignTokens(receiver, tokenAmount);
// Tell us invest was success
Invested(receiver, weiAmount, tokenAmount, 0);
}
/**
* Allow anonymous contributions to this crowdsale.
*/
function investWithSignedAddress(address addr, uint128 customerId, uint8 v, bytes32 r, bytes32 s) public payable {
bytes32 hash = sha256(addr);
if (ecrecover(hash, v, r, s) != signerAddress) throw;
if(customerId == 0) throw; // UUIDv4 sanity check
investInternal(addr, customerId);
}
/**
* Track who is the customer making the payment so we can send thank you email.
*/
function investWithCustomerId(address addr, uint128 customerId) public payable {
if(requiredSignedAddress) throw; // Crowdsale allows only server-side signed participants
if(customerId == 0) throw; // UUIDv4 sanity check
investInternal(addr, customerId);
}
/**
* Allow anonymous contributions to this crowdsale.
*/
function invest(address addr) public payable {
if(requireCustomerId) throw; // Crowdsale needs to track participants for thank you email
if(requiredSignedAddress) throw; // Crowdsale allows only server-side signed participants
investInternal(addr, 0);
}
/**
* Invest to tokens, recognize the payer and clear his address.
*
*/
function buyWithSignedAddress(uint128 customerId, uint8 v, bytes32 r, bytes32 s) public payable {
investWithSignedAddress(msg.sender, customerId, v, r, s);
}
/**
* Invest to tokens, recognize the payer.
*
*/
function buyWithCustomerIdWithChecksum(uint128 customerId, bytes1 checksum) public payable {
// see customerid.py
if (bytes1(sha3(customerId)) != checksum) throw;
investWithCustomerId(msg.sender, customerId);
}
/**
* Legacy API signature.
*/
function buyWithCustomerId(uint128 customerId) public payable {
investWithCustomerId(msg.sender, customerId);
}
/**
* The basic entry point to participate the crowdsale process.
*
* Pay for funding, get invested tokens back in the sender address.
*/
function buy() public payable {
invest(msg.sender);
}
/**
* Set policy do we need to have server-side customer ids for the investments.
*
*/
function setRequireCustomerId(bool value) onlyOwner {
requireCustomerId = value;
InvestmentPolicyChanged(requireCustomerId, requiredSignedAddress, signerAddress);
}
/**
* Set policy if all investors must be cleared on the server side first.
*
* This is e.g. for the accredited investor clearing.
*
*/
function setRequireSignedAddress(bool value, address _signerAddress) onlyOwner {
requiredSignedAddress = value;
signerAddress = _signerAddress;
InvestmentPolicyChanged(requireCustomerId, requiredSignedAddress, signerAddress);
}
}