-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathStakingPool
140 lines (120 loc) · 4.97 KB
/
StakingPool
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
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import '@openzeppelin/contracts/security/ReentrancyGuard.sol';
contract StakingPool is Ownable, ReentrancyGuard {
using SafeERC20 for IERC20;
struct Stake {
uint256 amount;
uint256 stakedTime;
}
address public token;
uint256 public apr;
uint256 public startTime;
uint256 public lockupPeriod;
uint256 public totalStakedUsers;
uint256 public totalDeposited;
uint256 public capacity;
bool public isClaimed;
bool public isStaked = true;
mapping(address => Stake) public stakes;
mapping(address => bool) public admin;
mapping(address => bool) public blacklist;
constructor(address _token, uint256 _apr, uint256 _startTime, uint256 _lockupPeriod, uint256 _capacity) {
token = _token;
apr = _apr;
startTime = _startTime;
lockupPeriod = _lockupPeriod;
capacity = _capacity;
admin[msg.sender] = true;
}
receive() external payable {}
function stake(uint256 amount) external nonReentrant {
require(isStaked, "isStaked");
require(!blacklist[_msgSender()], "blacklist");
require(block.timestamp >= startTime, "startTime");
require(totalDeposited + amount <= capacity, "capacity");
IERC20(token).safeTransferFrom(_msgSender(), address(this), amount);
uint256 sharesBefore = stakes[_msgSender()].amount;
totalDeposited += amount;
stakes[_msgSender()].amount += amount;
stakes[_msgSender()].stakedTime = block.timestamp;
if (sharesBefore == 0 && stakes[_msgSender()].amount > 0) {
totalStakedUsers++;
}
emit StakeToken(_msgSender(), amount, block.timestamp);
}
function unStake() external nonReentrant {
require(isClaimed, "isClaimed");
require(block.timestamp > stakes[_msgSender()].stakedTime + lockupPeriod, "timelock");
require(stakes[_msgSender()].amount > 0, "amount");
totalDeposited -= stakes[_msgSender()].amount;
totalStakedUsers--;
uint reward = (stakes[_msgSender()].amount * apr * lockupPeriod) / 365 days / 100;
uint amount = reward + stakes[_msgSender()].amount;
stakes[_msgSender()].amount = 0;
stakes[_msgSender()].stakedTime = block.timestamp;
IERC20(token).safeTransfer(_msgSender(), amount);
emit UnstakeToken(_msgSender(), amount, block.timestamp);
}
function rewardOf(address user) public view returns(uint256) {
if(stakes[user].stakedTime + lockupPeriod > block.timestamp){
return 0;
}
uint256 reward = (stakes[user].amount * apr * lockupPeriod) / 365 days / 100;
return reward;
}
function setAdmin(address _admin, bool _status) external onlyOwner {
admin[_admin] = _status;
emit SetAdmin(_admin, _status, block.timestamp);
}
function setClaim(bool status) external onlyOwner {
isClaimed = status;
emit SetClaim(status, block.timestamp);
}
function setStake(bool status) external onlyOwner {
isStaked = status;
emit SetStake(status, block.timestamp);
}
function setTime(uint256 _start) external onlyOwner {
startTime = _start;
emit SetTime(_start, block.timestamp);
}
function setAPR(uint8 _newAPR) external onlyOwner {
apr = _newAPR;
}
function setBlacklist(address[] memory _acc, bool[] memory _status) external {
require(admin[msg.sender], "onlyAdmin");
require(_acc.length == _status.length, "length");
for(uint i = 0; i < _acc.length; i++){
blacklist[_acc[i]] = _status[i];
emit SetBlacklist(_acc[i], _status[i], block.timestamp);
}
}
function setCapacity(uint _cap) external onlyOwner {
capacity = _cap;
emit SetCap(_cap, block.timestamp);
}
function withdrawEther() external onlyOwner {
(bool success, ) = msg.sender.call{value: address(this).balance}("");
require(success, "Transfer failed.");
}
function withdrawToken(address _token) external onlyOwner {
uint256 amount = IERC20(_token).balanceOf(address(this));
IERC20(_token).transfer(msg.sender, amount);
}
function setLockupPeriod(uint256 _seconds) external onlyOwner {
require(_seconds < 365 days, 'lte 1 year');
lockupPeriod = _seconds;
}
event SetAdmin(address admin, bool status, uint blockTime);
event SetBlacklist(address user, bool status, uint blockTime);
event SetCap(uint capacity, uint blockTime);
event SetClaim(bool status, uint blockTime);
event SetStake(bool status, uint blockTime);
event StakeToken(address user, uint amount, uint blockTime);
event UnstakeToken(address user, uint amount, uint blockTime);
event SetTime(uint startTime, uint blockTime);
}