# Inaccurate fees computation

Unlock Protocol's shareKey fee math applies the transfer fee to remaining time instead of credited time, overcharging receivers when sharing more time than available.

- Payout: Audit contest
- Severity: medium
- Program: Unlock Protocol
- Found by: cmichel
- Disclosed: 2022-04-20
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2021-11-unlock-findings/issues/165
- Library page: https://bugbountylibrary.com/r/c4%3A2021-11-unlock%3AM-10
- Tags: area:web3 domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:accounting-error vuln:fee-bypass

**Target:** MixinTransfer.shareKey key-sharing fee logic (Solidity contract)
**Root cause:** In the else branch when timePlusFee >= timeRemaining, fee is computed on timeRemaining rather than on the credited time, so time = timeRemaining - fee undercredits the receiver instead of timeRemaining/(1+fee).
**Steps:**
1. Call shareKey with _timeShared such that timePlusFee >= timeRemaining (e.g. _timeShared=10000s, 10% fee, timeRemaining=11000s).
2. Observe else branch: fee = getTransferFee(keyOwner, timeRemaining) = 1100.
3. time = timeRemaining - fee = 11000 - 1100 = 9900 instead of 10000.
4. Receiver gets 100s less than owed; correct formula is time = BASIS_POINTS_DEN * timeRemaining / (transferFeeBasisPoints + BASIS_POINTS_DEN).
**How found:** Code reading of shareKey: noticed the invariant time + fee*time == timeRemaining holds in the first branch but the else branch recomputes fee on timeRemaining, breaking the invariant.
**Insight:** When a fee formula is duplicated across branches, verify the algebraic invariant (time + fee*time == total) holds in every branch; boundary branches often recompute the fee on the wrong base.
