Skip to content
290 changes: 290 additions & 0 deletions ERCS/erc-8088.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,290 @@
---

Check failure on line 1 in ERCS/erc-8088.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

preamble is missing header(s): `eip`

error[preamble-req]: preamble is missing header(s): `eip` --> ERCS/erc-8088.md | | = help: see https://ethereum.github.io/eipw/preamble-req/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
---
---
eip: 8088

Assigning next sequential EIP/ERC/RIP number.
Numbers are assigned by editors & associates.

Please also update the filename.

title: Cross-Chain Tracking
description: This EIP standardizes a simplified set of cross-chain bridge transaction event formats, aiming to provide fundamental traceability standard for cross-chain transactions.

Check failure on line 3 in ERCS/erc-8088.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

preamble header `description` should not contain `standard` (or similar words.)

error[preamble-re-description]: preamble header `description` should not contain `standard` (or similar words.) --> ERCS/erc-8088.md:3:13 | 3 | ...on: This EIP standardizes a simplified set of cross-chain bridge transaction event formats, aiming to provide fundamental traceability standard for cross-chain transactions. | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ prohibited pattern was matched | = info: the pattern in question: `(?i)standar\w*\b` = help: see https://ethereum.github.io/eipw/preamble-re-description/

Check failure on line 3 in ERCS/erc-8088.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

preamble header `description` value is too long (max 140)

error[preamble-len-description]: preamble header `description` value is too long (max 140) --> ERCS/erc-8088.md:3:13 | 3 | ...on: This EIP standardizes a simplified set of cross-chain bridge transaction event formats, aiming to provide fundamental traceability standard for cross-chain transactions. | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ too long | = help: see https://ethereum.github.io/eipw/preamble-len-description/
author: Shulei(@baishuo13)<[email protected]>, Jeff Fei (@77eff) <[email protected]>, Kenny Kung (@kennyk10) <[email protected]>

Check failure on line 4 in ERCS/erc-8088.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

authors in the preamble must match the expected format

error[preamble-author]: authors in the preamble must match the expected format --> ERCS/erc-8088.md:4:8 | 4 | author: Shulei(@baishuo13)<[email protected]>, Jeff Fei (@77eff) <[email protected]>, Kenny Kung (@kennyk10) <kenny.kung@a... | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unrecognized author | = help: Try `Random J. User (@username) <[email protected]>` for an author with a GitHub username plus email. = help: Try `Random J. User (@username)` for an author with a GitHub username. = help: Try `Random J. User <[email protected]>` for an author with an email. = help: Try `Random J. User` for an author without contact information. = help: see https://ethereum.github.io/eipw/preamble-author/
discussions-to: https://ethereum-magicians.org/t/erc-8088-cross-chain-tracking-standard/26677
status: Draft
type: Standards Track
category: ERC
created: 2025-11-17
requires: EIP-155,EIP-172

Check failure on line 10 in ERCS/erc-8088.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

preamble header `requires` items must be unsigned integers

error[preamble-uint-requires]: preamble header `requires` items must be unsigned integers --> ERCS/erc-8088.md:10:10 | 10 | requires: EIP-155,EIP-172 | ^^^^^^^^ not a non-negative integer | ^^^^^^^ not a non-negative integer | = help: see https://ethereum.github.io/eipw/preamble-uint-requires/

Check failure on line 10 in ERCS/erc-8088.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

preamble header list items must begin with a space

error[preamble-list-requires]: preamble header list items must begin with a space --> ERCS/erc-8088.md:10:18 | 10 | requires: EIP-155,EIP-172 | ^ missing space | = help: see https://ethereum.github.io/eipw/preamble-list-requires/
---



## Abstract

By standardizing cross-chain bridge transaction event, it establishes a basis for regulatory compliance and user verification. This EIP contributes to improved security monitoring, and forensic analysis of cross-chain fund flows.

## Motivation

