Skip to content
Merged
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
40b7b01
Add ERC: Crosschain Token Interface
0xParti Oct 30, 2024
88e4244
added temporary erc number
0xParti Oct 30, 2024
f5c5140
added temporary erc number in preamble
0xParti Oct 30, 2024
7a22c41
chore: fix lint errors
0xParti Oct 30, 2024
f68b199
chore: fixing lint
0xParti Oct 30, 2024
c70b2aa
feat: added discussion link
0xParti Oct 30, 2024
2aadee3
fix internal links
0xParti Oct 30, 2024
95f4221
fix links
0xParti Oct 30, 2024
0eb7d1f
Apply suggestions from code review
0xParti Oct 31, 2024
2edb932
feat: improved reference code, change authors handles
0xParti Oct 31, 2024
a587407
chore: fix lint
0xParti Oct 31, 2024
0530449
feat: added ERC-165 compliance
0xParti Oct 31, 2024
9ffe3bc
chore: fix preamble
0xParti Oct 31, 2024
59e733a
feat: added requires field on preamble
0xParti Oct 31, 2024
1946670
feat: improved rationale for erc165
0xParti Oct 31, 2024
6e815b8
chore: lint
0xParti Oct 31, 2024
dae604d
feat: improved reference implementation
0xParti Nov 1, 2024
b7022c7
feat: added sender to events
0xParti Nov 18, 2024
5854570
feat: added rationale on function separation
0xParti Nov 19, 2024
bcea9fe
chore: lint
0xParti Nov 19, 2024
4fc3c98
feat: remove explicit references to third-party standards
0xParti Dec 17, 2024
1c283af
chore: includes 5679 in requirements
0xParti Dec 17, 2024
5d26ebb
chore: remove references to specific vendors, modified description an…
0xParti Dec 17, 2024
34983ad
chore: improve Abstract
0xParti Dec 17, 2024
c1fae24
lint: eip validator fix
0xParti Dec 17, 2024
bf1ebe7
feat: change invariants on the Transfer events to address 0 on calls …
0xParti Dec 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
259 changes: 259 additions & 0 deletions ERCS/erc-7802.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
---
eip: 7802
title: Crosschain Token Interface
Copy link
Contributor

Choose a reason for hiding this comment

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

"Interface" in an ERC title doesn't add a ton of information. Most ERCs contain some kind of interface.

How about:

Suggested change
title: Crosschain Token Interface
title: Permissioned Token Mint/Burn Across Chains

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agree with the suggestion of removing "interface" from the title. I'm not convinced about using "Permissioned", as that is not inherent to the interface (it could be permissionless). What do you think about something like "Token with Mint/Burn access Across Chains"?

description: Token interface that allows authorized contracts to mint and burn token representations during cross-chain transfers
author: skeletor (@skeletor-spaceman), parti (@0xParticle), joxes (@Joxess), ng (@0xng), agus duha (@agusduha), disco (@0xDiscotech), gotzen <gotzen@defi.sucks>, 0age <0age@uniswap.org>, Mark Tyneway <mark@oplabs.co>, Zain Bacchus <zain@oplabs.co>, Matt Solomon <msolomon@oplabs.co>, Maurelian <maurelian@protonmail.ch>, Blaine Malone (@blmalone)
discussions-to: https://ethereum-magicians.org/t/erc-7802-crosschain-token-interface/21508
status: Draft
type: Standards Track
category: ERC
created: 2024-10-30
requires: 165, 5679
---

## Abstract

This standard introduces a minimal interface, `IERC7802`, for tokens to enable standardized cross-chain communication. The interface consists of two functions, `crosschainMint` and `crosschainBurn`, which allow authorized bridge contracts to mint and burn token representations during cross-chain transfers. These functions serve as the entry points for bridge logic, enabling consistent handling of token supply across chains.

