Transfer event from the system emitter 0xffff…fffe (Arc’s
EIP-7708 implementation), crediting
after a single block confirmation (deterministic finality guarantees no reorgs),
and sweeping funds into a hot wallet.
Prerequisites
Before you begin, ensure that you’ve:- Obtained access to an Arc RPC endpoint (
https://rpc.testnet.arc.io) or WebSocket (wss://rpc.testnet.arc.io) - Installed an HD wallet library for generating deposit addresses (for example,
ethersorviem) - Familiarized yourself with Ethereum JSON-RPC methods and event log filtering
- Set up a database to track processed deposits and prevent double-crediting
Steps
Step 1. Generate deposit addresses
Arc uses standard Ethereum addresses (0x-prefixed, 20 bytes, EIP-55 checksum). Derive deposit addresses using the same HD wallet approach as Ethereum—one unique address per user.Step 2. Subscribe to new blocks
Useeth_subscribe("newHeads") over WebSocket for real-time block
notifications, or poll eth_blockNumber over HTTP as a fallback.
Step 3. Detect incoming transfers with the native USDC Transfer event
Every native USDC movement emits a standard ERC-20Transfer log from the
system address 0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE (Arc’s
EIP-7708 implementation). This single
stream covers plain native sends and the native leg of ERC-20 transfers, with
values in 18 decimals. Filter it to catch every deposit, including native
sends that emit no event on the ERC-20 contract.
Event signature:
0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
Native USDC system emitter: 0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE
Use eth_getLogs to filter for transfers to your deposit addresses:
Step 4. Confirm the deposit
Arc provides deterministic finality—once a transaction is included in a block, it is final with no possibility of reorg. You can safely credit deposits after 1 confirmation.Step 5. Handle decimal conversion
The native systemTransfer event emits values with 18 decimals. Convert to
6-decimal USDC (divide by 10^12) before crediting user balances.
Step 6. Sweep deposits to a hot wallet
Consolidate deposited funds from individual user addresses into your hot wallet. Use EIP-1559 transactions with Arc’s minimum base fee of 20 Gwei.When sweeping using a native USDC send, convert from 6-decimal amounts to
18-decimal
value fields. Alternatively, call the ERC-20 transfer function
on the USDC contract, which accepts 6-decimal amounts directly.Common mistakes
- Filtering the wrong emitter: Plain native USDC sends emit no
Transferon the ERC-20 contract (0x3600…0000). Filter the system emitter (0xffff…fffe) so you do not miss native deposits. - Double-counting: An ERC-20
transfer()logs from both emitters. Filter only the system emitter, and do not reconcileeth_getBalanceagainst Transfer events for the same address. - Decimal mismatch: The system emitter’s values use 18 decimals. Treating them as 6-decimal amounts inflates credited balances by 10^12—divide by 10^12 first.
- Waiting for multiple confirmations: Arc has deterministic finality. Waiting for 6+ confirmations adds unnecessary latency with no security benefit.
- Hardcoded keys: Never embed private keys in source code. Use environment variables or a secrets manager for sweep wallet credentials.
- Meta-transaction sweep of a brand-new address: If you sweep deposit
addresses using a
transferWithAuthorization(EIP-3009) meta-transaction rather than a direct native send, be aware that the relayer’s transaction does not increment the deposit address’s nonce. A meta-transaction that fully drains an address with zero nonce reverts; the post-drain state (zero nonce, zero balance, no code) is blocked by Arc. Initialize the deposit address with any prior transaction to set a non-zero nonce before sweeping using a meta-transaction. A protocol fix is planned for a future release. See Known limitation: draining an empty account.