Features and Operations
I. Basic Token Operations
Wrapping M to wM
Users can deposit $M tokens to receive an equivalent amount of wM:
wrap(recipient, amount)
The $M tokens are held by the wM contract and can potentially earn yield.
Unwrapping wM to M
Users can burn wM tokens to receive the equivalent amount of M:
unwrap(recipient, amount)
Any accrued yield remains in the user's wM balance if they're in earning mode.
Gasless Operations
The contract supports wrapping with permits for improved UX:
wrapWithPermit(recipient, amount, deadline, signature)
Standard ERC-20 Operations
All standard ERC-20 functions are supported, including:
transfer(to, amount)
transferFrom(from, to, amount)
approve(spender, amount)
balanceOf(account)
II. Earning Management
Starting to Earn
Approved accounts can activate earning status:
startEarningFor(account)
This converts their balance to a principal amount that will begin accruing yield.
Stopping Earning
Accounts can deactivate earning status (or anyone can do this for an account that's no longer approved):
stopEarningFor(account)
This claims any outstanding yield and converts the balance back to non-earning.
Global Earning Status
The wM contract itself must be an approved earner in the M token system. Earning can be enabled or disabled for the entire system:
enableEarning()
disableEarning()
A key improvement in wM v2 is the ability to re-enable earning after it has been disabled.
III. Yield Management
Claiming Yield
Accrued yield can be claimed at any time:
claimFor(account)
This increases the account's wM balance by the yielded amount and triggers appropriate transfers based on recipient settings.
Setting Claim Recipients
Users can direct their yield to another address:
setClaimRecipient(recipient)
This allows for flexible yield strategies without changing the underlying balance.
Checking Accrued Yield
Several view functions allow users and integrations to check the yield that has accrued for an earning account but has not yet been claimed:
accruedYieldOf(account)
:- Returns the amount of wM tokens earned as yield based on the account's
earningPrincipal
and the time elapsed (represented by the increase in thecurrentIndex
) since the last claim or since earning started. - This represents only the unclaimed portion of the yield. It does not include yield that has already been claimed and added to the balance.
- If the account is not in Earning Mode, this returns 0.
- Returns the amount of wM tokens earned as yield based on the account's
balanceWithYieldOf(account)
:- Returns the sum of the account's current stored
balanceOf
plus the currently claimableaccruedYieldOf
. - This function effectively shows the total wM value attributable to the account at that moment, representing what the balance would be if the accrued yield were claimed instantly (before considering any fees or alternate claim recipients).
- Returns the sum of the account's current stored
Effect of Claiming: When claimFor(account)
is successfully executed, the calculated accrued yield is processed. If the yield (net of fees) is directed to the account owner, their stored balanceOf
increases. Consequently, immediately after a claim, accruedYieldOf
will return 0 (or a negligible amount due to block timing), as the yield is no longer "accrued but unclaimed". balanceWithYieldOf
will then equal balanceOf
. New yield will start accumulating again as time passes and the currentIndex
increases further.
IV. Excess Management & Value Capture
Concept: The wM contract holds underlying M tokens. Because the wM contract itself earns yield on all these M tokens, but wM yield is only accrued for earning-mode wM holders, a surplus (or "excess") of $M tokens naturally accumulates within the contract over time. This primarily comes from the M yield earned on tokens backing non-earning wM balances.
Important note:Claiming Excess: This accumulated excess M, representing value captured by the protocol, can be claimed and transferred out using the claimExcess()
function.
claimExcess() returns (uint240 claimed_)
Destination: The excessDestination address, set during deployment, receives these claimed tokens. Typically, this is the Distribution Vault, directing this value back to the protocol ecosystem and ultimately benefiting Zero token holders.
V. Admin Operations via EarnerManager
The EarnerManager contract empowers designated admins ('special users') with the delegated authority to approve wM earners, managing status for potentially many accounts outside the standard governance process
Setting Earner Status
Admins can enable accounts for earning and set fee rates:
setEarnerDetails(account, status, feeRate)
Bulk Operations
Multiple accounts can be managed in a single transaction:
setEarnerDetails(accounts[], statuses[], feeRates[])
Checking Earner Status
Various functions provide information about earner status:
earnerStatusFor(account)
getEarnerDetails(account)