Skip to content
This repository has been archived by the owner on Oct 27, 2024. It is now read-only.

AMOW - OCE_ZVE.forwardEmissions() will forward freshly deposited balance alongside decayed one #331

Closed
sherlock-admin2 opened this issue Apr 25, 2024 · 2 comments
Labels
Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label Medium A valid Medium severity issue Reward A payout will be made for this issue

Comments

@sherlock-admin2
Copy link
Contributor

sherlock-admin2 commented Apr 25, 2024

AMOW

medium

OCE_ZVE.forwardEmissions() will forward freshly deposited balance alongside decayed one

Summary

Freshly pushed funds into OCE_ZVE.sol locker can be prematurely forwarded with currently decaying ones through forwardEmissions()

Vulnerability Detail

forwardEmissions() function catches the current ZVE balance of the OCE_ZVE locker and calls _forwardEmissions where it checks the decay rate and distributes the emissions.

    function forwardEmissions() external nonReentrant {
        uint zveBalance = IERC20(IZivoeGlobals_OCE_ZVE(GBL).ZVE()).balanceOf(address(this));
        _forwardEmissions(zveBalance - decay(zveBalance, block.timestamp - lastDistribution));
        lastDistribution = block.timestamp;
    }

If the function is called right after new funds are pushed into the locker, a portion of the fresh deposit will be immediately sent out despite not having decayed as the rest. It is profitable to wait for decay to accumulate and call the function right after new funds are pushed.

Impact

Unexpected behaviour / Unfair distribution of rewards

Code Snippet

    function forwardEmissions() external nonReentrant {
        uint zveBalance = IERC20(IZivoeGlobals_OCE_ZVE(GBL).ZVE()).balanceOf(address(this));
        _forwardEmissions(zveBalance - decay(zveBalance, block.timestamp - lastDistribution));
        lastDistribution = block.timestamp;
    }

Tool used

Manual Review

Recommendation

Implement forwardEmissions() call within pushToLocker() so lastDistribution counter will reset and start a new decay.

    function pushToLocker(address asset, uint256 amount, bytes calldata data) external override onlyOwner {
        require(
            asset == IZivoeGlobals_OCE_ZVE(GBL).ZVE(), 
            "OCE_ZVE::pushToLocker() asset != IZivoeGlobals_OCE_ZVE(GBL).ZVE()"
        );
        forwardEmissions(); // <----- add this 
        IERC20(asset).safeTransferFrom(owner(), address(this), amount);
    }

Duplicate of #282

@pseudonaut
Copy link

Not relevant, likely will call forwardEmissions prior anyways,

@github-actions github-actions bot closed this as completed May 5, 2024
@github-actions github-actions bot added Medium A valid Medium severity issue Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label labels May 5, 2024
@sherlock-admin2
Copy link
Contributor Author

1 comment(s) were left on this issue during the judging contest.

panprog commented:

medium, dup of #282. This issue describes slightly different scenario, but the core reason is the same - lack of emission reset, which makes new deposits forward some portion from previous update time, and using forwardEmission to reset it is not always possible, because it requires minimum of 100e18 token to forward.

@sherlock-admin2 sherlock-admin2 changed the title Curved Taffy Trout - OCE_ZVE.forwardEmissions() will forward freshly deposited balance alongside decayed one AMOW - OCE_ZVE.forwardEmissions() will forward freshly deposited balance alongside decayed one May 11, 2024
@sherlock-admin2 sherlock-admin2 added the Reward A payout will be made for this issue label May 11, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label Medium A valid Medium severity issue Reward A payout will be made for this issue
Projects
None yet
Development

No branches or pull requests

2 participants