Skip to main content
The AddressUtils library provides functions for converting between EVM addresses and bytes32 format. This enables cross-chain compatibility, allowing EVM chains to interact with non-EVM chains that use different address formats.

Overview

CCTP uses bytes32 for all address fields in messages to maintain compatibility across chains:
  • EVM chains: 20-byte addresses are left-padded with 12 zero bytes
  • Non-EVM chains: Native address formats can be encoded as bytes32
Two versions of the library exist:
  • AddressUtils: Internal functions for use within contracts
  • AddressUtilsExternal: External functions for off-chain or library linking

AddressUtils (Internal)

Source: ~/workspace/source/src/messages/v2/AddressUtils.sol Internal helper functions for address conversion.

toBytes32

Converts an EVM address to bytes32 by left-padding with zeros (alignment-preserving cast). Parameters:
  • addr: The 20-byte EVM address to convert
Returns: The address as bytes32 (left-padded with 12 zero bytes) Implementation:
Example:

toAddress

Converts bytes32 to an EVM address by taking the rightmost 20 bytes (alignment-preserving cast). Parameters:
  • _buf: The bytes32 value to convert
Returns: The rightmost 20 bytes as an EVM address Implementation:
Important Security Consideration:Different bytes32 values can map to the same address due to truncation of the leftmost 12 bytes. If address uniqueness is critical for your use case, you MUST validate that the first 12 bytes are zero-padding.
Example:

AddressUtilsExternal (External)

Source: ~/workspace/source/src/messages/v2/AddressUtilsExternal.sol External versions of the same functions, intended for:
  • Off-chain use (via eth_call)
  • Contract-to-contract library calls
  • Deployment as a separate library contract

addressToBytes32

External equivalent of toBytes32(). Converts address to bytes32. Gas Cost: ~200 gas (external call overhead)

bytes32ToAddress

External equivalent of toAddress(). Converts bytes32 to address.
Same truncation warning applies: different input values can map to the same address. Validate zero-padding if uniqueness is required.
Gas Cost: ~200 gas (external call overhead)

Legacy Message Library Functions

The original Message library also includes conversion functions: Source: ~/workspace/source/src/messages/Message.sol:146-158
These are functionally identical to AddressUtilsExternal but located in the Message library.

Usage Examples

Basic Conversion

Secure Conversion with Validation

Cross-Chain Message Construction

Decoding Received Messages

Off-Chain Address Conversion

Using AddressUtilsExternal via eth_call:

Non-EVM Chain Considerations

When integrating with non-EVM chains:

Solana Example

Solana addresses are 32-byte public keys (already bytes32):

Other Chain Formats

For chains with different address lengths:
  • Shorter addresses: Right-pad with zeros
  • Longer addresses: Hash to 32 bytes (not reversible)
  • Different encoding: Define chain-specific conversion logic
For production cross-chain applications, establish clear address encoding standards for each supported chain in your protocol documentation.

Gas Optimization

Internal functions are more gas-efficient:
Use internal functions within contracts, external functions for off-chain reads.

See Also