BAICE - Different `stakingRewards` contract address by using a same index id, `StakingRewardsManager:removeStakingRewardsContract` will cause the index ->address map to be out of order #207
Different stakingRewards contract address by using a same index id, StakingRewardsManager:removeStakingRewardsContract will cause the index ->address map to be out of order
Summary
Both StakingRewardsFactory and StakingRewardsManager contract use index to getStakingRewardsContract.
But when call removeStakingRewardsContract in StakingRewardsManager , the index of the two contracts will dismatch .
Vulnerability Detail
The BUILDER_ROLE, create new stakingReward contract by calling stakingRewardsFactory.createStakingRewards method, and then , both contracts pull new stakingRewardcontract to a StakingRewards[] array .
StakingRewardsFactory.sol
StakingRewards[] public stakingRewardsContracts;
···
// add contract to list
stakingRewardsContracts.push(stakingRewards);
StakingRewardsManager.sol
/// @dev Array of managed StakingRewards contracts
StakingRewards[] public stakingContracts;
// push staking onto stakingContracts array
stakingContracts.push(staking);
but if we call StakingRewardsManager:removeStakingRewardsContract, the specified index in StakingRewardsManager:stakingContracts will be poped , and the order by index will dismatch .
function removeStakingRewardsContract(
uint256 i
) external onlyRole(BUILDER_ROLE) {
StakingRewards staking = stakingContracts[i];
// un-mark this staking contract as included in stakingContracts
stakingExists[staking] = false;
// replace the removed staking contract with the last item in the stakingContracts array
stakingContracts[i] = stakingContracts[stakingContracts.length - 1];
// pop the last staking contract off the array
stakingContracts.pop();
emit StakingRemoved(staking);
}
function getStakingContract(
uint256 i
) external view returns (StakingRewards) {
return stakingContracts[i];
}
Tool used
Manual Review
Recommendation
Change StakingRewardsManager:stakingContracts index -> stakingReward contract address to zero address when calling removeStakingRewardsContract
@- stakingContracts[i] = stakingContracts[stakingContracts.length - 1];
// pop the last staking contract off the array
@- stakingContracts.pop();
@+ stakingContracts[i] = StakingRewards(0x0000000000000000000000000000000000000000);
BAICE
high
Different
stakingRewards
contract address by using a same index id,StakingRewardsManager:removeStakingRewardsContract
will cause the index ->address map to be out of orderSummary
Both
StakingRewardsFactory
andStakingRewardsManager
contract use index togetStakingRewardsContract
. But when callremoveStakingRewardsContract
inStakingRewardsManager
, the index of the two contracts will dismatch .Vulnerability Detail
The
BUILDER_ROLE
, create new stakingReward contract by callingstakingRewardsFactory.createStakingRewards
method, and then , both contracts pull newstakingReward
contract to aStakingRewards[]
array .StakingRewardsFactory.sol
StakingRewardsManager.sol
but if we call
StakingRewardsManager:removeStakingRewardsContract
, the specified index inStakingRewardsManager:stakingContracts
will be poped , and the order by index will dismatch .ForExample
before remove
after remove 0x3 address
add a new stakingReward contract
Impact
Unmatched array elements by same index .
Code Snippet
https://github.com/sherlock-audit/2024-01-telcoin/blob/main/telcoin-audit/contracts/telx/core/StakingRewardsFactory.sol#L73-L77
remove one element https://github.com/sherlock-audit/2024-01-telcoin/blob/main/telcoin-audit/contracts/telx/core/StakingRewardsManager.sol#L166-L179
Get staking contract address in
StakingRewardsManager
https://github.com/sherlock-audit/2024-01-telcoin/blob/main/telcoin-audit/contracts/telx/core/StakingRewardsManager.sol#L92C3-L98C1Tool used
Manual Review
Recommendation
Change
StakingRewardsManager:stakingContracts
index -> stakingReward contract address to zero address when callingremoveStakingRewardsContract
Duplicate of #104