Skip to content

Commit

Permalink
feat: _validatePerformanceRewardsSubmission
Browse files Browse the repository at this point in the history
  • Loading branch information
0xrajath committed Oct 16, 2024
1 parent 7ac5e7e commit 3832b9d
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 23 deletions.
118 changes: 97 additions & 21 deletions src/contracts/core/RewardsCoordinator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -185,27 +185,26 @@ contract RewardsCoordinator is
function createAVSPerformanceRewardsSubmission(
PerformanceRewardsSubmission[] calldata performanceRewardsSubmissions
) external onlyWhenNotPaused(PAUSED_AVS_PERFORMANCE_REWARDS_SUBMISSION) nonReentrant {
// for (uint256 i = 0; i < performanceRewardsSubmissions.length; i++) {
// PerformanceRewardsSubmission calldata performanceRewardsSubmission = performanceRewardsSubmissions[i];
// uint256 nonce = submissionNonce[msg.sender];
// bytes32 performanceRewardsSubmissionHash = keccak256(
// abi.encode(msg.sender, nonce, performanceRewardsSubmission)
// );
// _validateRewardsSubmission(performanceRewardsSubmission);
// isAVSPerformanceRewardsSubmissionHash[msg.sender][performanceRewardsSubmissionHash] = true;
// submissionNonce[msg.sender] = nonce + 1;
// emit AVSPerformanceRewardsSubmissionCreated(
// msg.sender,
// nonce,
// performanceRewardsSubmissionHash,
// performanceRewardsSubmission
// );
// performanceRewardsSubmission.token.safeTransferFrom(
// msg.sender,
// address(this),
// performanceRewardsSubmission.amount
// );
// }
for (uint256 i = 0; i < performanceRewardsSubmissions.length; i++) {
PerformanceRewardsSubmission calldata performanceRewardsSubmission = performanceRewardsSubmissions[i];
uint256 nonce = submissionNonce[msg.sender];
bytes32 performanceRewardsSubmissionHash = keccak256(
abi.encode(msg.sender, nonce, performanceRewardsSubmission)
);

uint256 totalAmount = _validatePerformanceRewardsSubmission(performanceRewardsSubmission);

isAVSPerformanceRewardsSubmissionHash[msg.sender][performanceRewardsSubmissionHash] = true;
submissionNonce[msg.sender] = nonce + 1;

emit AVSPerformanceRewardsSubmissionCreated(
msg.sender,
nonce,
performanceRewardsSubmissionHash,
performanceRewardsSubmission
);
performanceRewardsSubmission.token.safeTransferFrom(msg.sender, address(this), totalAmount);
}
}

/// @inheritdoc IRewardsCoordinator
Expand Down Expand Up @@ -364,6 +363,83 @@ contract RewardsCoordinator is
}
}

/**
* @notice Validate a PerformanceRewardsSubmission. Called from `createAVSPerformanceRewardsSubmission`.
* @param performanceRewardsSubmission PerformanceRewardsSubmission to validate.
* @return total amount to be transferred from the avs to the contract.
*/
function _validatePerformanceRewardsSubmission(
PerformanceRewardsSubmission calldata performanceRewardsSubmission
) internal view returns (uint256) {
require(
performanceRewardsSubmission.strategiesAndMultipliers.length > 0,
"RewardsCoordinator._validatePerformanceRewardsSubmission: no strategies set"
);
require(
performanceRewardsSubmission.operatorRewards.length > 0,
"RewardsCoordinator._validatePerformanceRewardsSubmission: no operators rewarded"
);

uint256 totalAmount = 0;
address currOperatorAddress = address(0);
for (uint256 i = 0; i < performanceRewardsSubmission.operatorRewards.length; ++i) {
OperatorReward calldata operatorReward = performanceRewardsSubmission.operatorRewards[i];
require(
operatorReward.operator != address(0),
"RewardsCoordinator._validatePerformanceRewardsSubmission: operator cannot be 0 address"
);
require(
currOperatorAddress < operatorReward.operator,
"RewardsCoordinator._validatePerformanceRewardsSubmission: operators must be in ascending order to handle duplicates"
);
currOperatorAddress = operatorReward.operator;
require(
operatorReward.amount > 0,
"RewardsCoordinator._validatePerformanceRewardsSubmission: operator reward amount cannot be 0"
);
totalAmount += operatorReward.amount;
}

require(
performanceRewardsSubmission.duration <= MAX_REWARDS_DURATION,
"RewardsCoordinator._validatePerformanceRewardsSubmission: duration exceeds MAX_REWARDS_DURATION"
);
require(
performanceRewardsSubmission.duration % CALCULATION_INTERVAL_SECONDS == 0,
"RewardsCoordinator._validatePerformanceRewardsSubmission: duration must be a multiple of CALCULATION_INTERVAL_SECONDS"
);
require(
performanceRewardsSubmission.startTimestamp % CALCULATION_INTERVAL_SECONDS == 0,
"RewardsCoordinator._validatePerformanceRewardsSubmission: startTimestamp must be a multiple of CALCULATION_INTERVAL_SECONDS"
);
require(
block.timestamp - MAX_RETROACTIVE_LENGTH <= performanceRewardsSubmission.startTimestamp &&
GENESIS_REWARDS_TIMESTAMP <= performanceRewardsSubmission.startTimestamp,
"RewardsCoordinator._validatePerformanceRewardsSubmission: startTimestamp too far in the past"
);
require(
performanceRewardsSubmission.startTimestamp + performanceRewardsSubmission.duration < block.timestamp,
"RewardsCoordinator._validatePerformanceRewardsSubmission: performance rewards submission is not retroactive"
);

// Require performanceRewardsSubmission is for whitelisted strategy or beaconChainETHStrategy
address currAddress = address(0);
for (uint256 i = 0; i < performanceRewardsSubmission.strategiesAndMultipliers.length; ++i) {
IStrategy strategy = performanceRewardsSubmission.strategiesAndMultipliers[i].strategy;
require(
strategyManager.strategyIsWhitelistedForDeposit(strategy) || strategy == beaconChainETHStrategy,
"RewardsCoordinator._validatePerformanceRewardsSubmission: invalid strategy considered"
);
require(
currAddress < address(strategy),
"RewardsCoordinator._validatePerformanceRewardsSubmission: strategies must be in ascending order to handle duplicates"
);
currAddress = address(strategy);
}

return totalAmount;
}

function _checkClaim(RewardsMerkleClaim calldata claim, DistributionRoot memory root) internal view {
require(!root.disabled, "RewardsCoordinator._checkClaim: root is disabled");
require(block.timestamp >= root.activatedAt, "RewardsCoordinator._checkClaim: root not activated yet");
Expand Down
3 changes: 1 addition & 2 deletions src/contracts/interfaces/IRewardsCoordinator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -349,8 +349,7 @@ interface IRewardsCoordinator {
* @dev The `RewardsCoordinator` contract needs a token approval of sum of all `operatorRewards` in the `performanceRewardsSubmissions`, before calling this function.
* @dev Strategies must be in ascending order of addresses to check for duplicates
* @dev Operators must be in ascending order of addresses to check for duplicates.
* @dev This function will revert if the `performanceRewardsSubmissions` is malformed,
* e.g. if the `strategies` and `weights` arrays are of non-equal lengths, or if the `operators` and `operatorRewards` arrays are of non-equal lengths
* @dev This function will revert if the `performanceRewardsSubmissions` is malformed.
*/
function createAVSPerformanceRewardsSubmission(
PerformanceRewardsSubmission[] calldata performanceRewardsSubmissions
Expand Down

0 comments on commit 3832b9d

Please sign in to comment.