Payment Tokens
The public v0.7 paymaster accepts USDC, USD₮0, or USDG for reimbursement. USDC is the default; select another token explicitly by symbol, alias, or address.
The EIP-7702 v0.8 deployment currently accepts USDC only and supports an
atomic EIP-2612 permit. Always use the selected deployment’s tokens list as
the authority for enabled tokens.
const { quote } = await paymasterClient.quoteUserOperation({
userOperation,
token: "USDG",
maxTokenCost: 100_000n,
});The Viem adapter accepts the same selection through paymasterContext:
paymasterContext: {
token: "USDT0", // Alias for the onchain USD₮0 symbol
maxTokenCost: 100_000n,
}maxTokenCost and allowances are denominated in the selected token’s smallest
unit. All three current tokens use six decimals. Read decimals from deployment
metadata rather than assuming that future tokens will do the same.
Canonical Ink addresses
| Symbol | Address | Decimals |
|---|---|---|
| USDC | 0x2D270e6886d130D724215A266106e6832161EAEd | 6 |
| USD₮0 | 0x0200C29006150606B650577BBE7B6248F58470c1 | 6 |
| USDG | 0xe343167631d89B6Ffc58B88d6b7fB0228795491D | 6 |
Token presence in INK_PAYMENT_TOKENS identifies its canonical address. The
active deployment’s tokens list remains the authority for what the live
paymaster has enabled.
Approvals are per token in prepaid mode
Each token has a separate ERC-20 allowance. Before requesting a quote, the
smart account must execute approve(paymaster, finiteAllowance) on the token it
will use for reimbursement.
import {
encodePublicPaymasterApproval,
getPublicPaymasterAccountState,
INK_PAYMENT_TOKENS,
INK_PUBLIC_PAYMASTER,
} from "@hellomoon/ink-paymaster";
const state = await getPublicPaymasterAccountState(
publicClient,
smartAccount.address,
INK_PUBLIC_PAYMASTER,
"USDG",
);
const approvalCall = {
to: INK_PAYMENT_TOKENS.USDG.address,
value: 0n,
data: encodePublicPaymasterApproval(10_000_000n),
};The public paymaster does not pay for this approval. Approve from the smart account using an owner-paid UserOperation.
The v0.8 USDC deployment also supports permit mode. In permit mode, the EOA signs a bounded EIP-2612 authorization and includes it with the quote request. The paymaster applies the permit and collects its precharge during the same UserOperation, so no prior allowance or owner-paid ETH transaction is required. See EIP-7702 for the complete flow.
Charging and refunds
The paymaster precharges a bounded amount during validation. After execution, it records the final reimbursement as treasury accrual and makes unused precharge available as pull-based refund credit owned by the smart account.
Read refundCredit with getPublicPaymasterAccountState. Applications may
claim it through the smart account using encodePublicPaymasterRefundClaim.
Refunds and allowances are independent for each token.
import {
encodePublicPaymasterRefundClaim,
INK_PUBLIC_PAYMASTER,
} from "@hellomoon/ink-paymaster";
const claim = encodePublicPaymasterRefundClaim(recipient);
const encodedCall = await smartAccount.encodeCalls([
{
to: INK_PUBLIC_PAYMASTER.paymaster,
value: 0n,
data: claim,
},
]);The smart account that owns the credit must execute the claim. The recipient may be a different address.