Revoking Vesting Will Trigger a Taxable Event
Resolution\\nFixed as of commit `f4299cdba5e863c9ca2d69a3a7dd554ac34af292`.\\nFrom the previous conversations with the Hedgey team, we identified that users should be in control of when taxable events happen. For that reason, one could redeem a plan in the past. Unfortunately, the recipient of the vesting plan can not always be in control of the redemption process. If for one reason or another the administrator of the vesting plan decides to revoke it, any vested funds will be sent to the vesting plan holder, triggering the taxable event and burning the NFT.\\n```\\nfunction \\_revokePlan(address vestingAdmin, uint256 planId) internal {\\n Plan memory plan = plans[planId];\\n require(vestingAdmin == plan.vestingAdmin, '!vestingAdmin');\\n (uint256 balance, uint256 remainder, ) = planBalanceOf(planId, block.timestamp, block.timestamp);\\n require(remainder > 0, '!Remainder');\\n address holder = ownerOf(planId);\\n delete plans[planId];\\n \\_burn(planId);\\n TransferHelper.withdrawTokens(plan.token, vestingAdmin, remainder);\\n TransferHelper.withdrawTokens(plan.token, holder, balance);\\n emit PlanRevoked(planId, balance, remainder);\\n}\\n```\\n\\n```\\nfunction \\_revokePlan(address vestingAdmin, uint256 planId) internal {\\n Plan memory plan = plans[planId];\\n require(vestingAdmin == plan.vestingAdmin, '!vestingAdmin');\\n (uint256 balance, uint256 remainder, ) = planBalanceOf(planId, block.timestamp, block.timestamp);\\n require(remainder > 0, '!Remainder');\\n address holder = ownerOf(planId);\\n delete plans[planId];\\n \\_burn(planId);\\n address vault = votingVaults[planId];\\n if (vault == address(0)) {\\n TransferHelper.withdrawTokens(plan.token, vestingAdmin, remainder);\\n TransferHelper.withdrawTokens(plan.token, holder, balance);\\n } else {\\n delete votingVaults[planId];\\n VotingVault(vault).withdrawTokens(vestingAdmin, remainder);\\n VotingVault(vault).withdrawTokens(holder, balance);\\n }\\n emit PlanRevoked(planId, balance, remainder);\\n}\\n```\\n
One potential workaround is to only withdraw the unvested portion to the vesting admin while keeping the vested part in the contract. That being said `amount` and `rate` variables would need to be updated in order not to allow any additional vesting for the given plan. This way plan holders will not be entitled to more funds but will be able to redeem them at the time they choose.
```\\nfunction \\_revokePlan(address vestingAdmin, uint256 planId) internal {\\n Plan memory plan = plans[planId];\\n require(vestingAdmin == plan.vestingAdmin, '!vestingAdmin');\\n (uint256 balance, uint256 remainder, ) = planBalanceOf(planId, block.timestamp, block.timestamp);\\n require(remainder > 0, '!Remainder');\\n address holder = ownerOf(planId);\\n delete plans[planId];\\n \\_burn(planId);\\n TransferHelper.withdrawTokens(plan.token, vestingAdmin, remainder);\\n TransferHelper.withdrawTokens(plan.token, holder, balance);\\n emit PlanRevoked(planId, balance, remainder);\\n}\\n```\\n