mt030d - Attackers can front-run the ZivoeYDL.distributeYield() function and call returnAsset() to prevent the available yield in YDL from being distributed to the appropriate recipients #187
Attackers can front-run the ZivoeYDL.distributeYield() function and call returnAsset() to prevent the available yield in YDL from being distributed to the appropriate recipients
Summary
The ZivoeYDL.distributeYield() function distributes the current balance in the contract as yield to recipients.
Since anyone can call the ZivoeYDL.returnAsset() function to move the asset from YDL to the DAO. An attacker can front-run the distributeYield() function and call the returnAsset() function to clean the asset balance, resulting in the distributeYield() function distributing 0 yield. As a result, the recipients can not get their reward in time.
The distributeYield() function in the ZivoeYDL contract is responsible for distributing the available earnings to the yield recipients (protocol recipients, senior tranche, junior tranche, residual recipients). It uses the current balance in the contract as the available earnings to distribute.
However, there is a permissionless returnAsset() function in the ZivoeYDL contract, which can be used to transfer all the balance to the DAO.
Attackers can front-run the distributeYield() TX and call returnAsset() to set the balance in the YDL to 0, which causes the distributeYield() to distribute 0 amount of earnings to recipients.
To make matters worse, the distributeYield() call will update the lastDistribution state variable, which disables the distributeYield() for 30 days (daysBetweenDistributions) due to the above block timestamp check.
This means that if a distributeYield() call is subject to a front-running attack, the team cannot use the distributeYield() function to redistribute the yields for 30 days. In other words, without other ways to redistribute the yields, the yield recipients can not get their rightful yields in at least 30 days.
Impact
Attackers can front-run the distributeYield() with returnAsset(), causing the distributeYield() to distribute 0 amount of yield.
Since there is a 30-day interval between two distributeYield() calls, without other ways to redistribute the yields, the yield recipients cannot get their yield redistributed by distributeYield() in 30 days.
One way to mitigate the issue is to prevent the distribution of 0 earnings in distributeYield(). Another approach is to implement proper access control for the returnAsset() function.
mt030d
high
Attackers can front-run the ZivoeYDL.distributeYield() function and call returnAsset() to prevent the available yield in YDL from being distributed to the appropriate recipients
Summary
The
ZivoeYDL.distributeYield()
function distributes the current balance in the contract as yield to recipients. Since anyone can call theZivoeYDL.returnAsset()
function to move the asset from YDL to the DAO. An attacker can front-run thedistributeYield()
function and call thereturnAsset()
function to clean the asset balance, resulting in thedistributeYield()
function distributing 0 yield. As a result, the recipients can not get their reward in time.Vulnerability Detail
The
distributeYield()
function in theZivoeYDL
contract is responsible for distributing the available earnings to the yield recipients (protocol recipients, senior tranche, junior tranche, residual recipients). It uses the current balance in the contract as the available earnings to distribute.However, there is a permissionless
returnAsset()
function in theZivoeYDL
contract, which can be used to transfer all the balance to the DAO. Attackers can front-run thedistributeYield()
TX and callreturnAsset()
to set the balance in the YDL to 0, which causes the distributeYield() to distribute 0 amount of earnings to recipients.To make matters worse, the
distributeYield()
call will update thelastDistribution
state variable, which disables thedistributeYield()
for 30 days (daysBetweenDistributions
) due to the above block timestamp check. This means that if adistributeYield()
call is subject to a front-running attack, the team cannot use thedistributeYield()
function to redistribute the yields for 30 days. In other words, without other ways to redistribute the yields, the yield recipients can not get their rightful yields in at least 30 days.Impact
Attackers can front-run the
distributeYield()
withreturnAsset()
, causing thedistributeYield()
to distribute 0 amount of yield. Since there is a 30-day interval between twodistributeYield()
calls, without other ways to redistribute the yields, the yield recipients cannot get their yield redistributed bydistributeYield()
in 30 days.Code Snippet
https://github.com/sherlock-audit/2024-03-zivoe/blob/main/zivoe-core-foundry/src/ZivoeYDL.sol#L213-L310 https://github.com/sherlock-audit/2024-03-zivoe/blob/main/zivoe-core-foundry/src/ZivoeYDL.sol#L314C1-L318C6
Tool used
Manual Review
Recommendation
One way to mitigate the issue is to prevent the distribution of 0 earnings in
distributeYield()
. Another approach is to implement proper access control for the returnAsset()
function.