Prerequisites
Before you begin, ensure you have:- An Arc Testnet RPC endpoint (
https://rpc.testnet.arc.io) - A funded hot wallet with USDC for both transfer amounts and gas fees
- The USDC ERC-20 contract address:
0x3600000000000000000000000000000000000000 - viem installed (
npm install viem)
Steps
Step 1. Validate the destination address
Verify that the withdrawal address is a valid EIP-55 checksum-validated Ethereum address before building the transaction. This prevents sending funds to malformed addresses.- 20 bytes (40 hex characters) with a
0xprefix - Valid per EIP-55 checksum rules
Step 2. Check the blocklist
Arc enforces a blocklist at the protocol level. If the destination address is blocklisted, the transaction reverts at runtime. Check before sending to avoid wasted gas.Step 3. Estimate gas units
Calleth_estimateGas to determine the gas units required for the native USDC
send. The value field is denominated in 18-decimal native wei.
eth_estimateGas returns gas units, not a cost in USDC. To calculate the
cost, multiply by the effective gas price. A native USDC send uses
approximately 21,000 gas units, while an ERC-20 transfer() call uses
approximately 65,000.Step 4. Calculate gas cost
Useeth_gasPrice to get the current suggested gas price, then compute the
total fee.
Step 5. Build the EIP-1559 transaction
Construct a type-2 (EIP-1559) transaction withmaxFeePerGas set to at least 20
Gwei. The fee fields and the value field are all denominated in USDC wei (18
decimals).
Step 6. Confirm inclusion
Arc provides deterministic finality. Once a transaction is included in a block, it is final—no reorgs, no need to wait for additional confirmations.Unlike other blockchains, you do not need to wait for multiple block
confirmations. A single block inclusion is final on Arc.
Step 7. Handle failures
Common failure scenarios and how to address them:Attach memos for compliance
Use the Memo contract to attach metadata (such as internal withdrawal IDs or compliance references) to transfers. The Memo contract wraps the encoded USDC transfer call, routes it through CallFrom so the USDC transfer still sees your hot wallet asmsg.sender, and emits a Memo event for reconciliation.
Memo contract address: 0x5294E9927c3306DcBaDb03fe70b92e01cCede505
For the full viem, ethers, Python, and cURL flow, see
Send USDC with a transaction memo.
Store a deterministic
memoId or encoded memo value that links the onchain
transfer to your internal withdrawal record.See also
- Gas and fees—Fee model details and base fee mechanics
- Deterministic finality—Why single-block confirmation is safe
- Detect deposits—The corresponding deposit detection guide
- Contract addresses—All system contract addresses