stake.link

stake.link
DeFiHardhatBridge
27,500 USDC
View results
Submission Details
Severity: high
Invalid

The `SDLPoolCCIPControllerPrimary::distributeRewards` function does not support sending rewards tokens more than the limit allowed by `CCIP`

Summary

The function SDLPoolCCIPControllerPrimary::distributeRewards does not support sending rewards tokens more than the limit allowed by CCIP.

Vulnerability Details

The function SDLPoolCCIPControllerPrimary::distributeRewards helps to be able to send the supported token rewards to different whitelisted chains, this with the help of CCIP.ccipSend. Afterwards the secondary chains can receive the rewards.

On the other hand, CCIP has a maximum allowed number of tokens sent per message, this can be seen in the following validation maxNumberOfTokensPerMsg, that means that if in the function SDLPoolCCIPControllerPrimary::distributeRewards distributes more tokens than allowed by CCIP the distribution of rewards will be reversed, making the distribution of rewards not possible.

The function SDLPoolCCIPControllerPrimary::distributeRewards obtains the supported tokens with help of the function ISDLPoolPrimary(sdlPool).supportedTokens()), however it does not have a procedure to send multiple messages and thus not exceed the limit of tokens per message of CCIP.

File: SDLPoolCCIPControllerPrimary.sol
56: function distributeRewards() external onlyRewardsInitiator {
57: uint256 totalRESDL = ISDLPoolPrimary(sdlPool).effectiveBalanceOf(address(this));
58: address[] memory tokens = ISDLPoolPrimary(sdlPool).supportedTokens();
59: uint256 numDestinations = whitelistedChains.length;
60:
61: ISDLPoolPrimary(sdlPool).withdrawRewards(tokens);
62:
63: uint256[][] memory distributionAmounts = new uint256[][](numDestinations);
64: for (uint256 i = 0; i < numDestinations; ++i) {
65: distributionAmounts[i] = new uint256[](tokens.length);
66: }
67:
68: for (uint256 i = 0; i < tokens.length; ++i) {
69: address token = tokens[i];
70: uint256 tokenBalance = IERC20(token).balanceOf(address(this));
71:
72: address wrappedToken = wrappedRewardTokens[token];
73: if (wrappedToken != address(0)) {
74: IERC677(token).transferAndCall(wrappedToken, tokenBalance, "");
75: tokens[i] = wrappedToken;
76: tokenBalance = IERC20(wrappedToken).balanceOf(address(this));
77: }
78:
79: uint256 totalDistributed;
80: for (uint256 j = 0; j < numDestinations; ++j) {
81: uint64 chainSelector = whitelistedChains[j];
82: uint256 rewards = j == numDestinations - 1
83: ? tokenBalance - totalDistributed
84: : (tokenBalance * reSDLSupplyByChain[chainSelector]) / totalRESDL;
85: distributionAmounts[j][i] = rewards;
86: totalDistributed += rewards;
87: }
88: }
89:
90: for (uint256 i = 0; i < numDestinations; ++i) {
91: _distributeRewards(whitelistedChains[i], tokens, distributionAmounts[i]);
92: }
93: }

Impact

The distribution of rewards (SDLPoolCCIPControllerPrimary::distributeRewards) will not be executed if the number of tokens to be sent exceeds the limit allowed by CCIP. The rewards will not be distributed to the users so users will lost tokens rewards.

Tools used

Manual review

Recommendations

Modify the SDLPoolCCIPControllerPrimary::distributeRewards function to be able to send multiple messages via CCIP to the secondary chains if supported tokens exceeds the limit allowed by CCIP. So the sending of rewards tokens will be in multiple batches in order to not exceed the CCIP limit.

Updates

Lead Judging Commences

0kage Lead Judge almost 2 years ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
0xbepresent Submitter
almost 2 years ago
0kage Lead Judge
almost 2 years ago
0kage Lead Judge almost 2 years ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.