Docs
How it works

Flow limits

Cap how much of a token can move into or out of a chain in each 6-hour window.

A flow limit caps the net amount of a token that can move into or out of a chain in each 6-hour window. It limits the damage if a chain, or the token's contract on it, is compromised: an attacker can move at most one limit's worth before someone reacts.

Each token has its own flow limit on each chain, kept by ITS on that chain: on EVM chains and Solana in the token's token manager (FlowLimit on EVM), on Sui and Stellar in ITS itself.

How it's applied

  • Windows. Time is split into fixed 6-hour windows of the chain's clock. Amounts reset at the start of each window.
  • Net flow. ITS adds up the amounts sent out of the chain and received into it in the current window. A transfer fails if the difference between the two would exceed the limit. Transfers in opposite directions cancel out.
  • Where it fails. An outgoing transfer over the limit fails on the source chain. An incoming one fails when it's executed on the destination chain: the message stays approved, and can be executed again in a later window.

Amounts are in the token's smallest unit on that chain. By default, a token has no flow limit. How "no limit" is written differs by chain:

ChainNo limitA limit of 0
EVM0, the defaultMeans no limit
SolanaNone, the defaultBlocks every transfer
Suinone, the defaultBlocks every transfer
StellarNone, the defaultBlocks every transfer

Who manages it

On every chain, ITS's operator, an account Axelar controls, can set the flow limit of a token. Axelar's operations tooling uses this for emergencies: it freezes a token on a chain by setting a limit that blocks its transfers, and lifts the limit afterwards.

Who else can set it depends on the chain:

ChainAlso set byCan Axelar's operator be removed?
EVMThe token manager's operator and the flow limiters it addsYes, see below
SolanaThe token manager's operator and its flow limitersNo
SuiThe token's operatorNo
StellarFlow limiters that ITS's operator approves for the tokenNo

The integration pages show the calls on each chain. The ITS Hub has no flow limits of its own.

On EVM chains

A flow limiter of the token manager calls:

function setFlowLimit(uint256 flowLimit_) external; // on the token manager

To read the limit and the current window's flows:

function flowLimit() external view returns (uint256);
function flowOutAmount() external view returns (uint256); // sent out in the current window
function flowInAmount() external view returns (uint256); // received in the current window

The token manager's address is deployedTokenManager(tokenId) on ITS. A single transfer larger than the limit also fails.

ITS is a flow limiter of every token manager when it's deployed, and ITS's operator sets limits through it with setFlowLimits on ITS. Axelar freezes a token by setting the limit to 1, and lifts the freeze by setting it back to 0.

The token manager's operator is also a flow limiter. For an interchain token, the operator is the minter you deployed it with; for a custom token, the operator you passed when linking it. A canonical token has no operator, so only ITS can set its limits. The operator decides who keeps the role:

You wantDo
Axelar to be able to freeze the token in an emergencyNothing: ITS is a flow limiter from the start
To set limits yourself as wellKeep an operator, which is also a flow limiter (for an interchain token, deploy it with a minter)
To be the only one who can set limitsAs operator, call removeFlowLimiter with ITS's address
No one to be able to change themRemove ITS as above, remove yourself with removeFlowLimiter, then give up the operator role with transferOperatorship(address(0))

Set the limit you want before removing yourself: without a flow limiter, it can't be changed. Removing ITS also means Axelar can't freeze the token on that chain in an emergency.

On this page