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: 20/27
Findings: 1
Award: $0.00
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 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
The StakerCount
variable take hold of the count of stakers in an instance, The Natspec comfirms that the stakerCount
is not expected to be > 50, but this is not implemented in the code and there didn't seem to be restriction for that. This means there is a chance of the count to be more than 50.
The stakeCount is a list of stakers that stake in an instance and is of RollUpCore.sol
func.
What can go wrong here? well, during the cleanupOldRollup function call, the stakerCount
has been set to 50 if its > 50, remember, this is just for the loop not to be arbitrary and lead to out-Of gas
issue or something unexpected.
The problem here is that the count has now been lost to only 50 whenever there's > 50 stakerCount
, this is problematic as the number has been lost forever and this also means that some staker will be missed out when a call is made to cleanupOldRollup()
function, potentially leaving them behind without being touched
/// @dev Refund the existing stakers, pause and upgrade the current rollup to /// allow them to withdraw after pausing function cleanupOldRollup() private { IOldRollupAdmin(address(OLD_ROLLUP)).pause(); 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); } } // upgrade the rollup to one that allows validators to withdraw even whilst paused DoubleLogicUUPSUpgradeable(address(OLD_ROLLUP)).upgradeSecondaryTo(IMPL_PATCHED_OLD_ROLLUP_USER); }
Manual Review
I recommend putting the restriction in place to make sure there's not more than 50 stakers in an instance, this will ensure that no staker
is left behind during the function call.
The createNewStake function should be adjusted to something like:
function createNewStake(address stakerAddress, uint256 depositAmount, address withdrawalAddress) internal { uint64 stakerIndex = uint64(_stakerList.length); @ if (stakerIndex <= 50){ _stakerList.push(stakerAddress); _stakerMap[stakerAddress] = Staker(depositAmount, _latestConfirmed, stakerIndex, true, withdrawalAddress); } emit UserStakeUpdated(stakerAddress, withdrawalAddress, 0, depositAmount); }
This adjustment will ensure the stakers to be included in the cleanupOldRollup()
function call without leaving any behind.
Loop
#0 - c4-sponsor
2024-05-31T19:19:44Z
gzeoneth (sponsor) disputed
#1 - gzeoneth
2024-05-31T19:24:16Z
Expected behavior. https://github.com/code-423n4/2024-05-arbitrum-foundation/blob/6f861c85b281a29f04daacfe17a2099d7dad5f8f/src/rollup/BOLDUpgradeAction.sol#L345-L346
// since we for-loop these stakers we set an arbitrary limit - we dont // expect any instances to have close to this number of stakers
#2 - Picodes
2024-06-05T08:21:12Z
This is the expected behavior so this report falls within misconfiguration issues
#3 - c4-judge
2024-06-05T08:21:21Z
Picodes changed the severity to QA (Quality Assurance)
#4 - c4-judge
2024-06-08T16:43:10Z
This previously downgraded issue has been upgraded by Picodes
#5 - c4-judge
2024-06-08T16:43:24Z
Picodes changed the severity to QA (Quality Assurance)
#6 - c4-judge
2024-06-10T17:23:23Z
Picodes marked the issue as grade-b