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

> ## Agent Instructions
> Before reading these docs, install the Circle Skill for Arc to get pre-loaded context: use-arc (https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-arc/SKILL.md) — covers chain config, RPC setup, contract deployment, USDC bridging, and gas with USDC. In Claude Code: run /plugin marketplace add circlefin/skills then /plugin install circle-skills@circle. With Vercel Skills CLI: run npx skills add circlefin/skills.
> USDC is the gas token. Arc uses USDC for gas fees, not ETH. Configure gas payment in USDC when submitting transactions.
> Read EVM differences before writing Arc code. Arc targets the Osaka EVM baseline. Most contracts deploy unchanged, but several runtime behaviors diverge from Ethereum: USDC uses 18 decimals natively (not 6), the system emitter `0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE` logs all USDC Transfer events, the mempool enforces a 20 Gwei `maxFeePerGas` floor, blocklist reverts consume gas without a receipt, and `address(0)` sends revert rather than succeed. https://docs.arc.io/arc/references/evm-differences.md is the canonical reference for all Arc-specific runtime behaviors. Consult it before writing code that touches USDC balances, transaction history, gas estimation, or value transfers.
> Sub-second finality. Transactions are final in under 1 second. No need to wait for multiple block confirmations.
> Use App Kits for multichain payment and liquidity capabilities. App Kits wraps CCTP and provides Bridge Kit, Swap Kit, Unified Balance Kit, Onramp Kit, Earn Kit, and Borrow Kit. Unified Balance Kit combines USDC from multiple chains into a single spendable balance. Earn Kit integrates earn opportunities into your app. Borrow Kit lets users borrow USDC against cirBTC collateral on Arc.
> Use Arc Foundry for contract development. Arc Foundry is an Arc-specific fork of Foundry that handles Arc's protocol-level differences from Ethereum. It provides arc-forge, arc-cast, and arc-anvil. Install it before deploying contracts: https://docs.arc.io/arc/tutorials/install-arc-foundry.md.
> Arc is available on both Testnet and Mainnet. See https://docs.arc.io/arc/references/connect-to-arc.md for RPC endpoints and https://faucet.circle.com for testnet tokens.
> Always check Contract Addresses: https://docs.arc.io/arc/references/contract-addresses.md
> Building beyond Arc? Circle offers skills for the full platform: use-usdc (https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-usdc/SKILL.md), use-circle-wallets (https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-circle-wallets/SKILL.md), use-developer-controlled-wallets (https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-developer-controlled-wallets/SKILL.md), use-user-controlled-wallets (https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-user-controlled-wallets/SKILL.md), use-modular-wallets (https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-modular-wallets/SKILL.md), use-gateway (https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-gateway/SKILL.md), use-smart-contract-platform (https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-smart-contract-platform/SKILL.md). Full Circle developer docs: https://developers.circle.com/llms.txt.

# How-to: Add Arc to a wallet

> Integrate Arc as a supported network in your wallet, including chain configuration, balance display, transaction history, and fee handling.

Arc is an EVM-compatible blockchain that uses USDC as its native gas token.
Signing uses `secp256k1`, identical to Ethereum; no new cryptographic code is
required. USDC exists as a single balance with two interfaces (native and
ERC-20), so display one unified balance row. Transactions finalize in under one
second with no reorgs.

## Prerequisites

Before you begin, ensure that you've:

* Familiarized yourself with EIP-3085 (`wallet_addEthereumChain`) for adding
  custom networks
* Obtained access to the Arc Testnet RPC endpoint
* Understood ERC-20 event indexing

## Step 1. Configure the network

