Platform: Code4rena
Start Date: 10/05/2024
Pot Size: $300,500 USDC
Total HM: 4
Participants: 27
Period: 17 days
Judge: Picodes
Total Solo HM: 1
Id: 375
League: ETH
Rank: 10/27
Findings: 2
Award: $5,993.97
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: SpicyMeatball
Also found by: dontonka, josephdara
5993.9737 USDC - $5,993.97
cleanupOldRollup()
gets the stakerCount from the oldRollup, then loops over that number if they are less than 50 or 50 addresses if they are over 50 stakers.
Rollup.stakerCount()
gets the number of stakerRollup.getStakerAddress()
gets the staker address from the _stakerList
arrayRollup.forceRefundStaker()
makes the staker's stake withdrawable and then deletes the stakerHowever, by deleting a staker, the array is being reduced from the right while the by incrementing the loop, we are skipping addresses from the left.
for (uint64 i = 0; i < stakerCount; i++) { address stakerAddr = ROLLUP_READER.getStakerAddress(i); OldStaker memory staker = ROLLUP_READER.getStaker(stakerAddr); if (staker.isStaked && staker.currentChallenge == 0) { address[] memory stakersToRefund = new address[](1); stakersToRefund[0] = stakerAddr; IOldRollupAdmin(address(OLD_ROLLUP)).forceRefundStaker(stakersToRefund); }
By increaasing the index i, and getting the next staker address, the loop will run out of bounds since the array is being reduced in the OLD_ROLLUP
contract.
This is not an issue with the old rollup, but with the loop depicted above.
MANUAL REVIEW, Josephdara
Always get the first address in the loop, only change that if the currentChallenge for the first address is not zero.
uint64 j; for (uint64 i = 0; i < stakerCount; i++) { address stakerAddr = ROLLUP_READER.getStakerAddress(j); OldStaker memory staker = ROLLUP_READER.getStaker(stakerAddr); if (staker.isStaked && staker.currentChallenge == 0) { address[] memory stakersToRefund = new address[](1); stakersToRefund[0] = stakerAddr; IOldRollupAdmin(address(OLD_ROLLUP)).forceRefundStaker(stakersToRefund); }else{ j++; } }
Error
#0 - c4-judge
2024-06-05T08:21:20Z
Picodes changed the severity to QA (Quality Assurance)
#1 - Josephdara
2024-06-05T21:33:57Z
Hi @Picodes Thanks for the judging. I believe this bug has been grouped wrongly. It is a duplicate of issues #5 Please review.
#2 - c4-judge
2024-06-08T16:43:12Z
This previously downgraded issue has been upgraded by Picodes
#3 - c4-judge
2024-06-08T16:43:15Z
Picodes marked the issue as not a duplicate
#4 - c4-judge
2024-06-08T16:43:36Z
Picodes marked the issue as satisfactory
#5 - c4-judge
2024-06-08T16:43:43Z
Picodes marked the issue as duplicate of #5
🌟 Selected for report: Sathish9098
Also found by: Audinarey, Dup1337, K42, KupiaSec, LessDupes, Rhaydden, SpicyMeatball, Takarez, ZanyBonzy, bronze_pickaxe, carlitox477, dontonka, forgebyola, fyamf, guhu95, hihen, josephdara, ladboy233, slvDev, twcctop, xuwinnie, zanderbyte
0 USDC - $0.00
Although it is stated that not more than 50 stakers are expected, this remains a projection. Therefore if there exists more than 50 stakers, these stakers would be stuck on the older rollup.
Their funds would also be permanently stuck on the old rollup contract.
uint64 stakerCount = ROLLUP_READER.stakerCount(); // since we for-loop these stakers we set an arbitrary limit - we dont // expect any instances to have close to this number of stakers if (stakerCount > 50) { stakerCount = 50; } for (uint64 i = 0; i < stakerCount; i++) { address stakerAddr = ROLLUP_READER.getStakerAddress(i); OldStaker memory staker = ROLLUP_READER.getStaker(stakerAddr); if (staker.isStaked && staker.currentChallenge == 0) { address[] memory stakersToRefund = new address[](1); stakersToRefund[0] = stakerAddr; IOldRollupAdmin(address(OLD_ROLLUP)).forceRefundStaker(stakersToRefund); } }
Manual Review, Josephdara
Implement a function to complete refunds, or transfer the ownership of the old rollup contract to a new address after upgrade to allow for manual forceRefund calls.
Other
#0 - c4-judge
2024-06-05T08:21:20Z
Picodes changed the severity to QA (Quality Assurance)
#1 - c4-judge
2024-06-08T16:43:10Z
This previously downgraded issue has been upgraded by Picodes
#2 - c4-judge
2024-06-08T16:43:23Z
Picodes changed the severity to QA (Quality Assurance)
#3 - c4-judge
2024-06-10T17:23:44Z
Picodes marked the issue as grade-b