The interface also defines two standardized events, `CrosschainMint` and `CrosschainBurn`, which emit metadata, including the target address, token amount, and caller. These events facilitate deterministic indexing and monitoring of cross-chain activities by off-chain agents, such as indexers, analytics tools, and auditors.

`IERC7802` is intentionally lightweight, ensuring minimal overhead for implementation. Its modular design enables extensibility, allowing additional features—such as mint/burn limits, transfer fees, or bridge-specific access control mechanisms—to be layered on top without modifying the base interface.
Copy link
Contributor

Choose a reason for hiding this comment

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

This paragraph probably belongs (with some rewording) in the Rationale section, since it explains why this standard is designed the way it is.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The Rationale section already speaks about this design decision in more depth. I wanted to highlight this key property in the Abstract as well.
If you still consider this paragraph is too much information for the Abstract, I could rephrase it and make it shorter.


## Motivation

All rollups and multiple important sidechains (Gnosis and Polygon PoS, among others) implement canonical bridges that embed their security into some part of the network's core architecture. These bridges do not have mint/burn rights over original tokens, so they usually lock (unlock) liquidity on the native chain and then mint (burn) a non-equivalent representation on the other. Mint/burn is used because the native token is non-existent on that side, so they must create a new representation. However, each bridge implements a different interface for minting/burning on non-native chains.

This interface fragmentation is a massive issue in cross-chain communication among chains via third-party bridges or future canonical solutions. At this point, it is clear that every bridge would benefit from a standardized interface for minted/burnt tokens.

There have been different attempts in the past to standardize token-bridging interfaces. However, third-party providers are also developing cross-chain token frameworks. Each framework defines its features, like rate limits and fee switches, and implements its mint and burn versions. The resultant interfaces become highly specific, lacking naming conventions and structures.

The proposed interface includes the most relevant and minimal set of actions used by most of these standards. These actions also do not require any governance or owner participation, in contrast, for instance, to set rate limits.

## Specification

This ERC introduces the `IERC7802` interface.

### Interface Identification

The interface identifier for `IERC7802` is **`0x33331994`**, calculated according to [ERC-165](./eip-165.md) as the XOR of the function selectors of the two functions in the interface:

```solidity
bytes4 constant INTERFACE_ID_IERC7802 =
bytes4(keccak256("crosschainMint(address,uint256)")) ^
bytes4(keccak256("crosschainBurn(address,uint256)"));
```

or via Solidity as

```solidity
type(IERC7802).interfaceId
```

Implementors MUST ensure that the `supportsInterface` method of ERC-165 returns true for this interface ID to indicate support for `IERC7802`.


### Methods

**`crosschainMint`**

Mints `_amount` of token to address `_account`.

This function works as the minting entry point for bridge contracts. Each implementation is responsible for its access control logic.
Copy link
Contributor

Choose a reason for hiding this comment

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

You can move the access control notes on each method to the security considerations section.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The Security considerations mention this issue explicitly. I will remove these considerations from the method description to minimize redundancy.


```solidity
function crosschainMint(address _account, uint256 _amount) external;
```

Implementations SHOULD emit `Transfer(address(0), _to, _amount)` on calls to `crosschainMint` to be compliant with [ERC-20](./eip-20.md) invariants on token creation.

**`crosschainBurn`**

Burns `_amount` of token from address `_account`.

This function works as the burning entry point for bridge contracts. Each implementation is responsible for its access control logic.

```solidity
function crosschainBurn(address _account, uint256 _amount) external;
```

Implementations might consider emitting `Transfer(_from, address(0), _amount)` on calls to `crosschainBurn` to be compliant with [ERC-5679](./eip-5679.md).

### Events
Copy link

Choose a reason for hiding this comment

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

Adding source/destination chain id & a unique message id to events would make crosschain data more easily usable. This ~may be a hard requirement for analytics, but hard to know without seeing further build out. This is necessary for joining messages across chains, to then see inflows/outflows by chain and routes.

