Skip to content

V2#129

Open
toninorair wants to merge 27 commits into
mainfrom
v2
Open

V2#129
toninorair wants to merge 27 commits into
mainfrom
v2

Conversation

@toninorair

Copy link
Copy Markdown
Contributor

No description provided.

deluca-mike and others added 20 commits January 21, 2025 14:00
- solc 0.8.26
- latest common
- latest forge-std
- registrar as constructor arg
- excess destination as constructor arg
- constants made public
- token name changed
- `IsApprovedEarner` and `NotApprovedEarner` errors have account as parameter
- basic Migrator contract introduced
- version bump
- use more from common
- more test coverage
- fixed scripts to allow for generic deploy and mainnet upgrade
- principal-based earner account, instead of last index
- migration for existing earners on upgrade
Co-authored-by: Michael De Luca <michael.deluca@circle-free.com>
* Increase excess type

* Ignore negative rounding error
* feat: use SwapFacility

* chore: rename M^0 -> M0

* fix: tests
* fix(WrappedMToken): remove EarnerManager

* chore: rename M^0 to M0
* chore(lib): update libs

* feat(WrappedM): add Freezable

* feat(WrappedM): add Pausable

* feat(WrappedM): add initialize upgrade pattern

* fix(build): reduce optimizer runs

* chore(lib): import Pausable and Freezable from extensions repo
@github-actions

github-actions Bot commented May 31, 2026

Copy link
Copy Markdown

LCOV of commit d2374be during Forge Coverage #656

Summary coverage rate:
  lines......: 99.4% (328 of 330 lines)
  functions..: 100.0% (68 of 68 functions)
  branches...: 87.5% (7 of 8 branches)

Files changed coverage rate:
                                 |Lines       |Functions  |Branches    
  Filename                       |Rate     Num|Rate    Num|Rate     Num
  =====================================================================
  src/ListOfEarnersToMigrate.sol |22.2%      9| 0.0%     2|    -      0
  src/WrappedMToken.sol          |21.8%    271| 0.0%    59|    -      0
  src/WrappedMTokenMigratorV1.sol|14.6%     48| 114%     7|    -      0

PierrickGT and others added 7 commits June 5, 2026 13:23
)

- I-01: call _disableInitializers() in constructor to lock down the
  implementation contract, per OpenZeppelin guidance
- I-02: fix NatSpec typos in IWrappedMToken (Earner Manager -> Registrar/
  Excess Manager, EXCESS_MANAGER_ROLE description)
- I-03: remove unused HUNDRED_PERCENT constant and interface declaration
* fix(WrappedM): correct Claimed event recipient when skipTransfer is true

When `_claim` runs with `skipTransfer_` true (paused stop-earning or
freeze),
the yield stays on `account_`, but the `Claimed` event reported the
configured
claim recipient. Compute the effective recipient as `account_` when
transfer is
skipped so the event reflects where the yield actually lands.

* docs(WrappedM): correct inaccurate NatSpec on unwrap and earning toggles

- unwrap: document that `recipient` is unused and M is always sent to the
  SwapFacility, which routes it to the final recipient.
- enableEarning/disableEarning: replace "if it has never been done" with
  "not already enabled/disabled", since earning can be toggled multiple times.

* chore(WrappedM): call inherited base initializers in initialize()

Invoke __Context_init, __ERC165_init, and __AccessControl_init in the
initializer. These are no-ops in the current OpenZeppelin version, but calling
them prevents silently uninitialized state should a future version add
meaningful initialization logic.
* fix(WrappedM): prevent frozen claim recipient from blocking stopEarningFor

An earner could point their claim recipient at a frozen address so that the
permissionless stopEarningFor() reverts inside _claim() -> _transfer() ->
_revertIfFrozen(recipient_), keeping the account earning indefinitely and
defeating the deauthorization mechanism.

Both stopEarningFor() overloads now fall back to skipTransfer when the resolved
claim recipient is frozen, mirroring the _beforeFreeze path: the yield is
crystallized onto the account's own balance instead of being routed to the
frozen recipient, so deauthorization always succeeds.

* fix(WrappedM): enforce sorted unique earners in migrator list

The WrappedMTokenMigratorV1 migration corrupts accounting if an address
appears twice in the earners array, since the first pass overwrites the
lastIndex slot with the computed principal. ListOfEarnersToMigrate now
requires strictly ascending addresses, enforcing sorted order, uniqueness
and non-zero in a single O(n) pass without the gas cost of an O(n^2) check.

Integration test fixtures sort the in-memory earners copy before deploying
the migrator, mirroring the production generation script.

* chore(script): harden earners list generation

Make the earners list generation safe to rely on for the v1->v2 migration:

- Paginate holder fetches so earners are never silently truncated by the
  `first` cap, with a max-pages guard against a broken `skip`.
- Build the whole file in memory and write once after every network
  succeeds; abort without writing on any error, and exit non-zero, so a
  partial run never mixes fresh and stale lists.
- Throw on duplicate or zero earner addresses instead of relying solely on
  the on-chain check.
- Fix the GraphQL response typing (drop the unsound cast), add a request
  timeout, centralize the chain enum, and drop the unused balance field.

* Sort earners before migrator construction (#135)

* fix(deploy): sort earners before migrator construction

* refactor(test): pass earners storage array directly to migrator deploy

Drop the manual storage-to-memory copy loops in the integration test
fixtures; assigning or passing the storage array to a memory parameter
already performs the copy.

---------

Co-authored-by: Pierrick Turelier <pierrick@turelier.com>

---------

Co-authored-by: Denali Marsh <denalimarsh@gmail.com>
Call OZ's parameterless `__Pausable_init()` in `initialize()` to
complete
the initializer chain. Distinct from the `Pausable` component's
`__Pausable_init(pauser_)` overload, which only grants the pauser role.

No behavioral change: OZ v5.3.0's `__Pausable_init()` is empty and the
`_paused` flag already defaults to false.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants