`Staking.unstake()` doesn't decrease the original voting power that was used in `Staking.stake()`.
`Staking.unstake()` doesn't decrease the original voting power that was used in `Staking.stake()`.\\nWhen users stake/unstake the underlying NFTs, it calculates the token voting power using getTokenVotingPower() and increases/decreases their voting power accordingly.\\n```\\n    function getTokenVotingPower(uint _tokenId) public override view returns (uint) {\\n      if (ownerOf(_tokenId) == address(0)) revert NonExistentToken();\\n\\n      // If tokenId < 10000, it's a FrankenPunk, so 100/100 = a multiplier of 1\\n      uint multiplier = _tokenId < 10_000 ? PERCENT : monsterMultiplier;\\n      \\n      // evilBonus will return 0 for all FrankenMonsters, as they are not eligible for the evil bonus\\n      return ((baseVotes * multiplier) / PERCENT) + stakedTimeBonus[_tokenId] + evilBonus(_tokenId);\\n    }\\n```\\n\\nBut `getTokenVotingPower()` uses some parameters like `monsterMultiplier` and `baseVotes` and the output would be changed for the same `tokenId` after the admin changed these settings.\\nCurrently, `_stake()` and `_unstake()` calculates the token voting power independently and the below scenario would be possible.\\nAt the first time, `baseVotes = 20, monsterMultiplier = 50`.\\nA user staked a `FrankenMonsters` and his voting power = 10 here.\\nAfter that, the admin changed `monsterMultiplier = 60`.\\nWhen a user tries to unstake the NFT, the token voting power will be `20 * 60 / 100 = 12` here.\\nSo it will revert with uint underflow here.\\nAfter all, he can't unstake the NFT.
I think we should add a mapping like `tokenVotingPower` to save an original token voting power when users stake the token and decrease the same amount when they unstake.
`votesFromOwnedTokens` might be updated wrongly or users can't unstake for the worst case because it doesn't decrease the same token voting power while unstaking.
```\\n    function getTokenVotingPower(uint _tokenId) public override view returns (uint) {\\n      if (ownerOf(_tokenId) == address(0)) revert NonExistentToken();\\n\\n      // If tokenId < 10000, it's a FrankenPunk, so 100/100 = a multiplier of 1\\n      uint multiplier = _tokenId < 10_000 ? PERCENT : monsterMultiplier;\\n      \\n      // evilBonus will return 0 for all FrankenMonsters, as they are not eligible for the evil bonus\\n      return ((baseVotes * multiplier) / PERCENT) + stakedTimeBonus[_tokenId] + evilBonus(_tokenId);\\n    }\\n```\\n