Open sherlock-admin2 opened 5 months ago
If pushToLockerMulti
was not called, then nothing will be forwarded.
1 comment(s) were left on this issue during the judging contest.
panprog commented:
medium, if
forwardYield
is called just after contract creation, thennextYieldDistribution
becomes incorrect andforwardYield
can be called at any time by anyone. The impact is limited, but the protocol functionality is broken (no time limit for callingforwardYield
)
Wouldn't _forwardYield()
revert due to division by 0 if basis is 0 ?
function forwardYield() external {
...
(uint256 amount, uint256 lp) = fetchBasis();
if (amount > basis) { _forwardYield(amount, lp); }
Or rather _forwardYield()
wouldn't even be called if (amount > basis) { _forwardYield(amount, lp); }
...
function _forwardYield(uint256 amount, uint256 lp) private nonReentrant {
address ZVE = IZivoeGlobals_OCL_ZVE(GBL).ZVE();
uint256 lpBurnable = (amount - basis) * lp / amount * (BIPS - compoundingRateBIPS) / BIPS;
@pseudonaut
This is correct, _forwardYield
will not be called, the point is that the last line of forwardYield
:
nextYieldDistribution += 30 days;
will make nextYieldDistribution = 30 days
, thus all future forwardYield
will ignore timestamp check because block.timestamp
will always be greater than nextYieldDistribution
.
The issue is valid, keeping it medium.
Escalate
Issues which can be mitigated by correct admin configuration upon deployment are not valid according to Sherlock rules. Issue should be low.
Escalate
Issues which can be mitigated by correct admin configuration upon deployment are not valid according to Sherlock rules. Issue should be low.
You've created a valid escalation!
To remove the escalation from consideration: Delete your comment.
You may delete or edit your escalation comment anytime before the 48-hour escalation window closes. After that, the escalation becomes final.
Escalate
Issues which can be mitigated by correct admin configuration upon deployment are not valid according to Sherlock rules. Issue should be low.
Pushing into the locker upon deployment is in no way, shape or form, correct admin configuration. That is not even a configuration.
Agree with @samuraii77 , this can only be mitigated if admin pushes into locker in the same transaction as contract creation, which doesn't seem to be reasonable assumption as this should not be part of the deployment.
The protocol team fixed this issue in the following PRs/commits: https://github.com/Zivoe/zivoe-core-foundry/pull/265
As I understand from Zivoe's Deployment diagram on Figma, they indeed will initially call push
on lockers (phase three) and only then forwardYield
(phase four). Hence, I believe this report requires an admin acting as not intended (i.e. calling forwardYield
before pushToLockerMulti
), therefore, should be invalid.
Planning to reject an escalation and leave the issue as it is.
The issue does not rely on an admin acting not as intended. The forwardYield()
function can be called by any user after the contract has been deployed which as visible by the diagram you provided happens at phase 1 and pushing happens all the way in phase 3. Basically, that means that a user has the time between phase 1 and phase 3 to just call forwardYield()
in order for the vulnerability to happen. Issue should stay valid.
Also, I am not sure if I get you correctly but it seems like you are disputing my issue and agreeing with the escalation but then proceed to say that you will reject the escalation and keep the issue as it is, not sure if I interpreted your comment wrong.
Yep, sorry for that two confusions here and I agree that indeed the locker is deployed earlier than push is called. Therefore, this issue indeed may occur.
Planning to reject the escalation and leave the issue as it is.
Result: Medium Has Duplicates
The Lead Senior Watson signed off on the fix.
samuraii77
medium
Forwarding yield in
OCL_ZVE
is possible a lot more often than the enforced 30 daysSummary
Calling
OCL_ZVE::forwardYield()
is supposed to only be possible every 30 days however in reality, it is possible to call the function a lot more often.Vulnerability Detail
The
require
statement inOCL_ZVE::forwardYield()
enforces that the function should only be callable whenblock.timestamp
is of larger value than the value ofnextYieldDistribution
Then, at the end of the function,
nextYieldDistribution
is incremented by 30 days making the function supposedly not callable for another 30 days. However, there is a vulnerability that allowsOCL_ZVE::forwardYield()
to be called a lot more times.Upon calling the
OCL_ZVE::pushToLockerMulti()
, thenextYieldDistribution
gets set toblock.timestamp + 30 days
if its value is 0.If this is the way
nextYieldDistribution
gets its first value, then there will not be an issue. However, ifOCL_ZVE::forwardYield()
is called beforehand, thennextYieldDistribution
will be set to0 += 30 days
which equals30 days
making its value a lot less than the value ofblock.timestamp
resulting in people being able to callOCL_ZVE::forwardYield()
at will all the way untilnextYieldDistribution
gets incremented all the way toblock.timestamp
.Calling
OCL_ZVE::forwardYield()
before any other function is possible and requires just 1 simple circumstance to be a fact.Imagine the following scenario:
OCL_ZVE::forwardYield()
is calledif
statement passes asblock.timestamp
is larger thannextYieldDistribution
, the value of which is the default value of 0OCL_ZVE::fetchBasis()
gets calledpairAsset
andZVE
, the vulnerability will take placepoolTotalSupply
not being 0 as division by 0 is not possiblepairAsset
andZVE
OCL_ZVE::forwardYield()
functionif(amount > basis)
does not pass as both values are 0nextYieldDistribution
gets set to30 days
making theOCL_ZVE::forwardYield()
function callable again and againImpact
OCL_ZVE::forwardYield()
is callable over and over again even though it is only supposed to be called every 30 daysProof Of Concept
Paste the following test into
Test_OCL_ZVE.sol
:Code Snippet
https://github.com/sherlock-audit/2024-03-zivoe/blob/d4111645b19a1ad3ccc899bea073b6f19be04ccd/zivoe-core-foundry/src/lockers/OCL/OCL_ZVE.sol#L186 https://github.com/sherlock-audit/2024-03-zivoe/blob/d4111645b19a1ad3ccc899bea073b6f19be04ccd/zivoe-core-foundry/src/lockers/OCL/OCL_ZVE.sol#L287-L305
Tool used
Manual Review
Recommendation
Do not allow
OCL_ZVE::forwardYield()
to be called whenever the value ofnextYieldDistribution
is equal to 0. Also, another option is to setnextYieldDistribution
toblock.timestamp + 30 days
instead of just incrementing it by30 days
.