Vulnerability: `cancelVesting` will potentially not give users unclaimed, vested funds, even if giveUnclaimed = true
Severity: high

Description:
The purpose of `cancelVesting` is to cancel a vesting grant and potentially give users unclaimed but vested funds in the event that `giveUnclaimed = true`. However, due to a bug, in the event that the user had staked / locked funds, they will potentially not received the unclaimed / vested funds even if `giveUnclaimed = true`.\\nHere's the cancelVesting function in TrufVesting:\\n```\\nfunction cancelVesting(uint256 categoryId, uint256 vestingId, address user, bool giveUnclaimed)\\n        external\\n        onlyOwner\\n{\\n        UserVesting memory userVesting = userVestings[categoryId][vestingId][user];\\n\\n        if (userVesting.amount == 0) {\\n            revert UserVestingDoesNotExists(categoryId, vestingId, user);\\n        }\\n\\n        if (userVesting.startTime + vestingInfos[categoryId][vestingId].period <= block.timestamp) {\\n            revert AlreadyVested(categoryId, vestingId, user);\\n        }\\n\\n        uint256 lockupId = lockupIds[categoryId][vestingId][user];\\n\\n        if (lockupId != 0) {\\n            veTRUF.unstakeVesting(user, lockupId - 1, true);\\n            delete lockupIds[categoryId][vestingId][user];\\n            userVesting.locked = 0;\\n        }\\n\\n        VestingCategory storage category = categories[categoryId];\\n\\n        uint256 claimableAmount = claimable(categoryId, vestingId, user);\\n        if (giveUnclaimed && claimableAmount != 0) {\\n            trufToken.safeTransfer(user, claimableAmount);\\n\\n            userVesting.claimed += claimableAmount;\\n            category.totalClaimed += claimableAmount;\\n            emit Claimed(categoryId, vestingId, user, claimableAmount);\\n        }\\n\\n        uint256 unvested = userVesting.amount - userVesting.claimed;\\n\\n        delete userVestings[categoryId][vestingId][user];\\n\\n        category.allocated -= unvested;\\n\\n        emit CancelVesting(categoryId, vestingId, user, giveUnclaimed);\\n}\\n```\\n\\nFirst, consider the following code:\\n```\\nuint256 lockupId = lockupIds[categoryId][vestingId][user];\\n\\nif (lockupId != 0) {\\n            veTRUF.unstakeVesting(user, lockupId - 1, true);\\n            delete lockupIds[categoryId][vestingId][user];\\n            userVesting.locked = 0;\\n}\\n```\\n\\nFirst the locked / staked funds will essentially be un-staked. The following line of code: `userVesting.locked = 0;` exists because there is a call to `uint256 claimableAmount = claimable(categoryId, vestingId, user);` afterwards, and in the event that there were locked funds that were unstaked, these funds should now potentially be `claimable` if they are vested (but if locked is not set to 0, then the vested funds will potentially not be deemed `claimable` by the `claimable` function).\\nHowever, because `userVesting` is `memory` rather than `storage`, this doesn't end up happening (so `userVesting.locked = 0;` is actually a bug). This means that if a user is currently staking all their funds (so all their funds are locked), and `cancelVesting` is called, then they will not receive any funds back even if `giveUnclaimed = true`. This is because the `claimable` function (which will access the unaltered userVestings[categoryId][vestingId][user]) will still think that all the funds are currently locked, even though they are not as they have been forcibly unstaked.

Impact:
When `cancelVesting` is called, a user may not receive their unclaimed, vested funds.

Recommended mitigation:
Change `userVesting.locked = 0;` to `userVestings[categoryId][vestingId][user].locked = 0;`