Skip to content

Commit

Permalink
support redepositing of rewards in staking/priority pools
Browse files Browse the repository at this point in the history
  • Loading branch information
BkChoy committed Sep 6, 2023
1 parent dc8425e commit dcad958
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 32 deletions.
72 changes: 45 additions & 27 deletions contracts/core/PriorityPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ contract PriorityPool is UUPSUpgradeable, OwnableUpgradeable, PausableUpgradeabl
ISDLPool public sdlPool;
address public distributionOracle;

uint256 public queueDepositThreshold;
uint128 public queueDepositMin;
uint128 public queueDepositMax;
PoolStatus public poolStatus;

bytes32 public merkleRoot;
Expand Down Expand Up @@ -59,7 +60,7 @@ contract PriorityPool is UUPSUpgradeable, OwnableUpgradeable, PausableUpgradeabl
uint256 incrementalSharesAmount
);
event SetPoolStatus(PoolStatus status);
event SetQueueDepositThreshold(uint256 threshold);
event SetQueueDepositParams(uint128 queueDepositMin, uint128 queueDepositMax);
event DepositQueuedTokens(uint256 amount);

error InvalidValue();
Expand All @@ -86,21 +87,24 @@ contract PriorityPool is UUPSUpgradeable, OwnableUpgradeable, PausableUpgradeabl
* @param _token address of asset token
* @param _stakingPool address of staking pool
* @param _sdlPool address of SDL pool
* @param _queueDepositThreshold min amount of tokens needed to execute deposit
* @param _queueDepositMin min amount of tokens needed to execute deposit
* @param _queueDepositMax max amount of tokens in a single deposit
**/
function initialize(
address _token,
address _stakingPool,
address _sdlPool,
uint256 _queueDepositThreshold
uint128 _queueDepositMin,
uint128 _queueDepositMax
) public initializer {
__UUPSUpgradeable_init();
__Ownable_init();
__Pausable_init();
token = IERC20Upgradeable(_token);
stakingPool = IStakingPool(_stakingPool);
sdlPool = ISDLPool(_sdlPool);
queueDepositThreshold = _queueDepositThreshold;
queueDepositMin = _queueDepositMin;
queueDepositMax = _queueDepositMax;
accounts.push(address(0));
token.safeIncreaseAllowance(_stakingPool, type(uint256).max);
}
Expand Down Expand Up @@ -323,32 +327,35 @@ contract PriorityPool is UUPSUpgradeable, OwnableUpgradeable, PausableUpgradeabl

/**
* @notice deposits queued tokens into the staking pool
* @dev bypasses queueDepositThreshold
* @dev bypasses queueDepositMin
*/
function depositQueuedTokens() external {
_depositQueuedTokens(0);
}

/**
* @notice returns whether a call should be made to performUpkeep to deposit queued tokens
* @notice returns whether a call should be made to performUpkeep to deposit queued/unused tokens
* into the staking pool
* @dev used by chainlink keepers
*/
function checkUpkeep(bytes calldata) external view returns (bool, bytes memory) {
uint256 canDeposit = stakingPool.canDeposit();
uint256 strategyDepositRoom = stakingPool.getStrategyDepositRoom();
uint256 unusedDeposits = stakingPool.getUnusedDeposits();
return (
poolStatus == PoolStatus.OPEN && totalQueued >= queueDepositThreshold && canDeposit >= queueDepositThreshold,
poolStatus == PoolStatus.OPEN &&
strategyDepositRoom >= queueDepositMin &&
(totalQueued + unusedDeposits) >= queueDepositMin,
bytes("")
);
}

/**
* @notice deposits queued tokens into the staking pool
* @dev will revert if less than queueDepositThreshold tokens can be deposited
* @dev will revert if less than queueDepositMin tokens can be deposited
* @dev used by chainlink keepers
*/
function performUpkeep(bytes calldata) external {
_depositQueuedTokens(queueDepositThreshold);
_depositQueuedTokens(queueDepositMin);
}

