This repository has been archived by the owner on Mar 6, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
/
RewardsInitiator.sol
105 lines (86 loc) · 4.08 KB
/
RewardsInitiator.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
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.15;
import "@openzeppelin/contracts/access/Ownable.sol";
import "./interfaces/IStakingPool.sol";
import "./interfaces/IStrategy.sol";
import "./interfaces/ISDLPoolCCIPControllerPrimary.sol";
/**
* @title Rewards Initiator
* @notice Updates and distributes rewards across the staking pool and cross-chain SDL Pools
* @dev Chainlink automation should call updateRewards periodically under normal circumstances and call performUpkeep
* in the case of a negative rebase in the staking pool
*/
contract RewardsInitiator is Ownable {
IStakingPool public stakingPool;
ISDLPoolCCIPControllerPrimary public sdlPoolCCIPController;
mapping(address => bool) public whitelistedCallers;
event WhitelistCaller(address indexed caller, bool shouldWhitelist);
error NoStrategiesToUpdate();
error PositiveDepositChange();
error SenderNotAuthorized();
constructor(address _stakingPool, address _sdlPoolCCIPController) {
stakingPool = IStakingPool(_stakingPool);
sdlPoolCCIPController = ISDLPoolCCIPControllerPrimary(_sdlPoolCCIPController);
}
/**
* @notice updates strategy rewards in the staking pool and distributes rewards to cross-chain SDL pools
* @param _strategyIdxs indexes of strategies to update rewards for
* @param _data encoded data to be passed to each strategy
**/
function updateRewards(uint256[] calldata _strategyIdxs, bytes calldata _data) external {
if (!whitelistedCallers[msg.sender]) revert SenderNotAuthorized();
stakingPool.updateStrategyRewards(_strategyIdxs, _data);
sdlPoolCCIPController.distributeRewards();
}
/**
* @notice returns whether or not rewards should be updated due to a negative rebase and the strategies to update
* @return upkeepNeeded whether or not rewards should be updated
* @return performData abi encoded list of strategy indexes to update
**/
function checkUpkeep(bytes calldata) external view returns (bool, bytes memory) {
address[] memory strategies = stakingPool.getStrategies();
bool[] memory strategiesToUpdate = new bool[](strategies.length);
uint256 totalStrategiesToUpdate;
for (uint256 i = 0; i < strategies.length; ++i) {
IStrategy strategy = IStrategy(strategies[i]);
if (strategy.getDepositChange() < 0) {
strategiesToUpdate[i] = true;
totalStrategiesToUpdate++;
}
}
if (totalStrategiesToUpdate != 0) {
uint256[] memory strategyIdxs = new uint256[](totalStrategiesToUpdate);
uint256 strategiesAdded;
for (uint256 i = 0; i < strategiesToUpdate.length; ++i) {
if (strategiesToUpdate[i]) {
strategyIdxs[strategiesAdded] = i;
strategiesAdded++;
}
}
return (true, abi.encode(strategyIdxs));
}
return (false, "0x");
}
/**
* @notice Updates rewards in the case of a negative rebase
* @param _performData abi encoded list of strategy indexes to update
*/
function performUpkeep(bytes calldata _performData) external {
address[] memory strategies = stakingPool.getStrategies();
uint256[] memory strategiesToUpdate = abi.decode(_performData, (uint256[]));
if (strategiesToUpdate.length == 0) revert NoStrategiesToUpdate();
for (uint256 i = 0; i < strategiesToUpdate.length; ++i) {
if (IStrategy(strategies[strategiesToUpdate[i]]).getDepositChange() >= 0) revert PositiveDepositChange();
}
stakingPool.updateStrategyRewards(strategiesToUpdate, "");
}
/**
* @notice Adds or removes an address from the whitelist for calling updateRewards
* @param _caller address to add/remove
* @param _shouldWhitelist whether address should be whitelisted
*/
function whitelistCaller(address _caller, bool _shouldWhitelist) external onlyOwner {
whitelistedCallers[_caller] = _shouldWhitelist;
emit WhitelistCaller(_caller, _shouldWhitelist);
}
}