From f3124063fd671b319beb3cb184b30e6532da5032 Mon Sep 17 00:00:00 2001 From: Michael De Luca <35537333+deluca-mike@users.noreply.github.com> Date: Thu, 5 Dec 2024 16:35:38 -0500 Subject: [PATCH] fix: Natspec corrections (#92) --- src/SmartMToken.sol | 9 ++-- src/interfaces/IEarnerManager.sol | 4 ++ src/interfaces/ISmartMToken.sol | 12 ++--- test/unit/EarnerManager.sol | 2 +- test/unit/SmartMToken.t.sol | 88 +++++++++++++++---------------- test/unit/Stories.t.sol | 11 ++-- 6 files changed, 66 insertions(+), 60 deletions(-) diff --git a/src/SmartMToken.sol b/src/SmartMToken.sol index e888e50..ac8cb8a 100644 --- a/src/SmartMToken.sol +++ b/src/SmartMToken.sol @@ -35,10 +35,11 @@ contract SmartMToken is ISmartMToken, Migratable, ERC20Extended { /** * @dev Struct to represent an account's balance and yield earning details - * @param isEarning Whether the account is actively earning yield. - * @param balance The present amount of tokens held by the account. - * @param lastIndex The index of the last interaction for the account (0 for non-earning accounts). - * @param hasEarnerDetails Whether the account has additional details for earning yield. + * @param isEarning Whether the account is actively earning yield. + * @param balance The present amount of tokens held by the account. + * @param lastIndex The index of the last interaction for the account (0 for non-earning accounts). + * @param hasEarnerDetails Whether the account has additional details for earning yield. + * @param hasClaimRecipient Whether the account has an explicitly set claim recipient. */ struct Account { // First Slot diff --git a/src/interfaces/IEarnerManager.sol b/src/interfaces/IEarnerManager.sol index 232e857..f1b068b 100644 --- a/src/interfaces/IEarnerManager.sol +++ b/src/interfaces/IEarnerManager.sol @@ -62,6 +62,8 @@ interface IEarnerManager is IMigratable { /** * @notice Sets the status for `account` to `status`. + * @notice If approving an earner that is already earning, but was recently removed from the Registrar earners list, + * call `smartM.stopEarning(account)` before calling this, then call `smartM.startEarning(account)`. * @param account The account under which yield could generate. * @param status Whether the account is an earner, according to the admin. * @param feeRate The fee rate to be taken from the yield. @@ -70,6 +72,8 @@ interface IEarnerManager is IMigratable { /** * @notice Sets the status for multiple accounts. + * @notice If approving an earner that is already earning, but was recently removed from the Registrar earners list, + * call `smartM.stopEarning(account)` before calling this, then call `smartM.startEarning(account)`. * @param accounts The accounts under which yield could generate. * @param statuses Whether each account is an earner, respectively, according to the admin. * @param feeRates The fee rates to be taken from the yield, respectively. diff --git a/src/interfaces/ISmartMToken.sol b/src/interfaces/ISmartMToken.sol index 6e0e687..60a86cc 100644 --- a/src/interfaces/ISmartMToken.sol +++ b/src/interfaces/ISmartMToken.sol @@ -69,7 +69,7 @@ interface ISmartMToken is IMigratable, IERC20Extended { error EarningCannotBeReenabled(); /** - * @notice Emitted when calling `stopEarning` for an account approved as earner by the Registrar. + * @notice Emitted when calling `mToken.stopEarning` for an account approved as an earner. * @param account The account that is an approved earner. */ error IsApprovedEarner(address account); @@ -83,7 +83,7 @@ interface ISmartMToken is IMigratable, IERC20Extended { error InsufficientBalance(address account, uint240 balance, uint240 amount); /** - * @notice Emitted when calling `startEarning` for an account not approved as earner by the Registrar. + * @notice Emitted when calling `mToken.startEarning` for an account not approved as an. * @param account The account that is not an approved earner. */ error NotApprovedEarner(address account); @@ -195,25 +195,25 @@ interface ISmartMToken is IMigratable, IERC20Extended { function disableEarning() external; /** - * @notice Starts earning for `account` if allowed by the Registrar. + * @notice Starts earning for `account` if allowed by the Earner Manager. * @param account The account to start earning for. */ function startEarningFor(address account) external; /** - * @notice Starts earning for multiple accounts if individually allowed by the Registrar. + * @notice Starts earning for multiple accounts if individually allowed by the Earner Manager. * @param accounts The accounts to start earning for. */ function startEarningFor(address[] calldata accounts) external; /** - * @notice Stops earning for `account` if disallowed by the Registrar. + * @notice Stops earning for `account` if disallowed by the Earner Manager. * @param account The account to stop earning for. */ function stopEarningFor(address account) external; /** - * @notice Stops earning for multiple accounts if individually disallowed by the Registrar. + * @notice Stops earning for multiple accounts if individually disallowed by the Earner Manager. * @param accounts The account to stop earning for. */ function stopEarningFor(address[] calldata accounts) external; diff --git a/test/unit/EarnerManager.sol b/test/unit/EarnerManager.sol index 7dd86c1..39c3e7d 100644 --- a/test/unit/EarnerManager.sol +++ b/test/unit/EarnerManager.sol @@ -9,7 +9,7 @@ import { IEarnerManager } from "../../src/interfaces/IEarnerManager.sol"; import { MockRegistrar } from "./../utils/Mocks.sol"; import { EarnerManagerHarness } from "../utils/EarnerManagerHarness.sol"; -contract EarnerStatusManagerTests is Test { +contract EarnerManagerTests is Test { bytes32 internal constant _EARNERS_LIST_IGNORED_KEY = "earners_list_ignored"; bytes32 internal constant _EARNERS_LIST_NAME = "earners"; bytes32 internal constant _ADMINS_LIST_NAME = "em_admins"; diff --git a/test/unit/SmartMToken.t.sol b/test/unit/SmartMToken.t.sol index a789d65..86f61df 100644 --- a/test/unit/SmartMToken.t.sol +++ b/test/unit/SmartMToken.t.sol @@ -25,7 +25,7 @@ contract SmartMTokenTests is Test { uint56 internal constant _ONE_HUNDRED_PERCENT = 10_000; bytes32 internal constant _CLAIM_OVERRIDE_RECIPIENT_KEY_PREFIX = "wm_claim_override_recipient"; - bytes32 internal constant _EARNERS_LIST = "earners"; + bytes32 internal constant _EARNERS_LIST_NAME = "earners"; address internal _alice = makeAddr("alice"); address internal _bob = makeAddr("bob"); @@ -144,7 +144,7 @@ contract SmartMTokenTests is Test { } function test_internalWrap_toEarner() external { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); @@ -206,7 +206,7 @@ contract SmartMTokenTests is Test { accountEarning_ = earningEnabled_ && accountEarning_; if (earningEnabled_) { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); } @@ -274,7 +274,7 @@ contract SmartMTokenTests is Test { accountEarning_ = earningEnabled_ && accountEarning_; if (earningEnabled_) { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); } @@ -340,7 +340,7 @@ contract SmartMTokenTests is Test { accountEarning_ = earningEnabled_ && accountEarning_; if (earningEnabled_) { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); } @@ -406,7 +406,7 @@ contract SmartMTokenTests is Test { accountEarning_ = earningEnabled_ && accountEarning_; if (earningEnabled_) { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); } @@ -468,7 +468,7 @@ contract SmartMTokenTests is Test { } function test_internalUnwrap_insufficientBalance_fromEarner() external { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); @@ -507,7 +507,7 @@ contract SmartMTokenTests is Test { } function test_internalUnwrap_fromEarner() external { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); @@ -559,7 +559,7 @@ contract SmartMTokenTests is Test { accountEarning_ = earningEnabled_ && accountEarning_; if (earningEnabled_) { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); } @@ -627,7 +627,7 @@ contract SmartMTokenTests is Test { accountEarning_ = earningEnabled_ && accountEarning_; if (earningEnabled_) { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); } @@ -682,7 +682,7 @@ contract SmartMTokenTests is Test { } function test_claimFor_earner() external { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); @@ -702,7 +702,7 @@ contract SmartMTokenTests is Test { } function test_claimFor_earner_withOverrideRecipient() external { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _registrar.set( keccak256(abi.encode(_CLAIM_OVERRIDE_RECIPIENT_KEY_PREFIX, _alice)), @@ -731,7 +731,7 @@ contract SmartMTokenTests is Test { } function test_claimFor_earner_withFee() external { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); @@ -757,7 +757,7 @@ contract SmartMTokenTests is Test { } function test_claimFor_earner_withFeeAboveOneHundredPercent() external { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); @@ -783,7 +783,7 @@ contract SmartMTokenTests is Test { } function test_claimFor_earner_withOverrideRecipientAndFee() external { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _registrar.set( keccak256(abi.encode(_CLAIM_OVERRIDE_RECIPIENT_KEY_PREFIX, _alice)), @@ -828,7 +828,7 @@ contract SmartMTokenTests is Test { balance_ = uint240(bound(balance_, 0, _getMaxAmount(accountIndex_))); index_ = uint128(bound(index_, accountIndex_, 10 * _EXP_SCALED_ONE)); - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); if (claimOverride_) { _registrar.set( @@ -936,7 +936,7 @@ contract SmartMTokenTests is Test { } function test_transfer_insufficientBalance_fromEarner_toNonEarner() external { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); @@ -998,7 +998,7 @@ contract SmartMTokenTests is Test { } function test_transfer_fromEarner_toNonEarner() external { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); @@ -1040,7 +1040,7 @@ contract SmartMTokenTests is Test { } function test_transfer_fromNonEarner_toEarner() external { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); @@ -1068,7 +1068,7 @@ contract SmartMTokenTests is Test { } function test_transfer_fromEarner_toEarner() external { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); @@ -1113,7 +1113,7 @@ contract SmartMTokenTests is Test { } function test_transfer_earnerToSelf() external { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); @@ -1151,7 +1151,7 @@ contract SmartMTokenTests is Test { bobEarning_ = earningEnabled_ && bobEarning_; if (earningEnabled_) { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); } @@ -1247,7 +1247,7 @@ contract SmartMTokenTests is Test { } function test_startEarningFor_notApprovedEarner() external { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); @@ -1256,7 +1256,7 @@ contract SmartMTokenTests is Test { } function test_startEarning_overflow() external { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); @@ -1275,7 +1275,7 @@ contract SmartMTokenTests is Test { } function test_startEarningFor() external { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); @@ -1302,7 +1302,7 @@ contract SmartMTokenTests is Test { balance_ = uint240(bound(balance_, 0, _getMaxAmount(_currentIndex))); index_ = uint128(bound(index_, _currentIndex, 10 * _EXP_SCALED_ONE)); - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); @@ -1334,7 +1334,7 @@ contract SmartMTokenTests is Test { } function test_startEarningFor_batch_notApprovedEarner() external { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _earnerManager.setEarnerDetails(_alice, true, 0, address(0)); _smartMToken.enableEarning(); @@ -1348,7 +1348,7 @@ contract SmartMTokenTests is Test { } function test_startEarningFor_batch() external { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _earnerManager.setEarnerDetails(_alice, true, 0, address(0)); _earnerManager.setEarnerDetails(_bob, true, 0, address(0)); @@ -1376,7 +1376,7 @@ contract SmartMTokenTests is Test { } function test_stopEarningFor() external { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); @@ -1402,7 +1402,7 @@ contract SmartMTokenTests is Test { balance_ = uint240(bound(balance_, 0, _getMaxAmount(accountIndex_))); index_ = uint128(bound(index_, accountIndex_, 10 * _EXP_SCALED_ONE)); - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); @@ -1471,7 +1471,7 @@ contract SmartMTokenTests is Test { } function test_stopEarningFor_batch() external { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); @@ -1498,22 +1498,22 @@ contract SmartMTokenTests is Test { } function test_enableEarning_earningCannotBeReenabled() external { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), false); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), false); _smartMToken.disableEarning(); - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); vm.expectRevert(ISmartMToken.EarningCannotBeReenabled.selector); _smartMToken.enableEarning(); } function test_enableEarning() external { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); vm.expectEmit(); emit ISmartMToken.EarningEnabled(_currentIndex); @@ -1526,11 +1526,11 @@ contract SmartMTokenTests is Test { vm.expectRevert(ISmartMToken.EarningIsDisabled.selector); _smartMToken.disableEarning(); - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), false); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), false); _smartMToken.disableEarning(); @@ -1539,18 +1539,18 @@ contract SmartMTokenTests is Test { } function test_disableEarning_approvedEarner() external { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); vm.expectRevert(abi.encodeWithSelector(ISmartMToken.IsApprovedEarner.selector, address(_smartMToken))); _smartMToken.disableEarning(); } function test_disableEarning() external { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), false); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), false); vm.expectEmit(); emit ISmartMToken.EarningDisabled(_currentIndex); @@ -1570,7 +1570,7 @@ contract SmartMTokenTests is Test { } function test_balanceOf_earner() external { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); @@ -1667,7 +1667,7 @@ contract SmartMTokenTests is Test { assertEq(_smartMToken.currentIndex(), 0); - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); @@ -1677,7 +1677,7 @@ contract SmartMTokenTests is Test { assertEq(_smartMToken.currentIndex(), 3 * _EXP_SCALED_ONE); - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), false); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), false); _smartMToken.disableEarning(); @@ -1697,7 +1697,7 @@ contract SmartMTokenTests is Test { uint240 transfer_, uint128 index_ ) external { - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _earnerManager.setEarnerDetails(_alice, true, 0, address(0)); _earnerManager.setEarnerDetails(_bob, true, 0, address(0)); diff --git a/test/unit/Stories.t.sol b/test/unit/Stories.t.sol index d9cb361..0d8b32b 100644 --- a/test/unit/Stories.t.sol +++ b/test/unit/Stories.t.sol @@ -11,10 +11,11 @@ import { SmartMToken } from "../../src/SmartMToken.sol"; import { MockEarnerManager, MockM, MockRegistrar } from "../utils/Mocks.sol"; -contract Tests is Test { +contract StoryTests is Test { uint56 internal constant _EXP_SCALED_ONE = 1e12; - bytes32 internal constant _EARNERS_LIST = "earners"; + bytes32 internal constant _EARNERS_LIST_NAME = "earners"; + bytes32 internal constant _ADMINS_LIST_NAME = "em_admins"; address internal _alice = makeAddr("alice"); address internal _bob = makeAddr("bob"); @@ -54,7 +55,7 @@ contract Tests is Test { function test_story() external { _earnerManager.setEarnerDetails(_alice, true, 0, address(0)); _earnerManager.setEarnerDetails(_bob, true, 0, address(0)); - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _smartMToken.enableEarning(); @@ -375,7 +376,7 @@ contract Tests is Test { function test_noExcessCreep() external { _earnerManager.setEarnerDetails(_alice, true, 0, address(0)); _earnerManager.setEarnerDetails(_bob, true, 0, address(0)); - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _mToken.setCurrentIndex(_EXP_SCALED_ONE + 3e11 - 1); @@ -407,7 +408,7 @@ contract Tests is Test { function test_dustWrapping() external { _earnerManager.setEarnerDetails(_alice, true, 0, address(0)); _earnerManager.setEarnerDetails(_bob, true, 0, address(0)); - _registrar.setListContains(_EARNERS_LIST, address(_smartMToken), true); + _registrar.setListContains(_EARNERS_LIST_NAME, address(_smartMToken), true); _mToken.setCurrentIndex(_EXP_SCALED_ONE + 1);