New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
It is possible that strategy cannot be harvested and its loss fails to be reported or realized #710
Comments
trust1995 marked the issue as satisfactory |
trust1995 marked the issue as primary issue |
Duplicates #488 . Leaving up to judge how to handle. |
tess3rac7 requested judge review |
trust1995 marked the issue as duplicate of #488 |
trust1995 changed the severity to QA (Quality Assurance) |
Hi @trust1995, Unlike #488 and #124, this report identifies Moreover, this report shows that calling the Hence, I would like to ask if this report can be considered as a duplicate of #752. Thanks! |
This previously downgraded issue has been upgraded by trust1995 |
trust1995 marked the issue as not a duplicate |
trust1995 marked the issue as duplicate of #752 |
Lines of code
https://github.com/code-423n4/2023-02-ethos/blob/main/Ethos-Vault/contracts/abstract/ReaperBaseStrategyv4.sol#L109-L138
https://github.com/code-423n4/2023-02-ethos/blob/main/Ethos-Vault/contracts/ReaperStrategyGranarySupplyOnly.sol#L114-L142
https://github.com/code-423n4/2023-02-ethos/blob/main/Ethos-Vault/contracts/ReaperVaultV2.sol#L493-L560
https://github.com/code-423n4/2023-02-ethos/blob/main/Ethos-Vault/contracts/ReaperVaultV2.sol#L432-L453
Vulnerability details
Impact
When calling the
ReaperBaseStrategyv4.harvest
function, thedebt
can be positive because theavailableCapital
returned by callingIVault(vault).availableCapital()
can be negative. Then, thedebt
is used to call theReaperStrategyGranarySupplyOnly._harvestCore
function.https://github.com/code-423n4/2023-02-ethos/blob/main/Ethos-Vault/contracts/abstract/ReaperBaseStrategyv4.sol#L109-L138
When calling the
ReaperStrategyGranarySupplyOnly._harvestCore
function, iftotalAssets < allocated
is true, then theroi
is first set to-int256(allocated - totalAssets)
and is negative. TheamountFreed
andloss
returned by calling_liquidatePosition(toFree)
, wheretoFree
is the_debt
, would add up to the_debt
. Sinceloss
can be positive,roi
is further reduced by theloss
after executingroi -= int256(loss)
. However, this can cause the-_roi
to be larger than the vault's token amount that is allocated to the strategy.https://github.com/code-423n4/2023-02-ethos/blob/main/Ethos-Vault/contracts/ReaperStrategyGranarySupplyOnly.sol#L114-L142
Calling the
ReaperVaultV2.report
function then calls theReaperVaultV2._reportLoss
function because the_roi
is negative. Since theroi
was further reduced by theloss
in theReaperStrategyGranarySupplyOnly._harvestCore
function that caused the the-_roi
to be more than the vault's token amount that is allocated to the strategy, calling theReaperVaultV2._reportLoss
function would revert when executingrequire(loss <= allocation, "Strategy loss cannot be greater than allocation")
. Hence, in this situation, calling theReaperBaseStrategyv4.harvest
function for the corresponding strategy reverts in which such strategy cannot be harvested and its loss fails to be reported or realized.https://github.com/code-423n4/2023-02-ethos/blob/main/Ethos-Vault/contracts/ReaperVaultV2.sol#L493-L560
https://github.com/code-423n4/2023-02-ethos/blob/main/Ethos-Vault/contracts/ReaperVaultV2.sol#L432-L453
Proof of Concept
The following steps can occur for the described scenario.
ReaperBaseStrategyv4.harvest
function, callingIVault(vault).availableCapital()
can return -3e6 so thedebt
is set to 3e6.ReaperStrategyGranarySupplyOnly._harvestCore
function, thetotalAssets
can be 1e6, theallocated
can be 5e6, andtotalAssets < allocated
is true if the vault currently has 5e6 tokens allocated to the strategy and the current token amount controlled by the strategy is 1e6.ReaperStrategyGranarySupplyOnly._harvestCore
function, theroi
is first set to -4e6 after executingroi = -int256(allocated - totalAssets)
.ReaperStrategyGranarySupplyOnly._harvestCore
function, theamountFreed
can be 1e6 and theloss
can be 2e6 after calling_liquidatePosition(toFree)
, wheretoFree
is the_debt
that is 3e6. Then, theroi
is further reduced to -6e6 after executingroi -= int256(loss)
.ReaperVaultV2.report
function, thevars.loss
is set touint256(-_roi)
, which is 6e6.ReaperVaultV2._reportLoss
function with theloss
input being 6e6 reverts because theloss
is bigger than thestrategies[strategy].allocated
that is still 5e6.Tools Used
VSCode
Recommended Mitigation Steps
The
ReaperStrategyGranarySupplyOnly._harvestCore
function can be updated to not executeroi -= int256(loss)
for the described scenario.The text was updated successfully, but these errors were encountered: