Vulnerability: Tokens that are both bribes and StakeDao gauge rewards will cause loss of funds
Severity: high

Description:
When SdtStakingPositionService is pulling rewards and bribes from buffer, the buffer will return a list of tokens and amounts owed. This list is used to set the rewards eligible for distribution. Since this list is never check for duplicate tokens, a shared bribe and reward token would cause the token to show up twice in the list. The issue it that _sdtRewardsByCycle is set and not incremented which will cause the second occurrence of the token to overwrite the first and break accounting. The amount of token received from the gauge reward that is overwritten will be lost forever.\\nIn L559 of SdtStakingPositionService it receives a list of tokens and amount from the buffer.\\nSdtBuffer.sol#L90-L168\\n```\\n    ICommonStruct.TokenAmount[] memory bribeTokens = _sdtBlackHole.pullSdStakingBribes(\\n        processor,\\n        _processorRewardsPercentage\\n    );\\n\\n    uint256 rewardAmount = _gaugeAsset.reward_count();\\n\\n    ICommonStruct.TokenAmount[] memory tokenAmounts = new ICommonStruct.TokenAmount[](\\n        rewardAmount + bribeTokens.length\\n    );\\n\\n    uint256 counter;\\n    address _processor = processor;\\n    for (uint256 j; j < rewardAmount; ) {\\n        IERC20 token = _gaugeAsset.reward_tokens(j);\\n        uint256 balance = token.balanceOf(address(this));\\n        if (balance != 0) {\\n            uint256 fullBalance = balance;\\n\\n            // rest of code\\n\\n            token.transfer(sdtRewardsReceiver, balance);\\n\\n          **@audit token and amount added from reward_tokens pulled directly from gauge**\\n\\n            tokenAmounts[counter++] = ICommonStruct.TokenAmount({token: token, amount: balance});\\n        }\\n\\n        // rest of code\\n\\n    }\\n\\n    for (uint256 j; j < bribeTokens.length; ) {\\n        IERC20 token = bribeTokens[j].token;\\n        uint256 amount = bribeTokens[j].amount;\\n\\n      **@audit token and amount added directly with no check for duplicate token**\\n\\n        if (amount != 0) {\\n            tokenAmounts[counter++] = ICommonStruct.TokenAmount({token: token, amount: amount});\\n\\n        // rest of code\\n\\n    }\\n```\\n\\nSdtBuffer#pullRewards returns a list of tokens that is a concatenated array of all bribe and reward tokens. There is not controls in place to remove duplicates from this list of tokens. This means that tokens that are both bribes and rewards will be duplicated in the list.\\nSdtStakingPositionService.sol#L561-L577\\n```\\n    for (uint256 i; i < _rewardAssets.length; ) {\\n        IERC20 _token = _rewardAssets[i].token;\\n        uint256 erc20Id = _tokenToId[_token];\\n        if (erc20Id == 0) {\\n            uint256 _numberOfSdtRewards = ++numberOfSdtRewards;\\n            _tokenToId[_token] = _numberOfSdtRewards;\\n            erc20Id = _numberOfSdtRewards;\\n        }\\n\\n      **@audit overwrites and doesn't increment causing duplicates to be lost**            \\n\\n        _sdtRewardsByCycle[_cvgStakingCycle][erc20Id] = ICommonStruct.TokenAmount({\\n            token: _token,\\n            amount: _rewardAssets[i].amount\\n        });\\n        unchecked {\\n            ++i;\\n        }\\n    }\\n```\\n\\nWhen storing this list of rewards, it overwrites _sdtRewardsByCycle with the values from the returned array. This is where the problem arises because duplicates will cause the second entry to overwrite the first entry. Since the first instance is overwritten, all funds in the first occurrence will be lost permanently.

Impact:
Tokens that are both bribes and rewards will be cause tokens to be lost forever

Recommended mitigation:
Either sdtBuffer or SdtStakingPositionService should be updated to combine duplicate token entries and prevent overwriting.