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
ILockBoxITypeAndVersionAuthorizedCallers
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()iftoken == 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()ifamount == 0. - Reverts
UnsupportedToken(token)iftoken != 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:
remoteChainSelectoris required by theILockBoxinterface but unused.
withdraw
function withdraw(
address token,
uint64 remoteChainSelector,
uint256 amount,
address recipient
) external
Validations:
- Reverts
TokenAmountCannotBeZero()ifamount == 0. - Reverts
UnsupportedToken(token)iftoken != address(i_token). - Reverts
RecipientCannotBeZeroAddress()ifrecipient == 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.