This proposal describes an interface, and the corresponding workflow, for smart contracts to send arbitrary data through cross-chain messaging protocols. The end goal of this proposal is to have all such messaging protocols accessible via this interface (natively or using "adapters") to improve their composability and interoperability. That would allow a new class of cross-chain native smart contracts to emerge while reducing vendor lock-in. This proposal is modular by design, allowing users to leverage bridge-specific features through attributes while providing simple "universal" access to the simple feature of "just getting a simple message through".
Cross-chain messaging protocols (or bridges) allow communication between smart contracts deployed on different blockchains. There is a large diversity of such protocols with multiple degrees of decentralization, different architectures, implementing different interfaces, and providing different guarantees to users.
Because almost every protocol implements a different workflow using a specific interface, portability between bridges is currently basically impossible. This also prevents the development of generic contracts that rely on cross chain communication.
The objective of this ERC is to provide a standard interface, and a corresponding workflow, for performing cross-chain communication between contracts. Existing cross-chain communication protocols that do not natively implement this interface should be able to adopt it using adapter gateway contracts.
Compared to previous ERCs in this area, this ERC offers compatibility with chains outside of the Ethereum/EVM ecosystem, and it is extensible to support the different feature sets of various protocols while offering a shared core of standard functionality.
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 and RFC 8174.
A cross-chain message consists of a sender, receiver, payload, and list of attributes.
The sender account (in the source chain) and receiver account (in the destination chain) MUST be represented using CAIP-10 account identifiers. Note that these are ASCII-encoded strings.
A CAIP-10 account identifier embeds a CAIP-2 chain identifier along with an address. In some parts of the interface, the address and the chain parts will be provided separately rather than as a single string, or the chain part will be implicit.
The payload is an opaque bytes
value.
Attributes are structured pieces of message data and/or metadata. Each attribute is a key-value pair, where the key determines the type and encoding of the value, as well as its meaning and behavior.
Some attributes are message data that must be sent to the receiver, although they can be transformed as long as their meaning is preserved. Other attributes are metadata that will be used by the intervening gateways and potentially removed before the message reaches the receiver.
The set of attributes is extensible. It is RECOMMENDED to standardize attributes and their characteristics by publishing them as ERCs.
A gateway MAY support any set of attributes. An empty attribute list MUST always be accepted by a gateway.
Each attribute key MUST have the format of a Solidity function signature, i.e., a name followed by a list of types in parentheses. For example, minGasLimit(uint256)
.
In this specification attributes are encoded as an array of bytes
(i.e., bytes[]
). Each element of the array MUST encode an attribute in the form of a Solidity function call, i.e., the first 4 bytes of the hash of the key followed by the ABI-encoded value.
An Source Gateway is a contract that offers a protocol to send a message to a receiver on another chain. It MUST implement IERC7786GatewaySource
.
interface IERC7786GatewaySource {
event MessagePosted(bytes32 indexed outboxId, string sender, string receiver, bytes payload, uint256 value, bytes[] attributes);
error UnsupportedAttribute(bytes4 selector);
function supportsAttribute(bytes4 selector) external view returns (bool);
function sendMessage(
string calldata destinationChain, // [CAIP-2] chain identifier
string calldata receiver, // [CAIP-10] account address
bytes calldata payload,
bytes[] calldata attributes
) external payable returns (bytes32 outboxId);
}
supportsAttribute
Returns a boolean indicating whether an attribute is supported by the gateway, identified by the selector computed from the attribute signature.
A gateway MAY be upgraded with support for additional attributes. Once present support for an attribute SHOULD NOT be removed to preserve backwards compatibility with users of the gateway.
sendMessage
Initiates the sending of a message.
Further action MAY be required by the gateway to make the sending of the message effective, such as providing payment for gas. See Post-processing.
MUST revert with UnsupportedAttribute
if an unsupported attribute key is included. MAY revert if the value of an attribute is not a valid encoding for its expected type.
MAY accept call value (native token) to be sent with the message. MUST revert if call value is included but it is not a feature supported by the gateway. It is unspecified how this value is represented on the destination.
MAY generate and return a unique non-zero outbox identifier, otherwise returning zero. This identifier can be used to track the lifecycle of the message in the outbox in events and for post-processing.
MUST emit a MessagePosted
event, including the optional outbox identifier that is returned by the function.
MessagePosted
This event signals that a would-be sender has requested a message to be sent.
If outboxId
is present, post-processing MAY be required to send the message through the cross-chain channel.
After a sender has invoked sendMessage
, further action MAY be required by the gateways to make the message effective. This is called post-processing. For example, some payment is typically required to cover the gas of executing the message at the destination.
The exact interface for any such action is out of scope of this ERC. If the postProcessingOwner
attribute is supported and present, such actions MUST be restricted to the specified account, otherwise they MUST be able to be performed by any party in a way that MUST NOT be able to compromise the eventual receipt of the message.
A Destination Gateway is a contract that implements a protocol to validate messages sent on other chains. The interface of the destination gateway and how it is invoked is out of scope of this ERC.
The protocol MUST ensure delivery of a sent message to its receiver using the IERC7786Receiver
interface (specified below), which the receiver MUST implement.
Once the message can be safely delivered (see Properties), the gateway MUST invoke executeMessage
with the message contents.
The gateway MUST verify that executeMessage
returns the correct value, and MUST revert otherwise.
interface IERC7786Receiver {
function executeMessage(
string calldata sourceChain, // [CAIP-2] chain identifier
string calldata sender, // [CAIP-10] account address
bytes calldata payload,
bytes[] calldata attributes
) external payable returns (bytes4);
}
executeMessage
Delivery of a message sent from another chain.
The receiver MUST validate that the caller of this function is a known gateway, i.e., one whose underlying cross-chain messaging protocol it trusts.
MUST return IERC7786Receiver.executeMessage.selector
(0x675b049b
).
The protocol underlying a pair of gateways is expected to guarantee a series of properties. For detailed definition and discussion we refer to XChain Research’s Cross-chain Interoperability Report.
Attributes are designed so that gateways can expose any specific features the bridge offers without having to use a specific endpoint. Having a unique endpoint, with modularity through attributes, SHOULD allow contracts to change the gateway they use while continuing to express messages the same way. This portability offers many advantages:
As some cross-chain communication protocols require additional parameters beyond the destination and the payload, and because we want to send messages through those bridges without any knowledge of these additional parameters, a post-processing of the message MAY be required (after sendMessage
is called, and before the message is delivered). The additional parameters MAY be supported through attributes, which would remove the need for a post-processing step. If these additional parameters are not provided through an attribute, an additional call to the gateway is REQUIRED for the message to be sent. If possible, the gateway SHOULD be designed so that anyone with an incentive for the message to be delivered can jump in. A malicious actor providing invalid parameters SHOULD NOT prevent the message from being successfully relayed by someone else.
Some protocols gateway support doing arbitrary direct calls on the receiver. In that case, the receiver must detect that they are being called by the gateway to properly identify cross-chain messages. Getters are available on the gateway to figure out where the cross-chain message comes from (source chain and sender address). This approach has the downside that it allows anyone to trigger any call from the gateway to any contract. This is dangerous if the gateway ever holds any assets (ERC-20 or similar). The use of a dedicated executeMessage
function on the receiver protects any assets or permissions held by the gateway against such attacks. If the ability to perform direct calls is desired, this can be implemented as a wrapper on top of any gateway that implements this ERC.
Existing cross-chain messaging protocols implement proprietary interfaces. We recommend that protocols natively implement the standard interface defined here, and propose the development of standard adapters for those that don't.
Unfortunately, CAIP-2 and CAIP-10 names are not unique. Using non-canonical strings may lead to undefined behavior, including message delivery failure and locked assets. While source gateways have a role to play in checking that user input are valid, we also believe that more effort should be put into standardizing and documenting what the canonical format is for each CAIP-2 namespace. This effort is beyond the scope of this ERC.
Copyright and related rights waived via CC0.