/**
Expand Down Expand Up @@ -442,12 +449,14 @@ contract PriorityPool is UUPSUpgradeable, OwnableUpgradeable, PausableUpgradeabl
}

/**
* @notice sets the minimum amount of tokens needed to execute a deposit
* @param _queueDepositThreshold min amount of tokens
* @notice sets the minimum and maximum amount that can be deposited
* @param _queueDepositMin min amount of tokens
* @param _queueDepositMax max amount of tokens
*/
function setQueueDepositThreshold(uint256 _queueDepositThreshold) external onlyOwner {
queueDepositThreshold = _queueDepositThreshold;
emit SetQueueDepositThreshold(_queueDepositThreshold);
function setQueueDepositThreshold(uint128 _queueDepositMin, uint128 _queueDepositMax) external onlyOwner {
queueDepositMin = _queueDepositMin;
queueDepositMax = _queueDepositMin;
emit SetQueueDepositParams(_queueDepositMin, _queueDepositMax);
}

/**
Expand Down Expand Up @@ -524,25 +533,34 @@ contract PriorityPool is UUPSUpgradeable, OwnableUpgradeable, PausableUpgradeabl

/**
* @notice deposits queued tokens
* @param _depositThreshold min amount of tokens required for successful deposit
* @param _depositMin min amount of tokens required to deposit
**/
function _depositQueuedTokens(uint256 _depositThreshold) internal {
function _depositQueuedTokens(uint256 _depositMin) internal {
if (poolStatus != PoolStatus.OPEN) revert DepositsDisabled();

uint256 canDeposit = stakingPool.canDeposit();
if (canDeposit == 0 || canDeposit < _depositThreshold) revert InsufficientDepositRoom();
uint256 strategyDepositRoom = stakingPool.getStrategyDepositRoom();
if (strategyDepositRoom == 0 || strategyDepositRoom < _depositMin) revert InsufficientDepositRoom();

uint256 _totalQueued = totalQueued;
if (_totalQueued == 0 || _totalQueued < _depositThreshold) revert InsufficientQueuedTokens();
uint256 unusedDeposits = stakingPool.getUnusedDeposits();
uint256 canDeposit = _totalQueued + unusedDeposits;
if (canDeposit == 0 || canDeposit < _depositMin) revert InsufficientQueuedTokens();

uint256 toDeposit = _totalQueued <= canDeposit ? _totalQueued : canDeposit;
uint256 toDepositFromStakingPool = MathUpgradeable.min(
MathUpgradeable.min(unusedDeposits, strategyDepositRoom),
queueDepositMax
);
uint256 toDepositFromQueue = MathUpgradeable.min(
MathUpgradeable.min(_totalQueued, strategyDepositRoom - toDepositFromStakingPool),
queueDepositMax - toDepositFromStakingPool
);

totalQueued = _totalQueued - toDeposit;
depositsSinceLastUpdate += toDeposit;
sharesSinceLastUpdate += stakingPool.getSharesByStake(toDeposit);
stakingPool.deposit(address(this), toDeposit);
totalQueued = _totalQueued - toDepositFromQueue;
depositsSinceLastUpdate += toDepositFromQueue;
sharesSinceLastUpdate += stakingPool.getSharesByStake(toDepositFromQueue);
stakingPool.deposit(address(this), toDepositFromQueue);

emit DepositQueuedTokens(toDeposit);
emit DepositQueuedTokens(toDepositFromQueue);
}

/**
Expand Down
37 changes: 32 additions & 5 deletions contracts/core/StakingPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,31 @@ contract StakingPool is StakingRewardsPool {
return min;
}

/**
* @notice returns the amont of tokens sitting in the pool outside a strategy
* @dev these tokens earn no yield and should be deposited ASAP
* @return amount of tokens outside a strategy
*/
function getUnusedDeposits() external view returns (uint256) {
return token.balanceOf(address(this));
}

/**
* @notice returns the available deposit room for this pool's strategies
* @return strategy deposit room
*/
function getStrategyDepositRoom() external view returns (uint256) {
uint256 depositRoom;
for (uint256 i = 0; i < strategies.length; ++i) {
uint strategyDepositRoom = IStrategy(strategies[i]).canDeposit();
if (strategyDepositRoom >= type(uint256).max - depositRoom) {
return type(uint256).max;
}
depositRoom += strategyDepositRoom;
}
return depositRoom;
}

/**
* @notice returns the available deposit room for this pool
* @return available deposit room
Expand Down Expand Up @@ -205,13 +230,14 @@ contract StakingPool is StakingRewardsPool {
/**
* @notice removes a strategy
* @param _index index of strategy
* @param _strategyUpdateData encoded data to be passed to strategy
**/
function removeStrategy(uint256 _index) external onlyOwner {
function removeStrategy(uint256 _index, bytes memory _strategyUpdateData) external onlyOwner {
require(_index < strategies.length, "Strategy does not exist");

uint256[] memory idxs = new uint256[](1);
idxs[0] = _index;
updateStrategyRewards(idxs);
updateStrategyRewards(idxs, _strategyUpdateData);

IStrategy strategy = IStrategy(strategies[_index]);
uint256 totalStrategyDeposits = strategy.getTotalDeposits();
Expand Down Expand Up @@ -286,7 +312,7 @@ contract StakingPool is StakingRewardsPool {
* @return total rewards
* @return total fees
**/
function getStrategyRewards(uint256[] memory _strategyIdxs) external view returns (int256, uint256) {
function getStrategyRewards(uint256[] calldata _strategyIdxs) external view returns (int256, uint256) {
int256 totalRewards;
uint256 totalFees;

Expand All @@ -308,8 +334,9 @@ contract StakingPool is StakingRewardsPool {
/**
* @notice updates and distributes rewards based on balance changes in strategies
* @param _strategyIdxs indexes of strategies to update rewards for
* @param _data encoded data to be passed to each strategy
**/
function updateStrategyRewards(uint256[] memory _strategyIdxs) public {
function updateStrategyRewards(uint256[] memory _strategyIdxs, bytes memory _data) public {
int256 totalRewards;
uint256 totalFeeAmounts;
uint256 totalFeeCount;
Expand All @@ -320,7 +347,7 @@ contract StakingPool is StakingRewardsPool {
IStrategy strategy = IStrategy(strategies[_strategyIdxs[i]]);

(int256 depositChange, address[] memory strategyReceivers, uint256[] memory strategyFeeAmounts) = strategy
.updateDeposits();
.updateDeposits(_data);
totalRewards += depositChange;

if (strategyReceivers.length != 0) {
Expand Down
4 changes: 4 additions & 0 deletions contracts/core/interfaces/IStakingPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,8 @@ interface IStakingPool is IStakingRewardsPool {
function poolIndex() external view returns (uint16);

function canWithdraw() external view returns (uint256);

function getStrategyDepositRoom() external view returns (uint256);

function getUnusedDeposits() external view returns (uint256);
}

0 comments on commit dcad958

Please sign in to comment.