Skip to main content
Most Ethereum contracts deploy and run on Arc without changes. The cases that need attention almost all come from one fact: on Arc the native gas token is USDC, and native USDC and the ERC-20 USDC interface are the same asset. This guide walks through the checks to perform on an existing contract and how to verify it on Arc Testnet before you ship. For the protocol-level detail behind each check, see EVM differences.

Before you start

  • Connect your tooling to Arc Testnet. See Connect to Arc.
  • Have your contract source and its test suite ready.
  • Get testnet USDC from the Circle Faucet to pay for gas and fund test transfers.

Steps

1

Audit balance and decimal assumptions

Search your contract for places that read balanceOf or address.balance and for any logic that compares or combines the two.
  • Convert before comparing: the ERC-20 view uses 6 decimals and the native view uses 18 for the same balance.
  • Treat the ERC-20 balanceOf as inexact. It truncates anything below 1×10⁻⁶ USDC, so 0.0000001 USDC reads as 0 and 100.0000001 USDC reads as 100. A balanceOf of 0 does not mean the native balance is 0.
2

Audit value transfers

Find every native send and every path that forwards value.
  • Handle reverts: a native transfer can revert even with a sufficient balance, for example a transfer to the zero address, a transfer to or from a blocklisted address, or any transfer that would burn value.
  • Don’t assume a call to a contract that forwards native value will succeed.
  • Don’t transfer to address(0); the transfer reverts with "Zero address not allowed".
3

Audit approvals and sweeps

Review allowances and any “sweep” logic.
  • If a contract is meant to hold USDC only as an ERC-20 token and not to act on native value, don’t let it sweep its native balance. Native USDC and the ERC-20 USDC interface are the same asset, so a native sweep also moves the users’ ERC-20 USDC balance.
  • Don’t pair “native” against the ERC-20 USDC interface in a liquidity pool. Both legs are the same asset, so the pairing is meaningless.
4

Audit DEX, AMM, and router contracts

If you are porting a DEX, AMM, or router (for example, Uniswap V2, Uniswap V3, or a fork), there is no wrapped native token on Arc and no WUSDC/WETH equivalent is needed.
  • Use the ERC-20 USDC contract directly as the pair token. Arc’s ERC-20 USDC interface at 0x3600000000000000000000000000000000000000 is the canonical token. Treat it like any other ERC-20 in your pool, pair, and router code.
  • Do not deploy a WUSDC wrapper contract. Wrapping the native asset on Arc fragments liquidity and can create user confusion. The ERC-20 interface already exposes transfer, approve, and transferFrom over the same underlying native balance.
  • Replace WETH-style code paths. Remove deposit() / withdraw() wrap-and-unwrap calls, and replace any WETH address constant in your router or periphery contracts with the ERC-20 USDC address above. Routes that accepted raw native value via msg.value can either keep accepting native USDC, or be simplified to ERC-20-only flows since both interfaces move the same balance. Mind the decimals when you mix paths: msg.value is denominated in 18-decimal native USDC, while the ERC-20 USDC interface uses 6 decimals, so convert between them explicitly (1 ERC-20 unit = 1012 wei) instead of assuming a 1:1 numeric value.
  • Do not bridge or deploy USDC.e / wUSDC variants. All USDC on Arc arrives via CCTP as the native asset. See Bridges for the bridging rules.
5

Audit SELFDESTRUCT usage

If your contract uses SELFDESTRUCT, confirm it doesn’t depend on burning, on sending value to a destructed account, or on retaining USDC afterward.
  • A contract’s USDC is its native balance, so self-destructing transfers that USDC to the beneficiary. On other chains the ERC-20 USDC balance would remain in the token contract.
  • Self-destructing to yourself with a balance, to the zero address with a balance, to a blocklisted address, or to an already self-destructed account all revert.
  • A non-zero-value call to a contract after it self-destructs reverts on Arc, even though it succeeds on Ethereum.
See SELFDESTRUCT for the exact conditions and a worked example.
6

Test against an Arc RPC endpoint

Run your test suite against Arc Testnet, not a local EVM simulator. Tools like Foundry’s anvil run a standard EVM and cannot reproduce Arc’s precompiles, EIP-7708 Transfer events, or USDC blocklist enforcement.
7

Exercise the revert paths

Confirm your contract handles a blocklist revert gracefully using the seeded blocklisted test address on the contract addresses page. A value transfer to or from it reverts at runtime, including when it is the beneficiary of a SELFDESTRUCT.
Once these checks pass against Arc Testnet, your contract is ready to deploy. For the full set of protocol-level rules, see EVM differences.