diff --git a/contracts/bonding/BondingManager.sol b/contracts/bonding/BondingManager.sol index 691894d0..28553396 100644 --- a/contracts/bonding/BondingManager.sol +++ b/contracts/bonding/BondingManager.sol @@ -863,21 +863,35 @@ contract BondingManager is ManagerProxyTarget, IBondingManager { * @param _newPosPrev Address of previous transcoder in pool if the caller is in the pool * @param _newPosNext Address of next transcoder in pool if the caller is in the pool */ - function rewardWithHint(address _newPosPrev, address _newPosNext) - public - whenSystemNotPaused - currentRoundInitialized - autoCheckpoint(msg.sender) - { + function rewardWithHint(address _newPosPrev, address _newPosNext) public { + rewardForTranscoderWithHint(msg.sender, _newPosPrev, _newPosNext); + } + + /** + * @notice Mint token rewards for an active transcoder and its delegators and update the transcoder pool using an optional list hint if needed + * @dev If the `_transcoder` is in the transcoder pool, the caller can provide an optional hint for its insertion position in the + * pool via the `_newPosPrev` and `_newPosNext` params. A linear search will be executed starting at the hint to find the correct position. + * In the best case, the hint is the correct position so no search is executed. See SortedDoublyLL.sol for details on list hints + * @dev Permissionless: callable by anyone for any active transcoder. Rewards always accrue to and are checkpointed + * for `_transcoder`, never the caller, so a call can only ever benefit the transcoder. + * @param _transcoder Address of the transcoder on behalf of which the reward is called + * @param _newPosPrev Address of previous transcoder in pool if the `_transcoder` is in the pool + * @param _newPosNext Address of next transcoder in pool if the `_transcoder` is in the pool + */ + function rewardForTranscoderWithHint( + address _transcoder, + address _newPosPrev, + address _newPosNext + ) public whenSystemNotPaused currentRoundInitialized autoCheckpoint(_transcoder) { uint256 currentRound = roundsManager().currentRound(); - require(isActiveTranscoder(msg.sender), "caller must be an active transcoder"); + require(isActiveTranscoder(_transcoder), "transcoder must be active"); require( - transcoders[msg.sender].lastRewardRound != currentRound, + transcoders[_transcoder].lastRewardRound != currentRound, "caller has already called reward for the current round" ); - Transcoder storage t = transcoders[msg.sender]; + Transcoder storage t = transcoders[_transcoder]; EarningsPool.Data storage earningsPool = t.earningsPoolPerRound[currentRound]; // Set last round that transcoder called reward @@ -910,17 +924,17 @@ contract BondingManager is ManagerProxyTarget, IBondingManager { mtr.trustedTransferTokens(trsry, treasuryRewards); - emit TreasuryReward(msg.sender, trsry, treasuryRewards); + emit TreasuryReward(_transcoder, trsry, treasuryRewards); } uint256 transcoderRewards = totalRewardTokens.sub(treasuryRewards); - updateTranscoderWithRewards(msg.sender, transcoderRewards, currentRound, _newPosPrev, _newPosNext); + updateTranscoderWithRewards(_transcoder, transcoderRewards, currentRound, _newPosPrev, _newPosNext); // Set last round that transcoder called reward t.lastRewardRound = currentRound; - emit Reward(msg.sender, transcoderRewards); + emit Reward(_transcoder, transcoderRewards); } /** diff --git a/contracts/bonding/IBondingManager.sol b/contracts/bonding/IBondingManager.sol index b7482085..a90606fb 100644 --- a/contracts/bonding/IBondingManager.sol +++ b/contracts/bonding/IBondingManager.sol @@ -71,6 +71,16 @@ interface IBondingManager { function setCurrentRoundTotalActiveStake() external; + function reward() external; + + function rewardWithHint(address _newPosPrev, address _newPosNext) external; + + function rewardForTranscoderWithHint( + address _transcoder, + address _newPosPrev, + address _newPosNext + ) external; + // Public functions function getTranscoderPoolSize() external view returns (uint256);