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

# Zap in from USDC

> Zap.zapSupply swaps an allowlisted asset to USDG and deposits sUSDG to the caller.

The core never sees USDC. `Zap` swaps along the registry route, deposits into `USDGPool`, and returns leftovers.

Addresses: [Addresses](/resources/addresses). ABI: [`Zap.json`](/abis/Zap.json). Confirm the USDC route with `RiskRegistry.zapRoute(usdc)` before you send.

<Steps>
  <Step title="Check the route">
    `zapRoute(token).allowed` must be true. `route[0] == token` and `route[last] == USDG`. Slippage is `maxSlippageBps` from the registry, not from the caller.

    ```typescript theme={"system"}
    import { parseAbi } from "viem"
    import { addresses } from "./addresses" // Addresses, testnet

    const registryAbi = parseAbi([
      "function zapRoute(address token) view returns (address[] route, uint16 maxSlippageBps, bool allowed)",
    ])

    const usdc = "0x0000000000000000000000000000000000000000" // fill from Addresses / registry, not from this line
    const route = await client.readContract({
      address: addresses.registry,
      abi: registryAbi,
      functionName: "zapRoute",
      args: [usdc],
    })
    if (!route.allowed) throw new Error("USDC is not allowlisted")
    ```
  </Step>

  <Step title="Approve and zapSupply">
    <CodeGroup>
      ```typescript theme={"system"}
      const zapAbi = parseAbi([
        "function zapSupply(address token, uint256 amountIn) payable",
      ])
      const erc20Abi = parseAbi([
        "function approve(address spender, uint256 amount) returns (bool)",
      ])

      const amountIn = 100n * 10n ** 6n // mainnet USDC is 6 decimals; testnet mocks may be 18

      await wallet.writeContract({
        address: usdc,
        abi: erc20Abi,
        functionName: "approve",
        args: [addresses.zap, amountIn],
      })

      await wallet.writeContract({
        address: addresses.zap,
        abi: zapAbi,
        functionName: "zapSupply",
        args: [usdc, amountIn],
      })
      ```

      ```solidity theme={"system"}
      interface IZap {
          function zapSupply(address token, uint256 amountIn) external payable;
          function zapRepay(uint16 bookId, address token, uint256 amountIn) external payable;
      }

      // IERC20(usdc).approve(zap, amountIn);
      // IZap(zap).zapSupply(usdc, amountIn);
      ```
    </CodeGroup>
  </Step>

  <Step title="ETH path">
    Send `msg.value`. `_resolveIn` wraps that ETH to `WETH` and ignores the token argument. Passing `token = address(0)` with no value reverts `ZeroAddress`. Outbound `borrowTo` / `zapWithdraw` accept `address(0)` or the WETH address to pay ETH.
  </Step>
</Steps>

## Related calls

| Intent                        | Function                                              |
| ----------------------------- | ----------------------------------------------------- |
| Repay a book from USDC        | `zapRepay(bookId, usdc, amountIn)` (always live)      |
| Borrow USDG and take USDC out | `borrowTo(bookId, usdgAmount, usdc)` (LIVE, operator) |
| Exit sUSDG to USDC            | `zapWithdraw(usdgAmount, usdc)`                       |

## What can go wrong

* `InvalidRoute` if the asset is not allowlisted or the path does not end in USDG.
* Slippage revert inside `SwapLib` when the pool moves more than `maxSlippageBps`.
* Decimal mixup: testnet faucet USDG is 18. Mainnet USDG is 6. USDC is usually 6. Read `decimals()`.
* `zapSupply` does not bypass pause on USDG withdraw, but depositing is live. `borrowTo` still needs LIVE and an operator grant.
* The Zap must hold nothing after the call. If a sweep ETH transfer fails, the tx reverts `ZeroAmount`.

The core never sees USDC. Zap swaps along the registry route, deposits into USDGPool, and returns leftovers. Confirm `RiskRegistry.zapRoute(usdc).allowed` before you send.

Slippage is `maxSlippageBps` from the registry, not from the caller. That is intentional. A frontend cannot widen slippage past governance.

ETH in: send `msg.value`. `_resolveIn` wraps to WETH and ignores the token argument. Passing `token = address(0)` with no value reverts `ZeroAddress`. ETH out: `borrowTo` and `zapWithdraw` accept `address(0)` or WETH.

## Functions

| Function                              | Direction                               | Needs LIVE                          | Needs operator grant |
| ------------------------------------- | --------------------------------------- | ----------------------------------- | -------------------- |
| `zapSupply(token, amountIn)`          | USDC, USDT, or ETH in, sUSDG out        | No                                  | No                   |
| `zapRepay(bookId, token, amountIn)`   | USDC, USDT, or ETH in, debt down        | No                                  | No                   |
| `borrowTo(bookId, usdgAmount, token)` | Borrow USDG, receive USDC, USDT, or ETH | Yes                                 | Yes                  |
| `zapWithdraw(usdgAmount, token)`      | sUSDG in, USDC, USDT, or ETH out        | No, but USDG withdraw can be paused | No                   |

Next: [Repay and withdraw](/developers/positions/repay-and-withdraw), [Reserve and fees](/concepts/reserve-and-fees).
