/
RewardsPoolFactory.sol
129 lines (112 loc) · 4.65 KB
/
RewardsPoolFactory.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
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
import "openzeppelin-solidity/contracts/math/Math.sol";
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
import "openzeppelin-solidity/contracts/access/Ownable.sol";
import "./interfaces/IERC20Detailed.sol";
import "./SafeERC20Detailed.sol";
import "./RewardsPoolBase.sol";
import "./AbstractPoolsFactory.sol";
contract RewardsPoolFactory is AbstractPoolsFactory {
using SafeMath for uint256;
using SafeERC20Detailed for IERC20Detailed;
event RewardsPoolDeployed(
address indexed rewardsPoolAddress,
address indexed stakingToken
);
/* ========== Permissioned FUNCTIONS ========== */
/** @dev Deploy a reward pool base contract for the staking token, with the given parameters.
* @param _stakingToken The address of the token being staked
* @param _startBlock The start block of the rewards pool
* @param _endBlock The end block of the rewards pool
* @param _rewardsTokens The addresses of the tokens the rewards will be paid in
* @param _rewardPerBlock Rewards per block
* @param _stakeLimit The stake limit per user
*/
function deploy(
address _stakingToken,
uint256 _startBlock,
uint256 _endBlock,
address[] memory _rewardsTokens,
uint256[] memory _rewardPerBlock,
uint256 _stakeLimit
) external onlyOwner {
require(
_stakingToken != address(0),
"RewardsPoolFactory::deploy: Staking token address can't be zero address"
);
require(
_rewardsTokens.length != 0,
"RewardsPoolFactory::deploy: RewardsTokens array could not be empty"
);
require(
_rewardsTokens.length == _rewardPerBlock.length,
"RewardsPoolFactory::deploy: RewardsTokens and RewardPerBlock should have a matching sizes"
);
for (uint256 i = 0; i < _rewardsTokens.length; i++) {
require(
_rewardsTokens[i] != address(0),
"RewardsPoolFactory::deploy: Reward token address could not be invalid"
);
require(
_rewardPerBlock[i] != 0,
"RewardsPoolFactory::deploy: Reward per block must be greater than zero"
);
}
require(
_stakeLimit != 0,
"RewardsPoolFactory::deploy: Stake limit must be more than 0"
);
address rewardsPoolBase =
address(
new RewardsPoolBase(
IERC20Detailed(_stakingToken),
_startBlock,
_endBlock,
_rewardsTokens,
_rewardPerBlock,
_stakeLimit
)
);
for (uint256 i = 0; i < _rewardsTokens.length; i++) {
uint256 rewardsAmount =
calculateRewardsAmount(
_startBlock,
_endBlock,
_rewardPerBlock[i]
);
IERC20Detailed(_rewardsTokens[i]).safeTransfer(
rewardsPoolBase,
rewardsAmount
);
}
rewardsPools.push(rewardsPoolBase);
emit RewardsPoolDeployed(rewardsPoolBase, _stakingToken);
}
/** @dev Function that will extend the rewards period, but not change the reward rate, for a given staking contract.
* @param _endBlock The new endblock for the rewards pool.
* @param _rewardsPerBlock Rewards per block .
* @param _rewardsPoolAddress The address of the RewardsPoolBase contract.
*/
function extendRewardPool(
uint256 _endBlock,
uint256[] memory _rewardsPerBlock,
address _rewardsPoolAddress
) external onlyOwner {
RewardsPoolBase pool = RewardsPoolBase(_rewardsPoolAddress);
uint256 currentEndBlock = pool.endBlock();
for (uint256 i = 0; i < _rewardsPerBlock.length; i++) {
uint256 currentRemainingReward = calculateRewardsAmount(block.number, currentEndBlock, pool.rewardPerBlock(i));
uint256 newRemainingReward = calculateRewardsAmount(block.number, _endBlock, _rewardsPerBlock[i]);
address rewardsToken = RewardsPoolBase(_rewardsPoolAddress).rewardsTokens(i);
if (newRemainingReward > currentRemainingReward) {
// Some more reward needs to be transferred to the rewards pool contract
IERC20Detailed(rewardsToken).safeTransfer(_rewardsPoolAddress, newRemainingReward.sub(currentRemainingReward));
}
}
RewardsPoolBase(_rewardsPoolAddress).extend(
_endBlock,
_rewardsPerBlock
);
}
}