Technical Specifications
Wrapped M Specification
Low-level technical specification for Wrapped M (wM) - function signatures, events, errors, and storage layout.
Contract overview
WrappedMToken (wM) is a non-rebasing ERC-20 wrapper for the rebasing $M token. It maintains yield-earning capabilities while providing compatibility with DeFi protocols that require standard ERC-20 tokens.
- Decimals: 6 (matches
$M) - Index: Derived from the underlying
$Mtoken's index - Yield realization: Explicit claiming (not automatic rebasing)
Key functions
Wrapping and Unwrapping
| Function | Description |
|---|---|
wrap(address recipient, uint256 amount) | Deposit $M tokens, receive equivalent wM |
unwrap(address recipient, uint256 amount) | Burn wM tokens, receive equivalent $M |
wrapWithPermit(address recipient, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) | Wrap with gasless $M approval |
ERC20 Standard
| Function | Description |
|---|---|
transfer(address to, uint256 amount) | Transfer wM tokens |
transferFrom(address from, address to, uint256 amount) | Transfer wM on behalf of another address |
approve(address spender, uint256 amount) | Approve a spender allowance |
balanceOf(address account) | Returns stored balance (excludes unclaimed yield) |
totalSupply() | Returns total wM in circulation |
Earning Management
| Function | Description |
|---|---|
startEarningFor(address account) | Activate earning mode for an approved account |
stopEarningFor(address account) | Deactivate earning mode (claims outstanding yield) |
enableEarning() | Enable earning for the wM contract itself on $M |
disableEarning() | Disable earning for the wM contract on $M |
Yield Management
| Function | Description |
|---|---|
claimFor(address account) | Claim accrued yield for an account |
setClaimRecipient(address recipient) | Set a custom address to receive claimed yield |
Balance and Yield Queries
| Function | Returns |
|---|---|
balanceOf(address account) | Stored balance (excludes unclaimed yield) |
accruedYieldOf(address account) | Unclaimed yield for an earning account |
balanceWithYieldOf(address account) | balanceOf + accruedYieldOf |
isEarning(address account) | Whether the account is in earning mode |
totalNonEarningSupply() | Sum of all non-earning balances |
totalEarningSupply() | Sum of all earning balances (excluding yield) |
projectedEarningSupply() | Total earning supply if all yield were claimed |
excess() | $M held by contract minus total wM liabilities |
Excess Management
| Function | Description |
|---|---|
claimExcess() | Transfer accumulated excess $M to excessDestination |
excessDestination() | Returns the address that receives claimed excess (typically Distribution Vault) |
Admin Operations (via EarnerManager)
| Function | Description |
|---|---|
setEarnerDetails(address account, bool status, uint16 feeRate) | Set earning status and fee rate for an account |
setEarnerDetails(address[] accounts, bool[] statuses, uint16[] feeRates) | Bulk set earning details |
earnerStatusFor(address account) | Check earner status for an account |
getEarnerDetails(address account) | Get full earner details including admin and fee rate |
Account storage model
struct Account {
bool isEarning; // Whether the account is in earning mode
uint240 balance; // Current token balance (excluding yield)
uint112 earningPrincipal; // Principal amount for earning accounts
bool hasClaimRecipient; // Whether a custom recipient is set
bool hasEarnerDetails; // Whether admin fee settings exist
}
Events
| Event | Description |
|---|---|
Transfer(address indexed from, address indexed to, uint256 value) | Standard ERC20 transfer |
Approval(address indexed owner, address indexed spender, uint256 value) | Standard ERC20 approval |
StartedEarning(address indexed account) | Account entered earning mode |
StoppedEarning(address indexed account) | Account exited earning mode |
Claimed(address indexed account, address indexed recipient, uint256 yield) | Yield claimed |
ExcessClaimed(uint240 amount) | Excess $M claimed to destination |
Errors
| Error | Condition |
|---|---|
NotApprovedEarner() | Account is not approved for earning |
EarningIsEnabled() | Operation not permitted while earning is enabled |
EarningIsDisabled() | Operation requires earning to be enabled |
InsufficientBalance(address account, uint256 balance, uint256 amount) | Transfer, unwrap, or burn exceeds balance |
Index mechanism
The wM index is derived from the underlying $M token's index:
When earning is enabled:
When earning is disabled:
Yield claim recipient priority
When determining where to send claimed yield:
- User-specified recipient (via
setClaimRecipient) - Governance-specified override (via Registrar)
- The account itself (default)
Solvency invariant
The excess above this threshold accumulates from yield on $M backing non-earning wM holders and minor rounding effects.
Related
- Wrapped M overview - Full conceptual documentation
- M Token specification -
$Mtoken spec - Distribution Vault - Where excess is typically directed