This gap is a main reason why you don't see this data for 3P bridges. Most sites do ~1-3 L2<>L2 bridges, then give up due to the high overhead.

Copy link

Choose a reason for hiding this comment

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

+1

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hi @MSilb7 !

Thank you for your suggestion. We have discussed your idea internally and agree that it has value. However, we couldn't find a minimalistic set of parameters to add to the event without making the current standard more opinionated:

  • Identifier: Incorporating an identifier would require defining an encoding standard within the ERC, which we believe is beyond the scope of this proposal.
  • Adding from/to and chainIdFrom/chainIdTo: Including these parameters would require changing the inputs of crosschainMint and crosschainBurn to allow the bridge to pass them. This approach is opinionated because bridges might have multiple destinations or origins, and imposing single input parameters could limit their flexibility. Moreover, event-collisions would be possible.

We see significant value in adding msg.sender to the CrosschainMint and CrosschainBurn events. This addition would allow integrators to identify which bridge interacts with the tokens, and does not affect the interface's neutrality in anyway.

I believe your idea has the potential to become a standard for bridge events.

Copy link

@MSilb7 MSilb7 Nov 6, 2024

Choose a reason for hiding this comment

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

On msg.sender:

  • Is the use case of msg.sender that in order to join, you would only look at transactions sent from that address on other chains? Or only function calls (internal txs) initiating from that address?
  • Is this already derivable from the transaction / internal transaction? If so then the only benefit is just that you don't need to use traces, you can just use logs.

My overall opinion is:

  • Without any way to clearly identify how you identify the source burn for any destination mint (and vice versa), it's not useful from an analytics & legibility perspective.
  • The only value it fulfills now seems to be: I know that this is intended to be a cross-chain transfer, versus a same-chain transfer. But it still gives me no information about where the transfer came from or goes to.
  • Which then opens up other questions, like: "How do applications know if the burn/mint is valid?"

Copy link

@karankurbur karankurbur Nov 9, 2024

Choose a reason for hiding this comment

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

adding msg.sender to the event would make indexing significantly easier as we can now find all mints/burns associated with a specific bridge purely based on log data.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We just added msg.sender. It was very easy to implement and can help off-chain agents.


**`CrosschainMint`**

MUST trigger when `crosschainMint` is successfully called.
Copy link
Contributor

Choose a reason for hiding this comment

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

