forked from nazariyv/Contracts-2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathITOPool.sol
139 lines (118 loc) · 4.61 KB
/
ITOPool.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
pragma solidity 0.6.12;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract ITOPool is Ownable, ReentrancyGuard {
using SafeMath for uint256;
using SafeERC20 for ERC20;
uint256 public tokenPrice;
ERC20 public rewardToken;
uint256 public decimals;
uint256 public startTimestamp;
uint256 public finishTimestamp;
uint256 public startClaimTimestamp;
uint256 public minEthPayment;
uint256 public maxEthPayment;
uint256 public maxDistributedTokenAmount;
uint256 public tokensForDistribution;
uint256 public distributedTokens;
struct UserInfo {
uint debt;
uint total;
uint totalInvestedETH;
}
mapping(address => UserInfo) public userInfo;
event TokensDebt(
address indexed holder,
uint256 ethAmount,
uint256 tokenAmount
);
event TokensWithdrawn(address indexed holder, uint256 amount);
constructor(
uint256 _tokenPrice,
ERC20 _rewardToken,
uint256 _startTimestamp,
uint256 _finishTimestamp,
uint256 _startClaimTimestamp,
uint256 _minEthPayment,
uint256 _maxEthPayment,
uint256 _maxDistributedTokenAmount
) public {
tokenPrice = _tokenPrice;
rewardToken = _rewardToken;
decimals = rewardToken.decimals();
require(
_startTimestamp < _finishTimestamp,
"Start timestamp must be less than finish timestamp"
);
require(
_finishTimestamp > now,
"Finish timestamp must be more than current block"
);
startTimestamp = _startTimestamp;
finishTimestamp = _finishTimestamp;
startClaimTimestamp = _startClaimTimestamp;
minEthPayment = _minEthPayment;
maxEthPayment = _maxEthPayment;
maxDistributedTokenAmount = _maxDistributedTokenAmount;
}
function pay() payable external {
require(msg.value >= minEthPayment, "Less then min amount");
require(msg.value <= maxEthPayment, "More then max amount");
require(now >= startTimestamp, "Not started");
require(now < finishTimestamp, "Ended");
uint256 tokenAmount = getTokenAmount(msg.value);
require(tokensForDistribution.add(tokenAmount) <= maxDistributedTokenAmount, "Overfilled");
UserInfo storage user = userInfo[msg.sender];
require(user.totalInvestedETH.add(msg.value) <= maxEthPayment, "More then max amount");
tokensForDistribution = tokensForDistribution.add(tokenAmount);
user.totalInvestedETH = user.totalInvestedETH.add(msg.value);
user.total = user.total.add(tokenAmount);
user.debt = user.debt.add(tokenAmount);
emit TokensDebt(msg.sender, msg.value, tokenAmount);
}
function getTokenAmount(uint256 ethAmount)
internal
view
returns (uint256)
{
return ethAmount.div(tokenPrice).mul(10**decimals);
}
/// @dev Allows to claim tokens for the specific user.
/// @param _user Token receiver.
function claimFor(address _user) external {
proccessClaim(_user);
}
/// @dev Allows to claim tokens for themselves.
function claim() external {
proccessClaim(msg.sender);
}
/// @dev Proccess the claim.
/// @param _receiver Token receiver.
function proccessClaim(
address _receiver
) internal nonReentrant{
require(now > startClaimTimestamp, "Distribution not started");
UserInfo storage user = userInfo[_receiver];
uint256 _amount = user.debt;
if (_amount > 0) {
user.debt = 0;
distributedTokens = distributedTokens.add(_amount);
rewardToken.safeTransfer(_receiver, _amount);
emit TokensWithdrawn(_receiver,_amount);
}
}
function withdrawETH(uint256 amount) external onlyOwner{
// This forwards all available gas. Be sure to check the return value!
(bool success, ) = msg.sender.call.value(amount)("");
require(success, "Transfer failed.");
}
function withdrawNotSoldTokens() external onlyOwner returns(bool success) {
require(now > finishTimestamp, "Withdraw allowed after stop accept ETH");
uint256 balance = rewardToken.balanceOf(address(this));
rewardToken.safeTransfer(msg.sender, balance.add(distributedTokens).sub(tokensForDistribution));
return true;
}
}