The cross-chain ecosystem is currently experiencing rapid expansion, driven by a continuous increase in the number of blockchains and cross-chain bridge assets. However, as each bridge implementation typically uses its own proprietary event formats, the transaction tracking mechanism has become increasingly fragmented. This creates opportunities for illicit funds to be laundered through these cross-chain services which poses significant challenges to the cross-chain ecosystem in terms of security and compliance, and incident response capabilities, directly impacting users, project teams, and regulatory bodies.
The specific problems include:
- Lack of Standardized Event Logging: The bridge contract on the destination chain may not record transaction events at all, or different bridges use incompatible message structures.
- Absence of a Universal Identifier: The lack of a unified cross-chain transaction identifier, coupled with differences in event field names and formats, results in the separation of transaction records between the source and destination chains, making them impossible to correlate.

## Specification

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

### Standard Event Formats

```solidity
event CrossChainTransactionInitiated(
bytes32 indexed messageId, // Cross-chain message unique identifier
address indexed destChainBridge, // Bridge contract address emitting CrossChainTransferCompleted event on destination chain
uint256 indexed destChainId, // Destination chain ID
bytes messageBody,
uint256 nonce
);
```

- The `CrossChainTransactionInitiatedevent` **MUST** be emitted when a cross-chain transaction is initiated on the source chain, generating a cross-chain transaction event.
- This event is monitored by existing off-chain indexers, as long as the event is supported. This event field can be added on top of existing bridges as an extended event in the source chain or as a standard event field of a bridge event.
- The `messageBody` field is protocol-specific and allowed to be customized while it **SHOULD** contain necessary cross-chain transaction data to maintain traceability.
- The `indexed` keyward is used to declare parameters in an event and indicate that the value of that parameter **SHOULD** be indexed.

```solidity
event CrossChainMessageCompleted(
bytes32 indexed messageId,
bytes32 indexed messageBodyHash // Used to verify if the messageBody is consistent.
)
```

- The `CrossChainTransferCompleted` event **MUST** be emitted when a cross-chain transaction is successfully completed on the target chain.
- The definiation of `messageBodyHash` is `messageBodyHash = keccak256(messageBody)`, which is used to verify the integrity of cross-chain message.

### Cross-Chain Message ID Generation

The messageId in cross-chain events is encoded as follow:
- `messageId = keccak256(sourceChainId || sourceChainBridge || destChainId || destChainBridge || nonce)`

It **SHALL** be generated using this structure to ensure global uniqueness, preventing replay attack, where:
- All fields are deterministically encoded
- The `nonce` is a strictly increasing value per sender or channel on the source chain.

```solidity
function generateCrossChainMessageId(
uint256 sourceChainId, // Source chain ID
address sourceChainBridge, // Source chain bridge contract address
uint256 destChainId, // Destination chain ID
address destChainBridge, // Destination chain bridge contract address
uint256 nonce // Message sequence number
) public pure returns (bytes32) {
return keccak256(abi.encodePacked(
sourceChainId,
sourceChainBridge,
destChainId,
destChainBridge,
nonce
));
}
```

### Implementation Requirements

- Bridge contracts **MAY** implement these events as an extension to existing backwards compatibility while still achieving cross-chain transaction tracking.
- The content format of the `messageBody` field is protocol-specific but **SHOULD** contain necessary cross-chain transaction data.
- The event **MUST** be triggered at the appropriate stage of the transaction lifecycle, and all fields in the event **MUST** be valid. The `CrossChainTransactionInitiated` event **SHOULD** be sent when the message is sent on the original chain, and the ```CrossChainTransferCompleted``` event **SHOULD** be sent when funds are withdrawn from the target chain.

## Rationale

**Minimal Design Approac**:The standard adopts a minimal design philosophy which include only necessary events to avoid over-standardization while providing sufficient tracking capabilities.
**Implementation Flexibility**:The messageBody field allows individual bridge protocols to include protocol-specific execution data while maintaining event structure consistency.
- ```messageBody = (messageBodyDomain || sourceTokenSender || destTokenReceiver || sourceTokenAddress || destTokenAddress || amount)```
> e.g:messageBodyDomain = "TOKEN_BRIDGE",sourceTokenSender = "Source chain token sender address", destTokenReceiver = "Destination chain token receiver address",sourceTokenAddress = "Source chain token address",destTokenAddress = "Destination chain token address" ,amount = "Transfer amount".

