Minting LVMON
LVMONMinter converts native MON or WMON into LVMON. The current mainnet configuration mints LVMON 1:1 with the input amount; all three assets use 18 decimals.
This is a standalone helper contract, not a Diamond facet. Calls on this page go to the LVMONMinter address.
| Contract | Address |
|---|---|
| LVMONMinter | 0x6FbEa6986F38aA85D09a8e9d8E5c71499ef70909 |
| WMON | 0x3bd359C1119dA7Da1D913D1C4D2B7c461115433A |
| LVMON | 0x91b81bfbe3A747230F0529Aa28d8b2Bc898E6D56 |
Access requirement
Only whitelisted callers can mint. Check the exact address that will call mint before asking the user to approve or send funds:
function whitelist(address account) external view returns (bool);The check uses msg.sender. If a smart account or another contract submits the call, that contract must be whitelisted — whitelisting the user's EOA is not enough. Only the LVMONMinter owner can change this list; there is no public self-registration transaction.
ABI and setup
The examples use the clients and account from the Quickstart config.
import { parseAbi } from 'viem'
export const LVMON_MINTER = '0x6FbEa6986F38aA85D09a8e9d8E5c71499ef70909' as const
export const WMON = '0x3bd359C1119dA7Da1D913D1C4D2B7c461115433A' as const
export const LVMON_MINTER_ABI = parseAbi([
'function whitelist(address account) view returns (bool)',
'function mint(uint256 amountIn) payable returns (uint256 lvmonOut)',
'function issuer() view returns (address)',
'function wmon() view returns (address)',
'function lvmon() view returns (address)',
'event Minted(address indexed user, uint256 monIn, uint256 lvmonOut)',
])Check access once at the start of the flow:
import { account, publicClient } from './config'
import { LVMON_MINTER, LVMON_MINTER_ABI } from './lvmon-minter'
const allowed = await publicClient.readContract({
address: LVMON_MINTER,
abi: LVMON_MINTER_ABI,
functionName: 'whitelist',
args: [account.address],
})
if (!allowed) throw new Error('This caller is not authorized to mint LVMON')Mint with native MON
Pass the same amount to the amountIn argument and transaction value. The contract wraps the MON to WMON, mints LVMON, and sends the LVMON back to msg.sender in one transaction.
import { formatEther, parseEther, parseEventLogs } from 'viem'
import { account, publicClient, walletClient } from './config'
import { LVMON_MINTER, LVMON_MINTER_ABI } from './lvmon-minter'
const amountIn = parseEther('1')
const { request, result: expectedOut } = await publicClient.simulateContract({
account,
address: LVMON_MINTER,
abi: LVMON_MINTER_ABI,
functionName: 'mint',
args: [amountIn],
value: amountIn,
})
console.log('Expected LVMON:', formatEther(expectedOut))
const hash = await walletClient.writeContract(request)
const receipt = await publicClient.waitForTransactionReceipt({ hash })
const [minted] = parseEventLogs({
abi: LVMON_MINTER_ABI,
eventName: 'Minted',
logs: receipt.logs,
})
if (!minted) throw new Error('Minted event not found')
console.log('Minted LVMON:', formatEther(minted.args.lvmonOut))mint has no minLvmonOut parameter. Simulate immediately before submitting and use the returned value or Minted.lvmonOut as the authoritative output instead of assuming the conversion rate in accounting code.
Mint with WMON
For WMON, first approve the LVMONMinter, then call mint without transaction value.
import { erc20Abi, parseEther } from 'viem'
import { account, publicClient, walletClient } from './config'
import { LVMON_MINTER, LVMON_MINTER_ABI, WMON } from './lvmon-minter'
const amountIn = parseEther('1')
const approvalHash = await walletClient.writeContract({
account,
address: WMON,
abi: erc20Abi,
functionName: 'approve',
args: [LVMON_MINTER, amountIn],
})
await publicClient.waitForTransactionReceipt({ hash: approvalHash })
const { request } = await publicClient.simulateContract({
account,
address: LVMON_MINTER,
abi: LVMON_MINTER_ABI,
functionName: 'mint',
args: [amountIn],
// No value: sending any native MON selects the native-MON path.
})
const hash = await walletClient.writeContract(request)
await publicClient.waitForTransactionReceipt({ hash })Approve only the amount you intend to mint. A successful call consumes that WMON allowance and delivers the resulting LVMON to the caller.
Function reference
function mint(uint256 amountIn) external payable returns (uint256 lvmonOut);| Input mode | amountIn | msg.value | Additional requirement |
|---|---|---|---|
| Native MON | MON amount, 18 decimals | Must equal amountIn | Caller needs enough MON for the input and gas |
| WMON | WMON amount, 18 decimals | 0 | Approve the minter to spend at least amountIn WMON |
The mode is selected solely by whether msg.value is greater than zero. Do not send native MON on a WMON mint call.
Read-only configuration:
| Function | Returns |
|---|---|
whitelist(account) | Whether account may call mint |
issuer() | The LVMON issuer used by the minter |
wmon() | The configured WMON token |
lvmon() | The LVMON token returned to the caller |
owner() | Address allowed to update the caller whitelist |
setWhitelist(address account, bool allowed) also exists, but is owner-only. Integrations should use whitelist(account) to check access rather than attempting the administrative call.
Events
event Minted(address indexed user, uint256 monIn, uint256 lvmonOut);
event WhitelistUpdated(address indexed account, bool allowed);Minted.monIn is the input amount for either mode: native MON or WMON. Minted.user is the caller and recipient of the LVMON.
Common reverts
| Revert | Cause |
|---|---|
lvmon-minter: caller not whitelisted | msg.sender is not on the minter's caller whitelist |
lvmon-minter: amount mismatch | Native msg.value does not equal amountIn |
lvmon-minter: amount=0 | WMON mode was called with a zero amount |
| Token transfer failure | WMON balance or allowance is below amountIn |
mint not enabled | Protocol-level LVMON minting is paused |
token reserve disabled | The WMON reserve is disabled at the issuer |
All wrapping, reserve deposit, minting, and transfer steps are atomic. If any step reverts, the caller keeps the original MON or WMON. A WMON approval submitted as an earlier transaction remains in place until it is used or replaced.