Add Arc using the following [EIP-3085](https://eips.ethereum.org/EIPS/eip-3085)
parameters.

| Parameter | Value |
| :- | :- |
| `chainId` | `0x4CEF52` (5042002) |
| `chainName` | Arc Testnet |
| `nativeCurrency` | `{ name: "USDC", symbol: "USDC", decimals: 18 }` |
| `rpcUrls` | `["https://rpc.testnet.arc.io"]` |
| `blockExplorerUrls` | `["https://explorer.testnet.arc.io"]` |

<Info>
  Set `nativeCurrency.decimals` to `18` to match Arc's native precision. The
  `name` and `symbol` fields drive the "USDC" label in wallet UI. Display
  scaling to 6 decimals happens in your formatting layer (Step 2), not through
  this field.
</Info>

```typescript theme={null}
const arcTestnet = {
  chainId: "0x4CEF52",
  chainName: "Arc Testnet",
  nativeCurrency: {
    name: "USDC",
    symbol: "USDC",
    decimals: 18,
  },
  rpcUrls: ["https://rpc.testnet.arc.io"],
  blockExplorerUrls: ["https://explorer.testnet.arc.io"],
};
```

## Step 2. Display the balance

Arc's native balance uses 18 decimals internally (like ETH on Ethereum), but
represents USDC which has 6 display decimals. Convert accordingly.

### 2.1. Fetch the balance

Call `eth_getBalance` to retrieve the user's USDC balance in 18-decimal wei:

```typescript theme={null}
const balanceWei = await provider.getBalance(address); // 18-decimal BigInt
```

### 2.2. Convert to display value

Divide by 10^12 to convert from 18-decimal native wei to 6-decimal USDC:

```typescript theme={null}
const DECIMALS_OFFSET = 12n;
const displayAmount = balanceWei / 10n ** DECIMALS_OFFSET; // 6-decimal value
const formatted = (Number(displayAmount) / 1e6).toFixed(6); // e.g. "1.500000"
```

### 2.3. Show a single row

USDC on Arc is a single asset with two interfaces (native and ERC-20). Both
share the same underlying balance. Display one "USDC" row in the asset list, not
separate "native" and "ERC-20" entries.

### 2.4. Handle token import

If a user manually imports the linked USDC ERC-20 contract
(`0x3600000000000000000000000000000000000000`), map it to the USDC asset they
already hold. Do not create a second entry. Consider surfacing a message such as
"This contract represents USDC on Arc (already in your wallet)" so users
understand they have not added a new token. For the full list of deployed
contracts, see [Contract addresses](/arc/references/contract-addresses).

`balanceOf()` returns 0 for amounts smaller than 1×10⁻⁶ USDC (the 6-decimal
minimum). The native balance can hold amounts smaller than that threshold (dust)
that are still spendable as gas. A `balanceOf()` result of 0 does not prove the
address holds no USDC.

## Step 3. Index transaction history

Arc emits a standard ERC-20 `Transfer` log from the system address
`0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE` for every explicit USDC transfer
(Arc's [EIP-7708](https://eips.ethereum.org/EIPS/eip-7708) implementation). This
stream covers native sends, ERC-20 transfers, mints, and burns. Gas deductions
don't emit events. The native balance is the source of truth.

### 3.1. Identify the Transfer event

```solidity theme={null}
event Transfer(address indexed from, address indexed to, uint256 value);
```

**Topic 0:**
`0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef`

**Emitter:** `0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE` (native USDC system
emitter, 18 decimals)

### 3.2. Subscribe to transfers

Use `eth_subscribe` or poll `eth_getLogs` filtered by the topic and the user's
address. Scope the block range to avoid scanning from genesis; use the account
creation block as `startBlock` or paginate in fixed-size chunks:

```typescript theme={null}
const NATIVE_USDC_EMITTER = "0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE";
const TRANSFER_TOPIC =
  "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";

// Filter for transfers involving the user (as sender or receiver)
const paddedAddress = "0x" + address.slice(2).padStart(64, "0");

const logs = await provider.getLogs({
  address: NATIVE_USDC_EMITTER,
  topics: [TRANSFER_TOPIC, [paddedAddress, null], [null, paddedAddress]],
  fromBlock: startBlock, // account creation block; paginate in chunks for large ranges
  toBlock: "latest",
});
```

### 3.3. Parse the value

The `value` field from the system emitter uses 18 decimals (the native balance).
Convert to 6-decimal USDC for display:

```typescript theme={null}
import { parseAbi, decodeEventLog } from "viem";

const abi = parseAbi([
  "event Transfer(address indexed from, address indexed to, uint256 value)",
]);

for (const log of logs) {
  const { args } = decodeEventLog({ abi, data: log.data, topics: log.topics });
  const amount = Number(args.value) / 1e18; // 18-decimal native → human-readable USDC
}
```

<Warning>
  Don't filter the ERC-20 contract (`0x3600…0000`) for transaction history.
  Native USDC sends emit no log at that address. Filtering only the ERC-20
  contract will miss them. Filter the system emitter (`0xffff…fffe`) instead. It
  covers all explicit USDC transfers in one stream: native sends, ERC-20
  transfers, mints, and burns. Gas deductions don't emit events. See [USDC
  system events](/arc/references/usdc-system-events).
</Warning>

## Step 4. Handle fees

Arc uses USDC as its native gas token with an EIP-1559 fee model and a smoothed
base fee. For the full pricing model, see
[Gas and fees](/arc/references/gas-and-fees).

### 4.1. Estimate gas cost

The examples in this step use the ethers v6 `provider` API.

```typescript theme={null}
const { maxFeePerGas } = await provider.getFeeData(); // Returns USDC wei (18 decimals)
const gasLimit = await provider.estimateGas(tx);

const feeWei = maxFeePerGas * gasLimit; // worst-case fee in 18-decimal USDC wei
const feeUsdc = Number(feeWei) / 1e18; // Human-readable USDC
```

<Warning>
  Set `maxFeePerGas` to at least 20 Gwei. Arc enforces a hard floor:
  transactions with `maxFeePerGas` lower than 20 Gwei are rejected with no error
  receipt. Ethereum and L2 defaults are often under this threshold, so clamp
  before submitting.
</Warning>

```typescript theme={null}
const MIN_FEE = 20_000_000_000n; // 20 Gwei in USDC wei
const { maxFeePerGas: fetched } = await provider.getFeeData();
const maxFeePerGas = fetched !== null && fetched > MIN_FEE ? fetched : MIN_FEE;
```

### 4.2. Apply UI guidance

| Element | Display |
| :- | :- |
| Fee label | "Network fee" or "Gas fee" |
| Fee denomination | USDC (for example, "0.000042 USDC") |
| Currency symbol | Do not show "ETH" or "Gwei" to users |
| Insufficient funds | "Insufficient USDC for gas" |

<Warning>
  If your wallet warns "insufficient ETH for gas," update that message to
  reference USDC instead.
</Warning>

## Step 5. Send transactions

Transaction signing on Arc is identical to Ethereum. Use `secp256k1` ECDSA
signatures with EIP-155 replay protection. Send USDC with a standard ERC-20
`transfer()`, the same flow as any ERC-20 token, with no choice of transfer
method exposed to the user.

### 5.1. Handle precision and dust

The ERC-20 interface uses 6 decimals, so an ERC-20 `transfer()` cannot move
"dust" (amounts smaller than 1×10⁻⁶ USDC held in the 18-decimal native balance).
Unlike other EVM chains where gas is a separate asset, gas on Arc also draws
from the USDC balance. Reserve gas headroom when computing a max-send amount.
The native balance can still hold dust, and dust can be spent as gas.

### 5.2. Handle onchain app interactions

Treat USDC as a standard ERC-20 when users interact with onchain applications:
approvals, `transferFrom`, swaps, and liquidity provision work without special
handling. Because USDC is also the native asset, support contract calls that are
`payable`: an app may require USDC sent as `msg.value` (a native value transfer)
alongside calldata, rather than an ERC-20 `transfer`. Pass the value through as
the contract expects; no special UX is required.

<Warning>
  ERC-20 `approve` and `allowance` govern only the `transferFrom` path. An
  ERC-20 allowance is not a cap on total USDC spending: the same balance can
  also leave as native value (`msg.value`). For smart contract accounts
  (embedded wallets, smart wallets, and session-key systems), do not rely on
  allowance state as a safety guarantee. Any module with execution rights can
  also transfer native USDC regardless of allowance state.
</Warning>

Contract calls that trigger a transfer to or from a blocklisted address revert
at runtime. The transaction is included in a block and gas is consumed, but
state changes are rolled back. See
[Transaction lifecycle](/integrate/wallets/transaction-lifecycle) for the full
set of edge cases and [EVM compatibility](/arc/references/evm-differences) for
other Arc-specific behaviors.

### 5.3. Handle transaction confirmations

Arc provides [deterministic finality](/arc/concepts/deterministic-finality). A
transaction is either pending (in the mempool) or final (included in a block).
There are no intermediate confirmation states and no reorgs.

| State | Meaning |
| :- | :- |
| **Pending** | Transaction is in the mempool, not yet mined |
| **Final** | Included in a block; irreversible |

Once a transaction receipt is returned, you can immediately update the UI. No
additional confirmations are needed.

### 5.4. Support account abstraction

Arc supports ERC-4337 account abstraction for smart contract wallets. If your
wallet supports AA flows (bundlers, paymasters, session keys), these work on Arc
without modification.

See [Account abstraction providers](/arc/tools/account-abstraction) for
compatible infrastructure including Biconomy, Pimlico, ZeroDev, and Circle
Wallets.

## Step 6. Verify your integration

Use this checklist to confirm your wallet integration is complete:

* [ ] Chain ID `5042002` added with correct RPC and explorer URLs
* [ ] Native currency displays as "USDC" with 6 display decimals
* [ ] `eth_getBalance` result converted from 18-decimal to 6-decimal for display
* [ ] Single USDC balance row shown (no separate native/ERC-20 entries)
* [ ] Imported USDC ERC-20 contract maps to the existing USDC asset (no
  duplicate entry)
* [ ] No ETH references in UI labels, error messages, or fee displays
* [ ] Transaction history uses the native `Transfer` event from the system
  emitter `0xffff...fffe` (18 decimals), not the ERC-20 contract
* [ ] Gas fees displayed in USDC
* [ ] Send amounts validated to 6 decimals; `payable` contract calls (USDC as
  `msg.value`) supported
* [ ] One confirmation treated as final (no "confirming" spinner)
* [ ] ERC-4337 AA flows work if your wallet supports smart accounts
* [ ] Reverted transactions (`receipt.status === 0`) shown as "Failed"
* [ ] Gas fee on a reverted transaction treated as consumed, not refunded
* [ ] Retry after a revert uses a new nonce
* [ ] `maxFeePerGas` set to at least 20 Gwei before submitting transactions