Cross-chain message ID **SHOULD** be generated using the following method to ensure uniqueness:
```solidity
function generateCrossChainMessageHash(
address messageBodyDomain, // Type identifier for message body decoding
address sourceTokenSender, // Source chain token sender address
address destTokenReceiver, // Destination chain token receiver address
address sourceTokenAddress, // Source chain token address
address destTokenAddress // Destination chain token address
uint256 amount // Transfer amount
) public pure returns (bytes32) {
return keccak256(abi.encodePacked(
messageBodyDomain,
sourceTokenSender,
destTokenReceiver,
sourceTokenAddress,
destTokenAddress,
amount
));
}
```
**Guarantee Uniqueness**:The messageId generation algorithm combines multiple chain-specific and transaction-specific parameters to ensure sufficient entropy, preventing overlapping with different bridge implementations.
**Event Indexing**:Indexing of messageId, destChainId, and destChainBridge supports efficient filtering and querying for common use cases, such as tracking specific destination chains or bridge contracts for transaction correlation.
## Backwards Compatibility
This EIP is fully backward compatible as it defines new event interfaces without modifying existing contract functionality. Bridge implementations **MAY** choose to implement these events alongside existing event structures. No breaking changes are introduced to existing smart contracts or protocols. Bridge protocols **MAY** adopt this standard gradually according to specific requirements.

## Test cases

Check failure on line 122 in ERCS/erc-8088.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

body has extra section(s)

error[markdown-order-section]: body has extra section(s) --> ERCS/erc-8088.md | 122 | ## Test cases | = help: see https://ethereum.github.io/eipw/markdown-order-section/
Example for tracking bridge event with this EIP standard:
1. Simulate the processing of cross-chain transactions
2. Monitor the source chain event (```CrossChainTransactionInitiated```) of cross-chain transactions to get ```messageId``` and ```messageBodyHash```
3. Query the target chain event (```CrossChainMessageCompleted```) of the bridge contract to associate it with the cross-chain transaction, and verify it by cross-checking ```messageId``` and ```messageBodyHash```. Once the verification is successful, it can be associated with the target chain monitoring object through the ```destChainId``` + ```destBridgeAddress``` fields in the source event

![图片](../assets/erc-xxx/Figure-1.png)
**<center><font size=2>Figure 1: Simulation of source chain and target chain event generation</font></center>**
![图片](../assets/erc-xxx/Figure-2.png)
**<center><font size=2>Figure 2:Cross-chain message verification</font></center>**
## Reference Implementation