This leaves a lot unspecified (which is fine if it's intentional.) For example, should other non-standard functions that also effectively perform a crosschain mint also trigger this event, or is it specifically tied to this function?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, this is intentionally unspecified. The CrosschainMint event MUST be triggered when the crosschainMint function is successfully called. However, implementers are not restricted from emitting this event when using other non-standard functions that effectively perform a crosschain mint.

If the implementation adheres to this standard, the full interface—including crosschainMint and crosschainBurn—will already be available, so it is expected that these functions are used for crosschain minting and burning. That said, the event is not mandated for every action that triggers a crosschain operation, as this standard focuses specifically on the standardized interface.

The `_sender` parameter MUST be set to the msg.sender at the time the function is called.

```solidity
event CrosschainMint(address indexed _to, uint256 _amount, address indexed _sender);
```

**`CrosschainBurn`**

MUST trigger when `crosschainBurn` is successfully called.
The `_sender` parameter MUST be set to the msg.sender at the time the function is called.

```solidity
event CrosschainBurn(address indexed _from, uint256 _amount, address indexed _sender)
```

## Rationale

### Design philosophy
The core design decisions behind this minimal interface are

- Bridge agnosticism.
- Extensibility.

**Bridge agnosticism**
This interface is designed so bridges, not tokens, contain the logic to process cross-chain actions. By maintaining this separation of concerns, token contracts remain simple, reducing their attack surface and easing auditing and upgradability. Offloading cross-chain complexities to bridge contracts ensures that tokens do not embed specific bridge logic.

By implementing the proposed interface, tokens can be supported by different bridge designs:

- Lock/unlock bridges can still operate and do not require any token modification.
- Burn/mint bridges can now use a universal and minimal token interface, so they will not need to introduce bridge-specific representations, improving cross-chain fungibility.

**Extensibility**
The minimal interface serves as a foundational layer upon which other standards can be built.
Token issuers or bridge contracts can extend functionality by adding features such as mint/burn limits, cross-chain transfer fees, and more without altering the core interface.

The interface is intentionally neutral and does not impose conditions on:

- **Access Control**: Token issuers determine who is authorized to call `crosschainMint()` and `crosschainBurn()`.
- **Zero Amount Calls**: Token issuers decide whether to allow or revert calls with zero amounts.

### Separation of Local and Cross-Chain Minting/Burning

**Different actions**

Local minting and burning are fundamentally different from cross-chain minting and burning.

- In cross-chain operations, the total circulating supply across all chains is expected to remain constant, as tokens are transferred between chains rather than created or destroyed in isolation.
- Agents that mint and burn tokens in cross-chain transfer fundamentally differ from token owners. It make sense for the two actors to have different permissions.

Therefore, it is reasonable to have different checks, access controls, and logic (such as mint/burn limits) for cross-chain actions.

**Separation of concerns**

Merging local and cross-chain minting/burning into the same functions can lead to complex implementations that intertwine different operational logic.
By splitting into two, concerns remain separate, making the codebase cleaner and more maintainable.

This separation of concerns is particularly relevant for

- Upgrades: Any changes in access control, limits, or logic will only affect the separate cross-chain functions (`crosschainMint` and `crosschainBurn`) without altering the standard local mint and burn implementations.
- Integrations with Different Chains: To make an [ERC-20](./eip-20.md) cross-chain compatible,
issuers simply need to implement the [ERC-7802](./eip-7802.md) extension with the corresponding access controls for each chain.
For example, when integrating with Optimism, the ERC-20 would grant access to the Optimism bridge; when integrating with Arbitrum, it would grant access to the Arbitrum bridge.
The local mint and burn functions remain unchanged.
Using dedicated functions for cross-chain operations provides a more modular approach, avoiding the need to modify the base implementation for each chain.

**Dedicated events**

A similar reasoning applies to having dedicated cross-chain-specific events. The separation significantly facilitates the work of indexers, analytics tools, and auditors. It allows for straightforward tracking of cross-chain activities, detecting anomalies, and monitoring bridge operations. If cross-chain and local events are indistinguishable, off-chain agents must implement complex logic to differentiate them, increasing the potential for errors and inefficiencies.

### ERC-165 Interface

The inclusion of ERC-165 provides an additional security check for integrators. By providing the interface identifier through the `supportsInterface` method, callers can programmatically confirm that the token adheres to the `IERC7802` interface.
This verification ensures that the token supports both `crosschainMint` and `crosschainBurn` functions, preventing scenarios where only one function is implemented. Such incomplete implementations could lead to issues like users burning tokens to bridge out but being unable to mint them upon return, resulting in failed cross-chain actions.

It is important to note that this check can only be performed locally on the chain where the token contract resides. There is no inherent guarantee that the token on the receiving chain also supports the `IERC7802` interface. Ensuring cross-chain consistency of interface support is the responsibility of the bridge implementation.

## Backwards Compatibility

This proposal is fully backwards compatible with [ERC-20](./eip-20.md).

As discussed in the Motivation section, a minimal, flexible cross-chain standard interface is necessary. The problem becomes larger as more tokens are deployed without a standardized format.

- Upgradable tokens can be upgraded to implement the new interface.
- Non-upgradable tokens cannot implement the interface on the token itself. They can still migrate to a standard-compliant version using a lockbox mechanism, as proposed by xERC-20. The idea is to lock non-mintable tokens and mint the same amount of interface-compliant tokens. The bridge contract can act as a lockbox on the native chain.
Copy link
Contributor

Choose a reason for hiding this comment

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

Does xERC-20 have an ERC? If so, you should link it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It has an open PR to the ERC repo with assigned number 7281, but it has not been merged. If I mention the ERC-7281 in this ERC, the EIP validator asks for an internal link, which I can't reference at the moment.


Bridge contracts will also need an upgrade to integrate with the interface.

## Reference Implementation

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity 0.8.25;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";


/// @title IERC7802
/// @notice Defines the interface for crosschain ERC20 transfers.
interface IERC7802 is IERC165 {
/// @notice Emitted when a crosschain transfer mints tokens.
/// @param to Address of the account tokens are being minted for.
/// @param amount Amount of tokens minted.
/// @param sender Address of the caller (msg.sender) who invoked crosschainMint.
event CrosschainMint(address indexed to, uint256 amount, address indexed sender);

/// @notice Emitted when a crosschain transfer burns tokens.
/// @param from Address of the account tokens are being burned from.
/// @param amount Amount of tokens burned.
/// @param sender Address of the caller (msg.sender) who invoked crosschainBurn.
event CrosschainBurn(address indexed from, uint256 amount, address indexed sender);

/// @notice Mint tokens through a crosschain transfer.
/// @param _to Address to mint tokens to.
/// @param _amount Amount of tokens to mint.
function crosschainMint(address _to, uint256 _amount) external;

/// @notice Burn tokens through a crosschain transfer.
/// @param _from Address to burn tokens from.
/// @param _amount Amount of tokens to burn.
function crosschainBurn(address _from, uint256 _amount) external;
}

contract CrosschainERC20 is ERC20, IERC7802 {
/// @notice Address of the TOKEN_BRIDGE contract that is allowed to mint/burn tokens.
address public immutable TOKEN_BRIDGE;

/// @notice Custom error for unauthorized access.
error Unauthorized();

/// @notice Constructor to set the TOKEN_BRIDGE address.
/// @param _tokenBridge Address of the TOKEN_BRIDGE.
constructor(address _tokenBridge, string memory name, string memory symbol) ERC20(name, symbol) {
require(_tokenBridge != address(0), "Invalid TOKEN_BRIDGE address");
TOKEN_BRIDGE = _tokenBridge;
}

/// @notice A modifier that only allows the TOKEN_BRIDGE to call
modifier onlyTokenBridge() {
if (msg.sender != TOKEN_BRIDGE) revert Unauthorized();
_;
}

/// @notice Allows the TOKEN_BRIDGE to mint tokens.
/// @param _to Address to mint tokens to.
/// @param _amount Amount of tokens to mint.
function crosschainMint(address _to, uint256 _amount) external onlyTokenBridge {
_mint(_to, _amount);
emit CrosschainMint(_to, _amount, msg.sender);
}

/// @notice Allows the TOKEN_BRIDGE to burn tokens.
/// @param _from Address to burn tokens from.
/// @param _amount Amount of tokens to burn.
function crosschainBurn(address _from, uint256 _amount) external onlyTokenBridge {
_burn(_from, _amount);
emit CrosschainBurn(_from, _amount, msg.sender);
}

function supportsInterface(bytes4 interfaceId) external pure override returns (bool) {
return interfaceId == type(IERC7802).interfaceId || interfaceId == type(IERC165).interfaceId;
}
}
```

## Security Considerations

Token issuers are responsible for controlling which contracts are authorized to call the `crosschainMint()` and `crosschainBurn()` functions. A buggy or malicious authorized caller could mint or burn tokens improperly, damaging token holders and disrupting integrations.

One method to minimize potential losses is introducing mint/burn limits, as proposed by xERC-20. These features are fully compatible with the proposed interface.

## Copyright

Copyright and related rights waived via [CC0](../LICENSE.md).
Loading