Skip to main content
For a step-by-step indexing walkthrough, see Index Arc events. For the conceptual model behind USDC’s native and ERC-20 interfaces, see Stablecoin native model.

Two event streams

USDC movements surface as logs from two distinct emitters. The native system emitter logs a Transfer for every USDC movement—native sends and ERC-20 transfers alike—so it is a single universal record of balance changes at 18-decimal precision. Filter by emitter address to tell the two streams apart.
A single ERC-20 transfer() emits two logs: the ERC-20 contract’s own Transfer (6 decimals, from 0x3600000000000000000000000000000000000000) and the native system Transfer (18 decimals, from 0xfffffffffffffffffffffffffffffffffffffffe). A plain native send emits only the system log. Match on the emitter address so you do not count the same movement twice, and never mix the 6-decimal and 18-decimal values.

Native USDC system events (EIP-7708)

Native USDC movements emit a standard ERC-20 Transfer log from a designated system address. This is Arc’s implementation of EIP-7708, an Amsterdam-track Ethereum proposal that Arc ships ahead of upstream. Native movements can be indexed the same way as ERC-20 transfers. (For the legacy events that testnet emitted before this behavior was activated, see Historical events.) The log covers native value transfers (CALL), contract creation with an endowment (CREATE), SELFDESTRUCT balance transfers, and the precompile-driven mint, burn, and transfer operations that back the ERC-20 USDC interface. Mint and burn are expressed as transfers involving the zero address:
  • Mint: Transfer(0x0, recipient, amount)
  • Burn: Transfer(from, 0x0, amount)
The following rules apply to the system Transfer log:
  • The native Transfer log is emitted first, before any other logs in the transaction.
  • Zero-value transfers emit no log.
  • Self-transfers (from == to) emit no log.
  • A native value transfer (CALL, CREATE, or SELFDESTRUCT) to or from the zero address reverts with "Zero address not allowed". Mint and burn are the only paths that produce a Transfer involving 0x0, and they go through the precompile.

ERC-20 USDC contract events

The NativeFiatToken contract at 0x3600000000000000000000000000000000000000 emits its own standard ERC-20 Transfer log (6 decimals) for activity on the ERC-20 interface. As on any ERC-20 token, mint and burn surface here as a Transfer to and from the zero address. These events are independent of the native system events: an ERC-20 transfer() produces a log from both emitters.

Historical events (before Zero5)

On testnet, before the Zero5 hard fork activated, native USDC movements emitted custom events from the NativeCoinAuthority precompile at 0x1800000000000000000000000000000000000000 (18 decimals) instead of the standard Transfer log. These events are no longer emitted after activation. Mainnet has used the EIP-7708 Transfer log since genesis, so this only affects indexers that backfill pre-activation testnet history. If you backfill history across the hard fork boundary, read NativeCoin* from 0x1800000000000000000000000000000000000000 for blocks before activation and Transfer from 0xfffffffffffffffffffffffffffffffffffffffe at and after activation. For the exact activation time and node version requirements, see the canonical arc-node CHANGELOG.md and BREAKING_CHANGES.md, and the Run an Arc node tutorial.

Out of scope: gas fees and block rewards

Gas fees and block rewards are not emitted as Transfer events and are unaffected by EIP-7708:
  • Gas fees are derived from the receipt (gasUsed × effectiveGasPrice).
  • Block rewards are attributed via block.miner.

See also