hats-finance / Convergence---Convex-integration-0xb3df23e155b74ad2b93777f58980d6727e8b40bb

0 stars 1 forks source link

`CvxConvergenceLocker.mint()` will revert when lock amount is zero #38

Open hats-bug-reporter[bot] opened 5 months ago

hats-bug-reporter[bot] commented 5 months ago

Github username: @0xRizwan Twitter username: 0xRizwann Submission hash (on-chain): 0xad2d6fbb7b898a977cff04d6adefb0a1af5cdeb9b32a8b0dba2fbaee93060f9e Severity: low

Description: Description\

CvxConvergenceLocker.mint()function allows to mint cvgCVX tokens by transferrig the same amount in CVX tokens. mint() permits user to lock CVX by simply by passing isLock argument as true or false.

    function mint(address account, uint256 amount, bool isLock) external {
        if (!isLock) {
            /// @dev Compute fees when not choosing to lock
            uint256 feesAmount = (amount * mintFees) / 10_000;
            amount -= feesAmount;

            /// @dev Take fees for relocking
            CVX.transferFrom(msg.sender, cvgControlTower.treasuryPod(), feesAmount);
        }

        /// @dev Transfer CVX from user to this contract
        CVX.transferFrom(msg.sender, address(this), amount);

        /// @dev Update CVX lock data
        cvxToLock += amount;
        if (isLock) {
            lockCvx();          @audit // would revert if lock amount is zero
        }

        _mint(account, amount);
    }

Consider if the CVX is supposed to be locked. since lockCvx() is a public function which allows anyone to call it. lockCvx()basically locks all balance of CVX received during the conversion of cvgCVX in vlCVX contract.

In between the mint()if the user has set true to isLock to lock the CVX and at the same time or in between the function processing, some random user calls lockCvc() then cvxToLock will be 0.

    function lockCvx() public {
@>      CVX_LOCKER.lock(address(this), cvxToLock, 0);
        cvxToLock = 0;
    }

When the cvxToLock will be 0 then CVX_LOCKER.lock(address(this), cvxToLock, 0) will revert.

Lets check, CVX_LOCKER.lock() at address 0x72a19342e8F1838460eBFCCEf09F6585e32db86E

    // Locked tokens cannot be withdrawn for lockDuration and are eligible to receive stakingReward rewards
    function lock(address _account, uint256 _amount, uint256 _spendRatio) external nonReentrant updateReward(_account) {

        //pull tokens
        stakingToken.safeTransferFrom(msg.sender, address(this), _amount);

        //lock
@>      _lock(_account, _amount, _spendRatio, false);
    }

    //lock tokens
    function _lock(address _account, uint256 _amount, uint256 _spendRatio, bool _isRelock) internal {
@>      require(_amount > 0, "Cannot stake 0");
        require(_spendRatio <= maximumBoostPayment, "over max spend");
        require(!isShutdown, "shutdown");

       . . . some code

      }

It can be seen, the lock function will revert when the amount will be 0 and it will revert with error Cannot stake 0.

This will make whole CvxConvergenceLocker.mint() revert and user wont be able to lock CVX by an argument set to true in mint() function.

Recommendation to fix\ Consider below changes:

    function mint(address account, uint256 amount, bool isLock) external {
        if (!isLock) {
            /// @dev Compute fees when not choosing to lock
            uint256 feesAmount = (amount * mintFees) / 10_000;
            amount -= feesAmount;

            /// @dev Take fees for relocking
            CVX.transferFrom(msg.sender, cvgControlTower.treasuryPod(), feesAmount);
        }

        /// @dev Transfer CVX from user to this contract
        CVX.transferFrom(msg.sender, address(this), amount);

        /// @dev Update CVX lock data
        cvxToLock += amount;
        if (isLock) {
+               if(cvxToLock != 0) {
                      lockCvx();
+               }
        }

        _mint(account, amount);
    }
kakarottosama commented 4 months ago

I think you overlooked this part of code

        CVX.transferFrom(msg.sender, address(this), amount);

        /// @dev Update CVX lock data
        cvxToLock += amount;