MEDIUM severity: The vulnerability allows an earner to continue earning even after being removed from the approved li. The vulnerability allows an earner to continue earning even after being removed from the approved list. This occurs because the `stopEarning()` function only allows the earner themselves to stop earning, and not others. As a result, an earner can continue to earn the `Earner Rate` even after being r...

Vulnerable code:
```\nfunction rate() external view returns (uint256) {\n    uint256 safeEarnerRate_ = getSafeEarnerRate(\n        IMinterGateway(minterGateway).totalActiveOwedM(),\n        IMToken(mToken).totalEarningSupply(),\n        IMinterGateway(minterGateway).minterRate()\n    );\n\n    return UIntMath.min256(maxRate(), (RATE_MULTIPLIER * safeEarnerRate_) / ONE);\n}\n\nfunction getSafeEarnerRate(\n    uint240 totalActiveOwedM_,\n    uint240 totalEarningSupply_,\n    uint32 minterRate_\n) public pure returns (uint32) {\n    if (totalActiveOwedM_ == 0) return 0;\n\n    if (totalEarningSupply_ == 0) return type(uint32).max;\n\n    if (totalActiveOwedM_ <= totalEarningSupply_) {\n        return uint32((uint256(totalActiveOwedM_) * minterRate_) / totalEarningSupply_);\n    }\n\n    uint48 deltaMinterIndex_ = ContinuousIndexingMath.getContinuousIndex(\n        ContinuousIndexingMath.convertFromBasisPoints(minterRate_),\n        RATE_CONFIDENCE_INTERVAL\n    );\n\n    int256 lnArg_ = int256(\n        _EXP_SCALED_ONE +\n            ((uint256(totalActiveOwedM_) * (deltaMinterIndex_ - _EXP_SCALED_ONE)) / totalEarningSupply_)\n    );\n\n    int256 lnResult_ = wadLn(lnArg_ * _WAD_TO_EXP_SCALER) / _WAD_TO_EXP_SCALER;\n\n    uint256 expRate_ = (uint256(lnResult_) * ContinuousIndexingMath.SECONDS_PER_YEAR) / RATE_CONFIDENCE_INTERVAL;\n\n    if (expRate_ > type(uint64).max) return type(uint32).max;\n\n    uint40 safeRate_ = ContinuousIndexingMath.convertToBasisPoints(uint64(expRate_));\n\n    return (safeRate_ > type(uint32).max)? type(uint32).max : uint32(safeRate_);\n}\n```\n```\nfunction test_AliceStillEarnAfterDisapproved() external {\n\n    _registrar.updateConfig(MAX_EARNER_RATE, 40000);\n    _minterGateway.activateMinter(_minters[0]);\n\n    uint256 collateral = 1_000_000e6;\n    _updateCollateral(_minters[0], collateral);\n\n    _mintM(_minters[0], 400e6, _bob);\n    _mintM(_minters[0], 400e6, _alice);\n    uint aliceInitialBalance = _mToken.balanceOf(_alice);\n    uint bobInitialBalance = _mToken.balanceOf(_bob);\n\n    assertEq(aliceInitialBalance, bobInitialBalance);\n\n    vm.prank(_alice);\n    _mToken.startEarning();\n    vm.prank(_bob);\n    _mToken.startEarning();\n\n    vm.warp(block.timestamp + 1 days);\n    uint aliceEarningDay1 = _mToken.balanceOf(_alice) - aliceInitialBalance;\n    uint bobEarningDay1 = _mToken.balanceOf(_bob) - bobInitialBalance;\n\n    assertNotEq(aliceEarningDay1, 0);\n    assertEq(aliceEarningDay1, bobEarningDay1);\n\n    _registrar.removeFromList(TTGRegistrarReader.EARNERS_LIST, _alice);\n    vm.warp(block.timestamp + 1 days);\n    uint aliceEarningDay2 = _mToken.balanceOf(_alice) - aliceInitialBalance - aliceEarningDay1;\n    uint bobEarningDay2 = _mToken.balanceOf(_bob) - bobInitialBalance - bobEarningDay1;\n\n    assertNotEq(aliceEarningDay2, 0);\n    assertEq(aliceEarningDay2, bobEarningDay2);\n\n    uint earnerRateBefore = _mToken.earnerRate();\n\n    vm.prank(_alice);\n    _mToken.stopEarning();\n    uint earnerRateAfter = _mToken.earnerRate();\n\n    assertApproxEqRel(earnerRateBefore * 2, earnerRateAfter, 0.01e18);\n\n    vm.warp(block.timestamp + 1 days);\n    uint aliceEarningDay3 = _mToken.balanceOf(_alice) - aliceInitialBalance - aliceEarningDay1 - aliceEarningDay2;\n    uint bobEarningDay3 = _mToken.balanceOf(_bob) - bobInitialBalance - bobEarningDay\n```