> ## 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.

# Port a contract to Arc

> How to adapt an existing EVM contract for Arc, where USDC is the native gas token, and verify it against Arc's value transfer rules before you deploy.

export const TryOnArcStudio = () => {
  const [copied, setCopied] = useState(false);
  const [prompt, setPrompt] = useState("");
  useEffect(() => {
    const url = `https://docs.arc.io${window.location.pathname}.md`;
    setPrompt(`Read the guide at ${url}, implement it in a new project, then run it and show me how it works.`);
  }, []);
  const arcStudioUrl = `https://studio.arc.io/app?prompt=${encodeURIComponent(prompt)}`;
  const handleArcStudioClick = () => {
    try {
      if (typeof navigator !== "undefined" && navigator.clipboard && prompt) {
        navigator.clipboard.writeText(prompt).then(() => {
          setCopied(true);
          setTimeout(() => setCopied(false), 4000);
        }, () => {});
      }
    } catch (e) {}
  };
  return <div className="not-prose mb-6">
      <span className="relative inline-flex">
        <a href={arcStudioUrl} target="_blank" rel="noreferrer" onClick={handleArcStudioClick} aria-label="Try it on Arc Studio (opens in new tab)" className="inline-flex items-center gap-2 px-4 py-2 rounded-lg bg-[#3E74BB] border border-[#3E74BB] text-sm font-medium text-white no-underline hover:bg-[#345f9c] hover:border-[#345f9c] transition-all">
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
            <path d="M13 2 3 14h9l-1 8 10-12h-9l1-8z" />
          </svg>
          Try it on Arc Studio
        </a>
        {copied && <span role="status" aria-live="polite" className="absolute left-0 top-full mt-2 w-72 text-sm text-gray-500 dark:text-[#888]">
            Opening Arc Studio — prompt copied to your clipboard in case you need to
            sign in first.
          </span>}
      </span>
    </div>;
};

<TryOnArcStudio />

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](/arc/references/evm-differences).

## Before you start

* Connect your tooling to Arc Testnet. See
  [Connect to Arc](/arc/references/connect-to-arc).
* Have your contract source and its test suite ready.
* Get testnet USDC from the [Circle Faucet](https://faucet.circle.com/) to pay
  for gas and fund test transfers.

## Steps

<Steps>
  <Step title="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`.
  </Step>

  <Step title="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. Gas is
      consumed on a revert. Check `receipt.status === 0` to detect it.
  </Step>

  <Step title="Audit approvals and sweeps">
    Review allowances and any "sweep" logic.

    * **Don't treat an ERC-20 allowance as a complete spending control on a
      contract.** `USDC.approve` bounds `transferFrom` calls only. If the
      contract you're building also exposes functions that send native USDC,
      those paths move USDC regardless of any allowance. Account for all
      transfer paths in your access controls, not just the ERC-20 interface.
    * 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.
  </Step>

  <Step title="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`](/arc/references/contract-addresses#usdc)
      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.

    * Don't alias the EIP-7528 native-asset sentinel that DeFi SDKs use in
      routing tables to Arc's ERC-20 USDC address
      (`0x3600000000000000000000000000000000000000`). Aliasing it conflates
      native value transfers with ERC-20 transfers.

    * Do not bridge or deploy `USDC.e` / `wUSDC` variants. All USDC on Arc
      arrives via CCTP as the native asset. See
      [Bridges](/integrate/infrastructure/bridges) for the bridging rules.
  </Step>

  <Step title="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](/arc/references/evm-differences#selfdestruct) for the exact
    conditions and a worked example.
  </Step>

  <Step title="Audit randomness sources">
    Replace any use of `block.prevrandao` with a VRF or randomness oracle. On
    Arc, `PREVRANDAO` always returns `0`. Contracts that use it for lottery,
    shuffle, or relay logic will always receive `0`.
  </Step>

  <Step title="Test on Arc">
    Use [Arc Foundry](https://github.com/circlefin/arc-foundry)'s
    `arc-anvil --network arc` to start a local Arc node, then run your test
    suite against it with `arc-forge test`. Standard `anvil` doesn't mimic
    Arc-specific behaviors. Test against Arc Testnet directly for hard fork
    transitions or realistic transaction ordering.
  </Step>

  <Step title="Exercise the revert paths">
    Confirm your contract handles a blocklist revert gracefully using the seeded
    blocklisted test address on the [contract
    addresses](/arc/references/contract-addresses#test-addresses-for-restricted-transfer-behavior)
    page. A value transfer to or from it reverts at runtime, including when it is
    the beneficiary of a `SELFDESTRUCT`.
  </Step>
</Steps>

Once these checks pass against Arc Testnet, your contract is ready to deploy.
For the full set of protocol-level rules, see
[EVM differences](/arc/references/evm-differences).
