# Update Rate Limits
Source: https://docs.chain.link/ccip/evm/concepts/cross-chain-token/rate-limits/update-rate-limits
Last Updated: 2025-06-09

> For the complete documentation index, see [llms.txt](/llms.txt).

This page describes updating limits on `TokenPool` v2.0 contracts. **v1.x pools** differences are noted inline.

Once you understand the current configuration and have validated token units and decimals, update inbound and outbound rate limits for the token pool and lane.

Rate limit updates are applied on-chain and take effect immediately. Changes should be made deliberately and reviewed carefully before submission.

> **NOTE: v2.0 only**
>
> Each update also refills the affected bucket to full capacity.

> **NOTE: v1.x pools**
>
> The bucket continues refilling at the **normal rate** after a config change — it does not jump to full capacity.

## Function used to update rate limits

### v2.0 Pools

Rate limits are updated by calling `setRateLimitConfig`:

```solidity
struct RateLimitConfigArgs {
  uint64 remoteChainSelector;
  bool fastFinality;
  RateLimiter.Config outboundRateLimiterConfig;
  RateLimiter.Config inboundRateLimiterConfig;
}

struct Config {
  bool isEnabled;
  uint128 capacity;
  uint128 rate;
}

function setRateLimitConfig(
  RateLimitConfigArgs[] calldata rateLimitConfigArgs
) external;
```

This accepts an array of entries. Each entry updates one bucket pair (outbound + inbound) for one remote chain. A single transaction can update multiple chains and/or both default and fast-finality buckets.

| Field                           | Description                                             |
| ------------------------------- | ------------------------------------------------------- |
| **`remoteChainSelector`**       | The remote chain for this lane                          |
| **`fastFinality`**              | `false` = default bucket; `true` = fast-finality bucket |
| **`outboundRateLimiterConfig`** | Outbound limit for this bucket type                     |
| **`inboundRateLimiterConfig`**  | Inbound limit for this bucket type                      |

When `isEnabled = true`, rate must be ≤ capacity. To disable: `isEnabled = false`, `capacity = 0`, `rate = 0`.

### v1.x pools

v1 pools use `setChainRateLimiterConfig` for a single lane:

```solidity
function setChainRateLimiterConfig(
  uint64 remoteChainSelector,
  RateLimiter.Config outboundConfig,
  RateLimiter.Config inboundConfig
) external;
```

For multiple lanes in one transaction, use the batch variant:

```solidity
function setChainRateLimiterConfigs(
  uint64[] calldata remoteChainSelectors,
  RateLimiter.Config[] calldata outboundConfigs,
  RateLimiter.Config[] calldata inboundConfigs
) external;
```

There is no `fastFinality` parameter. Config tuple shape (`isEnabled`, `capacity`, `rate`) is the same.

## Who can call this function

The pool **owner** or `rateLimitAdmin` (from `getDynamicConfig()` on v2.0; `getRateLimitAdmin()` on v1.x).

## Inbound and outbound configuration guidance

Inbound and outbound limits are configured independently, but they are related across the lane.

Recommended practice:

- set **outbound** on the **source** chain pool
- set **inbound** on the **destination** chain pool
- make destination **inbound \~5–10% higher** than source **outbound**

## Updating default and fast-finality buckets (v2.0 only)

> **NOTE: v1.x pools**
>
> Skip this section — only one inbound/outbound pair exists per remote chain.

If your lane supports fast-finality transfers, update both bucket types when you intend to limit all traffic:

```solidity
RateLimitConfigArgs[] memory args = new RateLimitConfigArgs[](2);

// Default bucket
args[0] = RateLimitConfigArgs({
  remoteChainSelector: REMOTE_SELECTOR,
  fastFinality: false,
  outboundRateLimiterConfig: outboundDefault,
  inboundRateLimiterConfig: inboundDefault
});

// Fast-finality bucket
args[1] = RateLimitConfigArgs({
  remoteChainSelector: REMOTE_SELECTOR,
  fastFinality: true,
  outboundRateLimiterConfig: outboundFF,
  inboundRateLimiterConfig: inboundFF
});

tokenPool.setRateLimitConfig(args);
```

If you only update the default bucket, fast-finality transfers may still use a separate fast-finality bucket or fall back to the default bucket depending on whether the FF bucket is enabled.

## Example interaction (conceptual)

1. Select the token pool on the correct chain
2. Build the version-appropriate call (`setRateLimitConfig` or `setChainRateLimiterConfig`)
3. Supply remote chain selector and outbound/inbound tuples in **local base units**
4. Submit from a wallet with owner or `rateLimitAdmin` permissions

For cross-chain lanes, expect **at least two transactions** — outbound on the source pool and inbound on the destination pool — unless one address controls both pools.

## Verifying before submission

- re-check values are in local base units on this chain
- confirm inbound and outbound are not swapped
- verify the correct remote chain selector
- on v2.0: confirm the `fastFinality` flag targets the intended bucket
- on v2.0: remember the bucket refills to full capacity immediately

## After the update

Once confirmed, the new limits apply immediately. Monitor behavior and re-inspect on-chain state. On v2.0, inspect both default and fast-finality buckets if applicable.

## What this page does not cover

This page does not cover:

- emergency actions such as locking down a lane — see [Emergency Actions](/ccip/evm/concepts/cross-chain-token/rate-limits/emergency-actions)
- worked examples for specific token decimals — see [Common Scenarios](/ccip/evm/concepts/cross-chain-token/rate-limits/common-scenarios)
- tool-specific execution steps for multisig wallets — see [Executing with a Multisig](/ccip/evm/concepts/cross-chain-token/rate-limits/executing-with-a-multisig)

> **CAUTION: Disclaimer**
>
> Chainlink CCIP is an interoperability messaging protocol. Chainlink does not hold or transfer any assets. The
> performance and behaviour of applications using Chainlink CCIP may depend on coding, engineering, configuration, and
> other technical implementation choices made by developers, token issuers, Cross-Chain Verifiers, and other
> participants. Users remain responsible for evaluating, configuring, testing, deploying, operating, and maintaining
> their own applications and integrations, including assessing any applicable operational, security, technical, and
> legal or regulatory risks. Please review the [Chainlink Terms of Service](https://chain.link/terms) which provides
> important information and disclosures. By using Chainlink CCIP, you expressly acknowledge and agree to accept these
> terms. Cross-Chain Verifiers (CCVs) may be operated by third parties. The security, availability, governance, and
> operational profile of a CCV varies depending on the verifier selected. Users are solely responsible for evaluating
> any CCVs used in connection with their applications or integrations and determining whether they are appropriate for
> their intended use case. This code represents an example of using a Chainlink product or service. It is provided "AS
> IS" and "AS AVAILABLE" without warranties of any kind, has not been audited, and may omit checks or error handling.
> Each party intending to use this reference implementation must perform its own audits, security and code review, and
> testing before any production deployment and ensure the operation and performance of such code matches expectations.
> Neither Chainlink Labs, the Chainlink Foundation, nor Chainlink node operators are responsible for outcomes due to
> errors in this example or how it is deployed or operated. Use of the Chainlink Network is subject to the Chainlink
> Foundation Terms of Service, which provides important information and disclosures. By using this code, you acknowledge
> and agree to these terms.