wrong accRewardsPerShare[][] calculation and fund loss if user call claim() multiple times for expired bond in Lock and BondNFT because of multiple calculation of _pendingDelta
Audit: 2022-12-tigris-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2022-12-tigris/blob/588c84b7bb354d20cbca6034544c4faa46e6a80e/contracts/BondNFT.sol#L160-L187
https://github.com/code-423n4/2022-12-tigris/blob/588c84b7bb354d20cbca6034544c4faa46e6a80e/contracts/Lock.sol#L29-L41


# Vulnerability details

## Impact
Function `Lock.claim()` claims pending rewards from a bond and it's callable for expired bond too. but if a user calls it multiple time after bond expired then function `bondNFT.claim()` would calculate `_pendingDelta` and increase `accRewardsPerShare[][]` value based on `_pendingDelta` multiple times and the value of `accRewardsPerShare[][]` would be higher than it should be and the rewards would get distributed wrongly. attacker can call `claim()` so many times and cause `accRewardsPerShare[][]` to be very wrong and then he can claim rewards for his other bond and withdraw all the rewards and steal other users rewards.

## Proof of Concept
This is `Lock.claim()` code:
```
function claim(
        uint256 _id
    ) public returns (address) {
        claimGovFees();
        (uint _amount, address _tigAsset) = bondNFT.claim(_id, msg.sender);
        IERC20(_tigAsset).transfer(msg.sender, _amount);
        return _tigAsset;
    }
```
As you can see there is no check that this bond is not expired and code just calls `bondNFT.claim()` and code don't release the bond if the bond is expired and a user can call this function multiple times even if his bond is expired. this is `bondNFT.claim()` code:
```
function claim(
        uint _id,
        address _claimer
    ) public onlyManager() returns(uint amount, address tigAsset) {
        Bond memory bond = idToBond(_id);
        require(_claimer == bond.owner, "!owner");
        amount = bond.pending;
        tigAsset = bond.asset;
        unchecked {
            if (bond.expired) {
                uint _pendingDelta = (bond.shares * accRewardsPerShare[bond.asset][epoch[bond.asset]] / 1e18 - bondPaid[_id][bond.asset]) - (bond.shares * accRewardsPerShare[bond.asset][bond.expireEpoch-1] / 1e18 - bondPaid[_id][bond.asset]);
                if (totalShares[bond.asset] > 0) {
                    accRewardsPerShare[bond.asset][epoch[bond.asset]] += _pendingDelta*1e18/totalShares[bond.asset];
                }
            }
            bondPaid[_id][bond.asset] += amount;
        }
        IERC20(tigAsset).transfer(manager, amount);
        emit ClaimFees(tigAsset, amount, _claimer, _id);
    }
```
As you can see if the bond is expired code tries to calculating rewards assigned because of this expired bond during the epochs after the expiration time which is `_pendingDelta` and then user redistribute that `_pendingDelta` among current shares. but if this function gets called multiple times for expired bond the value of the `_pendingDelta` won't get decreased (only would get decreased the first time because of the `bondPaid[][]`) and code won't know that already calculated and redistributed `_pendingDelta` and it would incre