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

# How-to: Configure rate limits and transfer caps

> Set the rate limit, max transfer amount, and rate-limit window on a CCTP for non-USDC TokenManager.

Two outbound throttles apply per token: a rate limit measured over a rolling
window, and a per-transaction maximum transfer amount. Both controls live on the
`TokenManager` for the token. Use this guide to configure them.

CCTP for non-USDC does not cap inbound transfers. Once a transfer is attested,
the destination always delivers the tokens.

<Warning>
  Custom token issuers must configure rate limits and a max transfer amount before
  allowing public transfers. The default rate limit is `0`, which silently blocks
  all outbound transfers. There is no automatic safeguard. Every
  `crossChainTransfer` call reverts until you set a non-zero limit.
</Warning>

## How the throttles behave

* **Rate limit.** Caps the net outbound amount of a token in a sliding window.
  Net outbound is the outbound amount minus the inbound amount received during
  the same window. The default window length is six hours. Setting the rate
  limit to `0` blocks all outbound transfers of the token. After configuration,
  always verify the limit is non-zero before your first `crossChainTransfer`; a
  common mistake is configuring with `rateLimit: 0` and skipping this guide.
* **Max transfer amount.** Caps the size of a single outbound transfer
  transaction. Applies on top of the rate limit to prevent oversize single
  transfers regardless of the headroom remaining in the rate-limit window.

For example, with a rate limit of `1,000,000` over six hours:

* A user transfers `300,000` out and `100,000` in during the window. Net
  outbound consumed is `200,000`. Remaining headroom: `800,000`.
* A second user attempts to transfer `900,000` out in the same window. The
  transfer reverts because net outbound would exceed `1,000,000`.

## Prerequisites

Before you begin, ensure that you've:

* Obtained the `tokenId` for the token you want to configure.
* Confirmed the wallet you'll use holds the operator role for that token's
  `TokenManager`.

## Steps

<Steps>
  <Step title="Discover the TokenManager address">
    Read the local `TokenManager` address from the `CrossChainTokenService`:

    ```typescript TypeScript theme={null}
    const tokenManager: `0x${string}` = await publicClient.readContract({
      address: serviceAddress,
      abi: serviceAbi,
      functionName: "resolveTokenManager",
      args: [tokenId],
    });
    ```
  </Step>

  <Step title="Set the rate limit">
    Call `setRateLimit` with the maximum net outbound amount per window in the
    token's smallest unit.

    ```typescript TypeScript theme={null}
    await walletClient.writeContract({
      address: tokenManager,
      abi: tokenManagerAbi,
      functionName: "setRateLimit",
      args: [5_000_000n * 10n ** 18n],
    });
    ```
  </Step>

  <Step title="Set the max transfer amount">
    Call `setMaxTransferAmount` to cap the size of a single outbound transfer.

    ```typescript TypeScript theme={null}
    await walletClient.writeContract({
      address: tokenManager,
      abi: tokenManagerAbi,
      functionName: "setMaxTransferAmount",
      args: [500_000n * 10n ** 18n],
    });
    ```
  </Step>

  <Step title="Set the rate-limit window (optional)">
    The default window is six hours. To change it, call `setRateLimitWindow` with
    the new window length in seconds.

    ```typescript TypeScript theme={null}
    await walletClient.writeContract({
      address: tokenManager,
      abi: tokenManagerAbi,
      functionName: "setRateLimitWindow",
      args: [3600n], // 1 hour
    });
    ```
  </Step>

  <Step title="Verify the configuration">
    Read the current values from the `TokenManager` and confirm they match what you
    set. If `rateLimit` is still `0`, outbound transfers revert until you call
    `setRateLimit` with a positive amount (in the token's smallest unit).

    ```typescript TypeScript theme={null}
    const [rateLimit, maxTransferAmount] = await Promise.all([
      publicClient.readContract({
        address: tokenManager,
        abi: tokenManagerAbi,
        functionName: "rateLimit",
      }),
      publicClient.readContract({
        address: tokenManager,
        abi: tokenManagerAbi,
        functionName: "maxTransferAmount",
      }),
    ]);

    console.log({ rateLimit, maxTransferAmount });
    if (rateLimit === 0n) {
      throw new Error("rateLimit is 0: outbound transfers are blocked");
    }
    ```
  </Step>
</Steps>
