Assessment reports>Metavest>High findings>Incorrect calculation in ,terminate, function
Category: Business Logic

Incorrect calculation in terminate function

High Severity
High Impact
High Likelihood

Description

In the function terminate in the VestingAllocation contract, the tokensToRecover is used to calculate the remaining tokens, excluding the tokens vested and withdrawn.

However, the getVestedTokenAmount() function returns the total vested tokens, so adding tokensWithdrawn is unnecessary. It allows the controller to recover more tokens than those remaining, causing the transaction to revert due to integer underflow.

function terminate() external override onlyController nonReentrant {
    if(terminated) revert MetaVesT_AlreadyTerminated();
    uint256 tokensToRecover = 0;
    uint256 milestonesAllocation = 0;
    for (uint256 i; i < milestones.length; ++i) {
            milestonesAllocation += milestones[i].milestoneAward;
    }
    tokensToRecover = allocation.tokenStreamTotal + milestonesAllocation - getVestedTokenAmount() + tokensWithdrawn;
    terminationTime = block.timestamp;
    safeTransfer(allocation.tokenContract, getAuthority(), tokensToRecover);
    terminated = true;
    emit MetaVesT_Terminated(grantee, tokensToRecover);
}

Similarly, in the function terminate in the TokenOptionAllocation contract, the tokensToRecover is used to calculate the remaining tokens, excluding the tokens exercisable and exercised. For the same reason, adding tokensWithdrawn is unnecessary.

function terminate() external override onlyController nonReentrant {
    if(terminated) revert MetaVesT_AlreadyTerminated();
    
    uint256 milestonesAllocation = 0;
    for (uint256 i; i < milestones.length; ++i) {
            milestonesAllocation += milestones[i].milestoneAward;
    }
    uint256 tokensToRecover = allocation.tokenStreamTotal + milestonesAllocation - getAmountExercisable() - tokensExercised + tokensWithdrawn;
    terminationTime = block.timestamp;
    shortStopTime = block.timestamp + shortStopDuration;
    safeTransfer(allocation.tokenContract, getAuthority(), tokensToRecover);
    terminated = true;
    emit MetaVesT_Terminated(grantee, tokensToRecover);
}

Impact

The controller cannot terminate the allocation contract and recover the remaining tokens.

Recommendations

Remove the tokensWithdrawn from the calculation of the remaining tokens in the terminate function.

Remediation

This issue has been acknowledged by MetaLeX Labs, Inc, and a fix was implemented in commit 033ab663.

Zellic © 2024Back to top ↑