```solidity
pragma solidity ^0.8.0;

/**
* @title CrossChainTrackingStandard
* @dev Implementation of EIP-XXXX Cross-Chain Transaction Tracking Standard
* Provides standardized event tracking for cross-chain transaction lifecycle
* This contract serves as a base implementation for cross-chain bridge protocols
* to ensure consistent transaction tracking across different blockchain networks
*/
contract CrossChainTrackingStandard {
/// @dev Transaction sequence counter to ensure unique nonce for each transaction
/// @notice This counter increments with each initiated transaction to prevent replay attacks
uint256 public nonce;
// Mapping to track processed messages to prevent replay attacks
mapping(bytes32 => bool) private _processedMessages;

/**
* @dev Emitted when a cross-chain transaction is initiated on the source chain
* @param messageId Cross-chain message unique identifier
* @param destChainBridge Bridge contract address on destination chain
* @param destChainId Destination chain ID
* @param messageBody Cross-chain message body containing transaction data
* @param nonce Cross-chain message sequence number
*/
event CrossChainTransactionInitiated(
bytes32 indexed messageId,
address indexed destChainBridge,
uint256 indexed destChainId,
bytes messageBody,
uint256 nonce
);

/**
* @dev Emitted when a cross-chain transaction is successfully completed on the target chain
* @param messageId Cross-chain message unique identifier
* @param messageBodyHash Hash of the message body for verification
*/
event CrossChainMessageCompleted(
bytes32 indexed messageId,
bytes32 indexed messageBodyHash
);

/**
* @dev Generates a unique cross-chain message ID
* @param sourceChainId Source chain ID
* @param sourceChainBridge Bridge contract address on source chain
* @param destChainId Destination chain ID
* @param destChainBridge Destination chain bridge contract address
* @param _nonce Transaction sequence number
* @return messageId Unique cross-chain message identifier
*/
function generateCrossChainTxId(
uint256 sourceChainId,
address sourceChainBridge,
uint256 destChainId,
address destChainBridge,
uint256 _nonce
) public pure returns (bytes32) {
return keccak256(abi.encodePacked(
sourceChainId,
sourceChainBridge,
destChainId,
destChainBridge,
_nonce
));
}
/**
* @dev Generates hash for cross-chain message body
* @param messageBodyDomain Type identifier for message body decoding
* @param sourceTokenSender Source chain token sender address
* @param destTokenReceiver Destination chain token receiver address
* @param sourceTokenAddress Source chain token address
* @param destTokenAddress Destination chain token address
* @param amount Transfer amount
* @return messageBodyHash Hash of the message body
*/
function generateCrossChainMessageHash(
bytes32 messageBodyDomain,
address sourceTokenSender,
address destTokenReceiver,
address sourceTokenAddress,
address destTokenAddress,
uint256 amount
) public pure returns (bytes32) {
return keccak256(abi.encodePacked(
messageBodyDomain,
sourceTokenSender,
destTokenReceiver,
sourceTokenAddress,
destTokenAddress,
amount
));
}
/**
* @dev Initiates a cross-chain transaction and emits the standard event
* @notice messageBody MUST include messageBodyDomain as the first field for type identification
* @param destChainBridge Bridge contract address on destination chain
* @param destChainId Destination chain ID
* @param messageBody Encoded message body with messageBodyDomain as type identifier
* @return messageId Generated message ID for this transaction
*/
function initiateCrossChainTransfer(
address destChainBridge,
uint256 destChainId,
bytes memory messageBody
) external returns (bytes32) {
uint256 _currentNonce = ++nonce;
bytes32 messageId = generateCrossChainTxId(
block.chainid, // Current chain ID as source chain ID (EIP-155)
address(this), // Source chain bridge contract address (current contract)
destChainId,
destChainBridge,
_currentNonce
);
emit CrossChainTransactionInitiated(
messageId,
destChainBridge,
destChainId,
messageBody,
_currentNonce
);
return messageId;
}

/**
* @dev Completes a cross-chain transaction and emits the completion event
* @notice Implementations SHOULD decode messageBody based on messageBodyDomain type
* @param messageId Cross-chain message unique identifier
* @param messageBody Cross-chain message body
* @return success Whether the completion was successful
*/
function completeCrossChainMessage(
bytes32 messageId,
bytes memory messageBody
) external returns (bool) {
// NOTE: Require additional signature verification
require(!_processedMessages[messageId], "Message already processed");

_processedMessages[messageId] = true;
bytes32 messageBodyHash = keccak256(messageBody);

emit CrossChainMessageCompleted(messageId, messageBodyHash);

return true;
}
}
```
## Security Considerations
- **Transaction ID Collision Resistance**:Implementations MUST ensure transaction ID generation has sufficient entropy to prevent collision attacks. The recommended keccak256 algorithm provides adequate collision resistance for typical cross-chain bridge usage, reducing the likelihood of enumeration and guessing attacks.
- **Prevention of Attack Forgery**: The source chain event includes an additional ```destChainBridge``` field to correlate the response status of cross-chain transactions with the target chain address. Since transactions that fail cross-chain validation will revert directly, and the target chain only records events from successfully validated transactions, even if an attacker attempts to confuse monitoring by forging a large number of identical cross-chain transactions simultaneously, it will not ultimately affect the correlation between source and target chain transactions.
- **Bridge-Specific Security**:This standard only defines event interfaces. Individual bridge implementations remain responsible for their protocol-specific security considerations, including but not limited to multi-signature validator sets, transaction data validation, economic security, cryptographic proofs, and ensuring bridge protocols undergo security audits.
- **Event Data Verification**:Bridge protocols SHOULD implement appropriate verification mechanisms to ensure the authenticity and integrity of event data. Event emission does not guarantee transaction success; protocols MUST verify on-chain state changes.

## Copyright

Copyright and related rights waived via [CC0](../LICENSE.md).
Binary file added assets/erc-xxx/Figure-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/erc-xxx/Figure-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading