FraxNet
Stablecoins as a Service (SaaS)
Overview

Stablecoins as a Service (SaaS)

Stablecoins as a Service (SaaS) are white-label stablecoin instances deployed through FraxNet's BrandedFactory. Each SaaS stablecoin is a fully collateralized ERC-20 token backed 1:1 by frxUSD, with native cross-chain support via LayerZero.

Core Components

ComponentDescription
Branded TokenERC-20 stablecoin with a uniform address across all deployed chains
BrandedCustodianERC-4626 vault holding frxUSD collateral for minting and redeeming the branded token
CrossChainRouterLayerZero-based bridge enabling cross-chain branded token transfers
BrandedFactoryFactory contract that deploys and maps tokens to their custodian and router

How It Works

  1. A branded stablecoin is deployed through the BrandedFactory, which creates the token, custodian, and router contracts using deterministic CREATE2 addresses.
  2. Users mint branded tokens by depositing frxUSD into the BrandedCustodian. The custodian maintains a 1:1 backing ratio.
  3. Users bridge branded tokens cross-chain via the CrossChainRouter, which redeems the token for frxUSD, sends it via LayerZero, and re-mints on the destination chain.
  4. Users redeem branded tokens back to frxUSD at any time through the custodian.

Deployed Chains

Branded stablecoins are deployed across 20 EVM chains with uniform contract addresses:

ChainChain IDLayerZero EID
Ethereum130101
Fraxtal25230255
Arbitrum4216130110
Avalanche4311430106
Base845330184
BSC5630102
Ink5707330339
Katana74747430375
Linea5914430183
Monad14330390
Mode3444330260
Optimism1030111
Plume9886630370
Polygon13730109
Scroll53435230214
Sei132930280
Sonic14630332
Stable98830396
Unichain13030320
World Chain48030319

Example: USSD (US Sonic Dollar)

USSD is the first branded stablecoin deployed through this system.

ContractAddress
USSD Token0x000000000eCcFf26B795F73fb0A70d48da657fEf
Custodian0x54E14489646fD9693ea5071cb5DFeb1F5Afa8f03
CrossChainRouter0x2F30BeF74c1F7572a3ea5e101d1f587287d06C94
BrandedFactory0x63E89638743a409e2389F06A3f778a4570314d7D

Minting Example (Solidity)

IERC20 frxUSD = IERC20(custodian.asset());
uint256 amount = 1000e18;
 
frxUSD.approve(address(custodian), amount);
uint256 brandedTokensReceived = custodian.deposit(amount, msg.sender);

Minting Example (TypeScript)

import { parseUnits } from "viem";
 
const custodianAddress = "0x54E14489646fD9693ea5071cb5DFeb1F5Afa8f03";
const frxUsdAddress = "0x..."; // frxUSD on the target chain
const amount = parseUnits("1000", 18);
 
// Approve custodian to spend frxUSD
await walletClient.writeContract({
  address: frxUsdAddress,
  abi: erc20Abi,
  functionName: "approve",
  args: [custodianAddress, amount],
});
 
// Deposit frxUSD to mint branded tokens
const brandedTokensReceived = await walletClient.writeContract({
  address: custodianAddress,
  abi: custodianAbi,
  functionName: "deposit",
  args: [amount, userAddress],
});

Redeeming Example (Solidity)

uint256 brandedAmount = 500e18;
uint256 frxUsdReceived = custodian.redeem(brandedAmount, msg.sender, msg.sender);

Bridging Example (Solidity)

uint32 dstEid = 30101; // Ethereum
address recipient = msg.sender;
uint256 amount = 100e18;
 
IERC20(brandedToken).approve(address(router), amount);
uint256 nativeFee = router.quote(dstEid, recipient, amount);
router.send{value: nativeFee}(dstEid, recipient, amount);

Bridging Example (TypeScript)

import { parseUnits } from "viem";
 
const routerAddress = "0x2F30BeF74c1F7572a3ea5e101d1f587287d06C94";
const brandedTokenAddress = "0x000000000eCcFf26B795F73fb0A70d48da657fEf";
const dstEid = 30101; // Ethereum
const amount = parseUnits("100", 18);
 
// Approve router to spend branded tokens
await walletClient.writeContract({
  address: brandedTokenAddress,
  abi: erc20Abi,
  functionName: "approve",
  args: [routerAddress, amount],
});
 
// Quote LayerZero fee
const nativeFee = await publicClient.readContract({
  address: routerAddress,
  abi: routerAbi,
  functionName: "quote",
  args: [dstEid, userAddress, amount],
});
 
// Send cross-chain
await walletClient.writeContract({
  address: routerAddress,
  abi: routerAbi,
  functionName: "send",
  args: [dstEid, userAddress, amount],
  value: nativeFee,
});

Factory Lookup

To look up the custodian and router for any branded token:

(address custodian, address router, ) = BrandedFactory(
  0x63E89638743a409e2389F06A3f778a4570314d7D
).brandedTokenToUtils(brandedTokenAddress);