Multi-Token Support
ServiceEscrowV3 supports multiple ERC-20 tokens for settlement. The seller chooses which token to accept when listing a service, and the buyer pays in that token.
Supported Tokens
Tier 1 β Live
| Token | Decimals | Amoy Address | Mainnet Address |
|---|---|---|---|
| USDC | 6 | 0x9DCE...2529 | 0x3c49...3359 |
| WPOL | 18 | TBD | 0x0d50...1270 |
| USDT | 6 | TBD | 0xc213...8e8F |
| DAI | 18 | TBD | 0x8f3C...A063 |
Tier 2 β Coming
| Token | Decimals | Mainnet Address |
|---|---|---|
| AAVE | 18 | 0xD6DF...C90B |
| WETH | 18 | 0x7ceB...f619 |
| UNI | 18 | 0xb33E...180f |
Tier 3 β Future
| Token | Decimals | Mainnet Address |
|---|---|---|
| WBTC | 8 | 0x1BFD...BfD6 |
Token Registry
The SDK provides a structured token registry:
import {
TOKEN_REGISTRY,
getToken,
getTokensByTier,
isTokenSupported,
POLYGON_AMOY_CHAIN_ID,
POLYGON_MAINNET_CHAIN_ID,
} from '@abbababa/sdk/wallet'
// Look up a specific token
const usdc = getToken(POLYGON_AMOY_CHAIN_ID, 'USDC')
// { symbol: 'USDC', address: '0x9DCE...', decimals: 6, tier: 1 }
// Get all Tier 1 tokens for a chain
const tier1 = getTokensByTier(POLYGON_MAINNET_CHAIN_ID, 1)
// [USDC, WPOL, USDT, DAI]
// Check if a token is supported
isTokenSupported(80002, 'USDC') // true
isTokenSupported(80002, 'WBTC') // false (Tier 3, not yet on Amoy)Token Decimals
Different tokens have different decimal places. The SDK handles this automatically, but if you're calculating amounts manually:
// USDC (6 decimals): $1.00 = 1_000_000
// WPOL (18 decimals): 1.0 WPOL = 1_000_000_000_000_000_000
import { getToken, POLYGON_AMOY_CHAIN_ID } from '@abbababa/sdk/wallet'
const token = getToken(POLYGON_AMOY_CHAIN_ID, 'USDC')
const amount = BigInt(Math.round(10.50 * 10 ** token.decimals))
// 10_500_000 for USDC, 10_500_000_000_000_000_000 for WPOLSeller: Listing in a Specific Token
const service = await seller.listService({
title: 'Data Analysis',
description: '...',
category: 'data',
price: 5.00,
priceUnit: 'per_request',
currency: 'WPOL', // Buyers must pay in WPOL
})Buyer: Paying in the Seller's Token
The checkout response tells the buyer which token to use:
const checkout = await buyer.purchase({
serviceId: service.id,
paymentMethod: 'crypto',
callbackUrl: '...',
})
const pi = checkout.paymentInstructions
console.log(pi.tokenSymbol) // 'WPOL'
console.log(pi.tokenAddress) // '0x0d50...'
console.log(pi.tokenDecimals) // 18
console.log(pi.totalWithFee) // '5050000000000000000' (5.05 WPOL in wei)
// Fund with the correct token
await buyer.fundAndVerify(
checkout.transactionId,
pi.sellerAddress,
BigInt(pi.totalWithFee),
pi.tokenSymbol, // 'WPOL' β SDK looks up the token automatically
)On-Chain Token Whitelist
The V3 contract maintains an admin-managed whitelist. Only whitelisted tokens can be used in escrow. The addToken and removeToken functions are restricted to the contract admin.
Existing escrows survive token removal β if a token is removed from the whitelist, escrows already funded with that token can still be released or refunded. Only new escrows with the removed token are blocked.
Cross-Token Settlement (Phase 2)
Currently, the buyer must pay in the exact token the seller specified. Cross-token settlement (buyer pays in USDC, seller receives WPOL) is planned for Phase 2 with Uniswap V3 integration.