Open c4-bot-7 opened 8 months ago
Picodes marked the issue as primary issue
othernet-global (sponsor) disputed
This is acceptable behavior.
Downgrading to Low as this is concerns at most dusts amounts.
Picodes changed the severity to QA (Quality Assurance)
Lines of code
https://github.com/code-423n4/2024-01-salty/blob/53516c2cdfdfacb662cdea6417c52f23c94d5b5b/src/Upkeep.sol#L200
Vulnerability details
Impact
In some conditions, some pools can lose their arbitrage profits during upkeep to other pools. And small losses will reoccur and accumulate over time.
Proof of Concept
performUpkeep()
is permissionless and users are incentivized to callperformUpkeep()
at any time.A) In normal conditions, arbitrage profits will be withdrawn to Upkeep.sol in step2. In later steps, arbitrage profits can be combined with emission salt rewards(step6) to be distributed to whitelisted pools that contributed to arbitrage(step7). Then pools' arbitrage profits will be cleared (
pools.clearProfitsForPools()
).(https://github.com/code-423n4/2024-01-salty/blob/53516c2cdfdfacb662cdea6417c52f23c94d5b5b/src/Upkeep.sol#L200)
B) But in some conditions, (1) there might be no emission salt rewards in step6 if
performUpkeep()
is called in the same block as the previous upkeep call (timeSinceLastUpkeep
==0); (2) And in step2, arbitrage profits might fail to be withdrawn to Upkeep.sol due to dust amount transfer causing reverts, even though there are arbitrage profits.The combination of (1) & (2) will cause pools' arbitrage profits records(
mapping(bytes32 => uint256) public _arbitrageProfits
) to be cleared without receiving rewards. Pools' rewards will be lost.When Dao's arbitrage profits accumulate later and are distributed, the previously lost small amount might be distributed to different pools that didn't earn the profits from previous upkeeps.
Suppose that many users/bots call
performUpkeep()
regularly, and when these upkeep transactions settle close to each other, or if arbitrage profits gain is slow due to low trading activities, the above scenario can happen and re-occur.Tools Used
Manual
Recommended Mitigation Steps
In
step7()
, (1) consider letsaltRewards.performUpkeep(poolIDs, profitsForPools);
return 0 when no balance to distribute; (2) Only callpools.clearProfitsForPools()
when non-zero is returned from saltRewards.performUpkeep.Assessed type
Other