BUILD ON PYUSDx

PYUSDx Quick Guide

The launch sequence for a custom token on PYUSDx: each step, its owner, and its result.

Launching a custom token requires a set of decisions, one deploy transaction, and a handoff to M0. M0 operates the shared layer and enables yield for your token. This page maps the full sequence so you can scope the work. For the commands, see the deployment guide.

Before you begin

You need the following:

  • A deployer wallet with gas on each target chain. Start on Ethereum Sepolia.
  • An admin address, preferably a multisig, to hold DEFAULT_ADMIN_ROLE on your token, and addresses for the operational roles in step 2. On testnet, one wallet can hold every role.
  • A treasury address to receive yield.
  • Testnet PYUSDx; faucets are deployed on Ethereum Sepolia and Arbitrum Sepolia. Addresses are on the deployments page.
  • An initial call with M0. Contact M0 before you deploy.

Launch sequence

#StepOwnerDescriptionResult
1Scope with M0You and M0Confirm the template, chains, timeline, and yield enablementCompleted decisions table
2Assign rolesYouChoose an address for each role on your tokenRole assignments
3Deploy on testnetYou (M0 can assist)One call to ExtensionFactory on Ethereum SepoliaToken address
4Test your tokenYouWrap, unwrap, bridge, freeze, and pauseTest checklist complete
5Share the addressYouSend your token address and chain to M0Handoff complete
6M0 enables yieldM0M0 registers your token as an earner on PYUSDxYield accruing
7Deploy on mainnetYou (M0 can assist)Repeat steps 3, 5, and 6 on each target chainToken live
8Operate your tokenYouClaim yield, manage roles, apply controls, manage upgradesOngoing

1. Scope with M0

A short set of decisions defines your token.

DecisionOptionsNotes
TemplateYieldToOne or MultiMintYieldToOne routes all yield to one treasury. M0 recommends it for most partners. MultiMint adds approved alternative stablecoins as backing under per-asset caps and adds one more role. Fixed at deployment.
Name and symbolYour brandFor example, "Acme Yield USD" and ayUSD. Fixed at deployment. Distinct from the deployment name in step 3.
Yield recipientA treasury addressWhere claimed yield is minted. YIELD_RECIPIENT_MANAGER_ROLE can change it later.
Role holdersOne address per roleSee step 2. DEFAULT_ADMIN_ROLE can change them later.
ChainsOne or more supported chainsEthereum, Arbitrum, and Monad. Start with one chain and add more later. Reusing the same deployer and deployment name produces the same address on each chain.
Compliance policyYour policyHow and when you apply freeze and pause, and how you coordinate with M0 on forced transfers.

Fixed at deployment: template, name, and symbol.

Changeable later: yield recipient, role holders, and the set of chains.

2. Assign roles

Each role on your token is independent. On testnet, assign one wallet to every role. For mainnet, separate them based on which wallets own each role.

RolePermissionsSuggested holder
DEFAULT_ADMIN_ROLEGrants and revokes every other roleMultisig
YIELD_RECIPIENT_MANAGER_ROLECalls claimYield and sets the yield recipientTreasury operations
FREEZE_MANAGER_ROLEFreezes and unfreezes accounts on your tokenCompliance
PAUSER_ROLEPauses and unpauses transfers on your tokenIncident response
VERSION_MANAGER_ROLEPins your token to a specific implementation version, or unpins itEngineering
ASSET_CAP_MANAGER_ROLE (MultiMint only)Sets per-asset caps and manages the replaceAsset caller allowlistTreasury operations
Forced transfers, which move funds out of a frozen account, are a PYUSDx-level control that M0 holds. Restricted addresses are expected to be frozen on PYUSDx and on every custom token, so include a coordination path with M0 in your compliance policy.

3. Deploy on testnet

Call deployYieldToOne(extensionName, params) or deployMultiMint(extensionName, params) on ExtensionFactory. In one transaction, the factory resolves the latest audited implementation from the template's beacon, deploys your proxy at a deterministic address, registers it, and emits ExtensionDeployed. You can deploy from a block explorer without local tooling, or with a script. The deployment guide covers both methods.

extensionName and name are different parameters. extensionName determines your token's address. It must be unique per deployer per network, and reusing it from the same deployer on another network produces the same address there. name and symbol in params are the ERC-20 fields that users see.

4. Test your token

Complete these checks on Ethereum Sepolia before you ask M0 to enable yield:

  1. Wrap testnet PYUSDx into your token with SwapFacility.swapIn and confirm that the amounts match 1:1.
  2. Unwrap with swapOut and confirm that the full PYUSDx amount is returned.
  3. Bridge a test amount with Portal to Arbitrum Sepolia or Monad Testnet. Both are peered with Ethereum Sepolia.
  4. Freeze a test account, confirm that its transfers revert, and unfreeze it.
  5. Pause your token, confirm that transfers revert, and unpause it.
  6. After step 6, call claimYield and confirm that new tokens are minted to your yield recipient.

5. Share the address

Send M0 your deployed token address and the chain it is deployed on.

6. M0 enables yield

M0 registers your token contract as an earner on PYUSDx. From that point, the PYUSDx that your contract holds accrues yield continuously, and your yield manager can claim it with claimYield. Before this step, your token supports wrapping, swapping, and bridging but doesn't accrue yield. Yield enablement is per chain. Repeat steps 5 and 6 for each network you deploy to.

7. Deploy on mainnet

Repeat step 3 on each target chain, followed by steps 5 and 6. On mainnet, every supported chain is peered with every other supported chain, so bridging works on every route as soon as your token is deployed on both ends.

8. Operate your token

  • Yield. Call claimYield on a schedule that fits your treasury operations. Each call mints the accrued yield to your yield recipient. Yield never accrues to holders. To change the recipient, call setYieldRecipient.
  • Compliance. Apply freeze and pause according to your policy. claimYield succeeds while your token is paused, but the minted tokens can't transfer until you unpause.
  • Upgrades. M0 publishes new audited implementations to the template beacon. By default, your token follows the latest version automatically. Call pinVersion to stay on a specific version and unpinVersion to follow the latest version again.
  • Cross-chain. No action is required. If a bridge recipient is frozen on PYUSDx, Portal routes the funds to M0's fallback recipient instead of failing.
  • MultiMint only. Manage backing assets with setAssetCap. A cap of zero disables new deposits of that asset. Existing balances remain unwrappable to PYUSDx.

Responsibilities

M0 operatesYou control
The PYUSDx base token and its issuanceEvery role on your token
SwapFacility and shared liquidityWhen yield is claimed and where it goes
Portal and its bridge adaptersHow freeze and pause are applied under your policy
The audited template implementations and their upgradesWhether your token follows upgrades automatically or pins a version
Yield enablement for your tokenBacking assets and caps (MultiMint only)

You don't manage reserves, run swap infrastructure, or operate a bridge.

Next steps

Deployment guide

Step-by-step instructions for deploying your token on testnet.

Specification

Roles, parameters, errors, and events for every contract.

Contact M0

Start the conversation with the M0 team.

Copyright © M0 Foundation 2026