CCIP v2.0.0 ERC20LockBox API Reference

Summary

ERC20LockBox is a single-token liquidity vault used by lock/release style token pools.

It:

  • Holds custody of exactly one ERC20 token.
  • Restricts deposit and withdrawal operations to an allowlist ([AuthorizedCallers](/ccip/evm/api-reference/v2.0.0/authorized-callers)).
  • Emits standardized events for liquidity accounting.
  • Allows full-balance withdrawals via type(uint256).max.

Contract

chains/evm/contracts/pools/ERC20LockBox.sol


Import

import {ERC20LockBox} from "chainlink-ccip/chains/evm/contracts/pools/ERC20LockBox.sol";

Inheritance

  • ILockBox
  • ITypeAndVersion
  • AuthorizedCallers

typeAndVersion

string public constant override typeAndVersion =
  "ERC20LockBox 2.0.0-dev";

State

Constants

None declared.


Immutables

IERC20 internal immutable i_token;

The only token supported by this lockbox.


Storage

No additional storage declared.

Allowlist state is inherited from AuthorizedCallers.


Constructor

constructor(address token)
  AuthorizedCallers(new address)

Behavior:

  • Reverts ZeroAddressNotAllowed() if token == address(0).
  • Sets i_token = IERC20(token).

The allowlist is initialized empty and must be configured via applyAuthorizedCallerUpdates.


External API

deposit

function deposit(
  address token,
  uint64 remoteChainSelector,
  uint256 amount
) external

Validations:

  • Reverts TokenAmountCannotBeZero() if amount == 0.
  • Reverts UnsupportedToken(token) if token != address(i_token).
  • Reverts UnauthorizedCaller(msg.sender) via _validateCaller() if caller not allowlisted.

Effects:

  • safeTransferFrom(msg.sender, address(this), amount)
  • Emits Deposit(token, msg.sender, amount)

Note:

  • remoteChainSelector is required by the ILockBox interface but unused.

withdraw

function withdraw(
  address token,
  uint64 remoteChainSelector,
  uint256 amount,
  address recipient
) external

Validations:

  • Reverts TokenAmountCannotBeZero() if amount == 0.
  • Reverts UnsupportedToken(token) if token != address(i_token).
  • Reverts RecipientCannotBeZeroAddress() if recipient == address(0).
  • Reverts UnauthorizedCaller(msg.sender) via _validateCaller() if caller not allowlisted.

Special case:

  • If amount == type(uint256).max, resolves to full balance.

Balance check:

if (amountResolved > i_token.balanceOf(address(this))) {
  revert InsufficientBalance(amountResolved, balance);
}

Effects:

  • safeTransfer(recipient, amountResolved)
  • Emits Withdrawal(token, recipient, amountResolved)

isTokenSupported

function isTokenSupported(address token)
  external
  view
  returns (bool)

Returns token == address(i_token).


Events

event Deposit(address token, address depositor, uint256 amount);
event Withdrawal(address token, address recipient, uint256 amount);

Errors

error InsufficientBalance(uint256 requested, uint256 available);
error TokenAmountCannotBeZero();
error RecipientCannotBeZeroAddress();
error UnsupportedToken(address token);

Inherited from AuthorizedCallers:

error UnauthorizedCaller(address caller);
error ZeroAddressNotAllowed();

Internal Functions

_validateDepositWithdraw

function _validateDepositWithdraw(
  address token,
  uint256 amount
) internal view

Shared validation logic for deposit/withdraw.


Security model

  • Only allowlisted callers may move funds.
  • Exactly one token supported.
  • Full-balance sentinel (type(uint256).max) simplifies migrations.
  • Does not interpret remoteChainSelector; per-lane isolation must be handled at pool layer.
  • Lockbox does not enforce per-chain liquidity accounting.

Get the latest Chainlink content straight to your inbox.