> ## Documentation Index
> Fetch the complete documentation index at: https://docs.startale.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Send a USDSC payment

> Charge a user in Startale USD with one click and verify the transaction on-chain.

Build a checkout button that charges a user in USDSC. Inside the Startale App, the host paymaster sponsors gas, so the user pays only the stablecoin amount. Standalone dapps configure their own paymaster through [`paymasterOptions`](/app-sdk/custom-paymaster) for the same gasless UX.

## What you'll build

A single button that:

1. Connects the user (if not yet connected).
2. Sends a USDSC `transfer` from the smart account to a recipient address.
3. Reads the on-chain receipt to confirm the payment.

## Prerequisites

* A working [connect button](/tutorials/code-walkthroughs/connect-and-sign).
* A recipient address controlled by your app. For testing, your own EOA on Soneium Minato is fine.
* A smart account funded with USDSC. On Minato, request testnet USDSC from the Startale team in [Discord](https://discord.gg/startale); there is no public USDSC faucet today.

## Steps

### 1. Define constants

```ts src/constants.ts theme={null}
import type { Address } from 'viem'

export const USDSC_ADDRESS: Address = '0x3f99231dD03a9F0E7e3421c92B7b90fbe012985a' // Soneium Mainnet
export const USDSC_DECIMALS = 6
export const RECIPIENT: Address = '0x...' // your collection wallet
```

### 2. Build the pay button

```tsx src/PayButton.tsx theme={null}
import { useWriteContract, useWaitForTransactionReceipt } from 'wagmi'
import { erc20Abi, parseUnits } from 'viem'
import { USDSC_ADDRESS, RECIPIENT, USDSC_DECIMALS } from './constants'

export function PayButton({ amount }: { amount: string }) {
  const { writeContractAsync, data: hash, isPending } = useWriteContract()
  const { isLoading, isSuccess } = useWaitForTransactionReceipt({ hash })

  const onClick = async () => {
    await writeContractAsync({
      address: USDSC_ADDRESS,
      abi: erc20Abi,
      functionName: 'transfer',
      args: [RECIPIENT, parseUnits(amount, USDSC_DECIMALS)],
    })
  }

  return (
    <button onClick={onClick} disabled={isPending || isLoading}>
      {isPending ? 'Confirming…' : isLoading ? 'Settling…' : isSuccess ? 'Paid' : `Pay ${amount} USDSC`}
    </button>
  )
}
```

### 3. Render it

```tsx src/App.tsx theme={null}
<PayButton amount="5" />
```

### 4. Verify the receipt

`useWaitForTransactionReceipt` from wagmi resolves once the transaction lands. The `isSuccess` flag flips when the receipt is available with status `'success'`. For a deeper verification, read the recipient's USDSC balance after the receipt:

```tsx theme={null}
import { erc20Abi, formatUnits } from 'viem'
import { useReadContract } from 'wagmi'

const { data: balance } = useReadContract({
  address: USDSC_ADDRESS,
  abi: erc20Abi,
  functionName: 'balanceOf',
  args: [RECIPIENT],
})
```

## Reading decimals dynamically

Hardcoding `6` works today, but if Startale ever upgrades USDSC to use different decimals, the math breaks. The defensive pattern reads them at runtime:

```ts theme={null}
const decimals = await publicClient.readContract({
  address: USDSC_ADDRESS,
  abi: erc20Abi,
  functionName: 'decimals',
})
```

Cache the result; it doesn't change often.

## What you've learned

* How to send an ERC-20 transfer from the user's smart account.
* That the user pays no gas, sponsorship is automatic.
* How to confirm settlement on-chain with viem and wagmi.

## Next

[Build your first Mini App →](/tutorials/code-walkthroughs/build-first-miniapp)
