This repository has been archived by the owner on Jan 12, 2025. It is now read-only.
bbl4de - createPosition()
and addToPosition()
are callable even in case of emergency, decreasing rewards for users
#131
Labels
Non-Reward
This issue will not receive a payout
bbl4de
Medium
createPosition()
andaddToPosition()
are callable even in case of emergency, decreasing rewards for usersSummary
Any user can create MLUM staking position with
createPosition()
during emergency and add more funds to it withaddToPosition()
, assuming thelockDuration
is set to 0 - and therefore the multiplier is 0.Vulnerability Detail
Creation of new positions should not be allowed during an emergency according to the following comment in
createPosition()
function:Unfortunately, the check in the code snippet above still allows locks with duration set to 0. This kind of call will not fail, as according to the sponsor, creation of locks with
lockDuration == 0
is an intended functionality - it simply creates a staking position with no multiplier as ingetMultiplierByLockDuration()
:However, in case of an emergency ANY call to
createPosition()
ANDaddToPosition()
must be reverted.Impact
Creating a position during emergency would decrease the rewards that other users are eligible for. As the users are allowed to choose to withdraw their funds during emergency with
withdrawFromPosition()
, rather thanemergencyWithdraw()
. Any user withdrawing their funds without the rewards - throughemergencyWithdraw()
would incentivize the malicious user to calladdToPosition()
and increase their stake to gain more rewards when they finally withdraw they stake. Note that the malicious user can withdraw their funds at any time, because theirlockDuration
was set to 0.Proof of Code
A test file that is deploying locally all the required contracts from the codebase was created to provide proof of codes for MagicSea audit. In the ./magicsea-staking/test directory create a PoC.t.sol test file and paste into it the code from this gist. For the code to compile the name of the ERC20Mock contract in ./src/mocks/ERC20Mock.sol needs to be changed to ERC20MockWithRoles. Then, run:
forge test --mt test_createPosition_and_addToPosition_callable_during_emergency
For simplicity of the test the rewards where not included, but it is verified that the position is created successfully and
_stakedSupplyWithMultiplier
is increased. We can see in_updatePool()
function ( called before any reward harvesting ) that_accRewardsPerShare
is updated based on_stakedSupplyWithMultiplier
:Therefore, rewards distribution would be indeed affected.
Code Snippet
https://github.com/sherlock-audit/2024-06-magicsea/blob/42e799446595c542eff9519353d3becc50cdba63/magicsea-staking/src/MlumStaking.sol#L356
Tool used
Manual Review
Recommendation
The essential part of the mitigation is locking the
createPosition()
andaddToPosition()
functions completely if the contract is in emergency by adding the following check:similarily to the
_lockPosition()
function where it's implemented correctly.Although it does not present an attack vector in itself, allowing staking positions with
lockDuration
set to 0 should be reconsidered due to its questionable fairness and lack of risk for stakers who choose this option ( no lock on their funds ).The text was updated successfully, but these errors were encountered: