68970 sc insight insufficient event emission in migratepositionsfrom leads to loss of migration accounting visibility
Description
Brief/Intro
function migratePositionsFrom(address user)
external
nonReentrant
onlyRole(MIGRATOR_ROLE)
returns (UserStake[] memory)
{
if (!migrationPermits[msg.sender][user]) revert MigratorNotPermitted(msg.sender, user);
UserStake[] memory stakes = userStakes[user];
uint256 stakesToMigrateCount;
// Count migratedStakes array size
for (uint256 i = 0; i < stakes.length; i++) {
if (stakes[i].claimedAmount + stakes[i].claimedReward < stakes[i].amount + stakes[i].reward) {
stakesToMigrateCount++;
}
}
UserStake[] memory migratedStakes = new UserStake[](stakesToMigrateCount);
delete userStakes[user];
uint256 migratedCount;
uint256 unclaimedUserAmount;
uint256 unclaimedUserRewards;
for (uint256 i = 0; i < stakes.length; i++) {
if (stakes[i].claimedAmount + stakes[i].claimedReward >= stakes[i].amount + stakes[i].reward) {
userStakes[user].push(stakes[i]);
continue;
}
unclaimedUserAmount += stakes[i].amount - stakes[i].claimedAmount;
unclaimedUserRewards += stakes[i].reward - stakes[i].claimedReward;
migratedStakes[migratedCount] = stakes[i];
migratedCount++;
}
// The capUsed is intentionally not decremented for migrated positions. Migration is a terminal operation:
// the manager will deactivate all staking periods or pauser will pause the contract before migration begins
activeTotalStaked -= unclaimedUserAmount;
activeTotalRewards -= unclaimedUserRewards;
TOKEN.safeTransfer(msg.sender, unclaimedUserAmount + unclaimedUserRewards);
emit MigrateFrom(msg.sender, user);
return migratedStakes;
}Vulnerability Details
Impact Details
References
Mitigation
Proof of Concept
Previous69188 sc low setmigrationpermit revoke blocked after migrator role revocationNext69605 sc low users cannot revoke migration authorization after role revocation contrary to documented behavior
Was this helpful?