diff --git a/ERCS/erc-7786.md b/ERCS/erc-7786.md index 47c4d87c409..7bb7e8f2cae 100644 --- a/ERCS/erc-7786.md +++ b/ERCS/erc-7786.md @@ -2,17 +2,18 @@ eip: 7786 title: Cross-Chain Messaging Gateway description: An interface for contracts to send and receive cross-chain messages containing arbitrary data. -author: Francisco Giordano (@frangio), Hadrien Croubois (@Amxx), Ernesto Garcia (@ernestognw), CJ Cobb (@cjcobb23), Sergey Gorbunov (@sergeynog) +author: Francisco Giordano (@frangio), Hadrien Croubois (@Amxx), Ernesto Garcia (@ernestognw), CJ Cobb (@cjcobb23), Sergey Gorbunov (@sergeynog), joxes (@Joxess) discussions-to: https://ethereum-magicians.org/t/erc-7786-cross-chain-messaging-gateway/21374 status: Draft type: Standards Track category: ERC created: 2024-10-14 +requires: 7930 --- ## Abstract -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". +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 (structured metadata) while providing simple "universal" access to the simple feature of "just getting a simple message through". ## Motivation @@ -30,13 +31,11 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S ### Message Field Encoding -A cross-chain message consists of a sender, receiver, payload, and list of attributes. +A cross-chain message consists of a sender, recipient, payload, value (native token), and list of attributes. -#### Sender & Receiver +#### Sender and Recipient -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 sender account (in the source chain) and recipient account (in the destination chain) MUST be input in an Interoperable Address binary format, specified in [ERC-7930](./eip-7930.md), which MUST be serialized according to CAIP-350. The recipient field MAY be omitted or zeroed (contain an Interoperable Address with all fields set to zero) to indicate an unspecified destination, such as when a broadcast mode is employed and the final recipients are determined by the protocol itself. #### Payload @@ -44,42 +43,48 @@ The payload is an opaque `bytes` value. #### Attributes -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. +An attribute is a key-value pair, where the key determines the type and encoding of the value, as well as its meaning and behavior in the gateway. -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 valid attributes is extensible. It is RECOMMENDED to standardize them and their characteristics by publishing them as ERCs. A gateway MAY support any set of standard or custom attributes. -The set of attributes is extensible. It is RECOMMENDED to standardize attributes and their characteristics by publishing them as ERCs. +An attribute key is a 4-byte value (`bytes4`). It is RECOMMENDED to define a key as the function selector for a function signature according to Solidity ABI (for example, `minGasLimit(uint256)` resulting in the key `39f87ba1`), so as to give the key a human-readable name and a standard value encoding corresponding to the ABI-encoding of the function arguments. -A gateway MAY support any set of attributes. An empty attribute list MUST always be accepted by a gateway. +An attribute value is byte array (`bytes`). -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)`. +The list of attributes MUST be encoded as `bytes[]` (an array of `bytes`) where each element is the concatenation of a key and a value. (Note that in the case of keys defined as Solidity function selectors, each element of the array can be encoded by `abi.encodeWithSignature`.) -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. +A message with no attributes (an empty attributes list) MUST be considered a valid message. ### Sending Procedure -An **Source Gateway** is a contract that offers a protocol to send a message to a receiver on another chain. It MUST implement `IERC7786GatewaySource`. +A **Source Gateway** is a contract that offers a protocol to send a message to a recipient on another chain. It MUST implement `IERC7786GatewaySource`. ```solidity interface IERC7786GatewaySource { - event MessagePosted(bytes32 indexed outboxId, string sender, string receiver, bytes payload, uint256 value, bytes[] attributes); + event MessageSent( + bytes32 indexed sendId, + bytes sender, // Binary Interoperable Address + bytes recipient, // Binary Interoperable Address + 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 recipient, // Binary Interoperable Address bytes calldata payload, bytes[] calldata attributes - ) external payable returns (bytes32 outboxId); + ) external payable returns (bytes32 sendId); } ``` #### `supportsAttribute` -Returns a boolean indicating whether an attribute is supported by the gateway, identified by the selector computed from the attribute signature. +Returns a boolean indicating whether an attribute (identified by its key) is supported by the gateway. 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. @@ -89,57 +94,55 @@ 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. +MUST revert with `UnsupportedAttribute` if an unsupported attribute is included. MAY revert if an attribute value is not valid for the key. 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. +MAY generate and return a unique non-zero _send identifier_, otherwise returning zero. This identifier can be used to track the lifecycle of the message in the source gateway in events and for post-processing. _Note that this identifier MAY be different from the `receiveId` that is delivered to the recipient, since that identifier may preferably consist of values like transaction id and log index that are not available in the execution environment._ -MUST emit a `MessagePosted` event, including the optional outbox identifier that is returned by the function. +MUST emit a `MessageSent` event, including the optional send identifier that is returned by the function. -#### `MessagePosted` +#### `MessageSent` 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. +If `sendId` is present, post-processing MAY be required to send the message through the cross-chain channel. #### Post-processing 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. +The exact interface for any such action is out of scope of this ERC. ### Reception Procedure 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. +The protocol MUST ensure delivery of a sent message to its **recipient** using the `IERC7786Recipient` interface (specified below), which the recipient MUST implement. -Once the message can be safely delivered (see Properties), the gateway MUST invoke `executeMessage` with the message identifier and contents, unless the sender or the receiver explicitly requested otherwise. +Once the message can be safely delivered (see Properties), the gateway MUST invoke `receiveMessage` with the message identifier and contents, unless the sender or the recipient explicitly requested otherwise. -The `messageId` MUST be either empty or unique (for the calling gateway) to the message being relayed. The format of this identifier is not specified, and the gateway can use it at its own discretion. For example it can be an identifier of the `MessagePosted` event that created the message. +The `receiveId` MUST be either empty or unique (for the calling gateway) to the message being relayed. The format of this identifier is not specified, and the gateway can use it at its own discretion. For example it can be an identifier of the `MessagePosted` event that created the message. -The gateway MUST verify that `executeMessage` returns the correct value, and MUST revert otherwise. +The gateway MUST verify that `receiveMessage` returns the correct value, and MUST revert otherwise. ```solidity -interface IERC7786Receiver { - function executeMessage( - string calldata messageId, // gateway specific, empty or unique - string calldata sourceChain, // [CAIP-2] chain identifier - string calldata sender, // [CAIP-10] account address +interface IERC7786Recipient { + function receiveMessage( + bytes32 receiveId, // Unique identifier + bytes calldata sender, // Binary Interoperable Address bytes calldata payload, - bytes[] calldata attributes ) external payable returns (bytes4); } ``` -#### `executeMessage` +#### `receiveMessage` 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. +The recipient 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`). +MUST return `IERC7786Recipient.receiveMessage.selector` (`0x2432ef26`). #### Interaction Diagram @@ -147,23 +150,23 @@ MUST return `IERC7786Receiver.executeMessage.selector` (`0x675b049b`). ### Properties -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_. +The protocol underlying a pair of gateways is expected to guarantee a series of properties. For a detailed definition and discussion, we refer to XChain Research’s _Cross-chain Interoperability Report_. - The protocol MUST guarantee Safety: A message is delivered at the destination if and only if it was sent at the source. The delivery process must ensure a message is only delivered once the sending transaction is finalized, and not delivered more than once. Note that there can be multiple messages with identical parameters that must be delivered separately. -- The protocol MUST guarantee Liveness: A sent message is delivered at the destination eventually, assuming Liveness and censorship-resistance of the source and destination chains. +- The protocol MUST guarantee Liveness: A sent message is eventually delivered to the destination, assuming Liveness and censorship-resistance of the source and destination chains and that any protocol costs are paid. - The protocol SHOULD guarantee Timeliness: A sent message is delivered at the destination within a bounded delivery time, which should be documented. -- The above properties SHOULD NOT rely on trust in some centralized actor. For example, safety should be guaranteed by some trustless mechanism such as a light client proof, or attestations by an open, decentralized validator set. Relaying should be decentralized or permissionless to ensure liveness; a centralized relayer can fail and thus halt the protocol. +- The above properties SHOULD NOT rely on trust in some centralized actor. For example, safety should be guaranteed by some trustless mechanism such as a light client proof or attestations by an open, decentralized validator set. Relaying should be decentralized or permissionless to ensure liveness; a centralized relayer can fail and thus halt the protocol. ## Rationale -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: +Attributes are designed so that gateways can expose any specific features the bridge offers without having to use a proprietary interface. This should allow contracts to change the gateway they use while continuing to express messages the same way. This portability offers many advantages: -- A contract that relies on a specific gateway for sending messages is vulnerable to the gateway being paused, deprecated, or simply breaking. If the communication between the contract and the gateway is standard, an admin of the contract COULD update the address (in storage) of the gateway to use. In particular, senders to update to the new gateway when a new version is available. -- Bridge layering SHOULD be possible. In particular, this interface should allow for a new class of bridges that routes the message through multiple independent bridges. Delivery of the message could require one or multiple of these independent bridges depending on whether improved liveness or safety is desired. +- A contract that relies on a specific gateway for sending messages is vulnerable to the gateway being paused, deprecated, or simply breaking. If the communication between the contract and the gateway is standard, an admin of the contract could update the address (in storage) of the gateway to use. In particular, senders to update to the new gateway when a new version is available. +- Bridge layering is made easier. In particular, this interface should allow for gateways that route the message through multiple independent bridges. Delivery of the message could require one or multiple of these independent bridges depending on whether improved liveness or safety is desired. -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. +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 attributes, 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](./eip-20.md) 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. +Some protocols gateway support doing arbitrary direct calls on the recipient. In that case, the recipient 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](./eip-20.md) or similar). The use of a dedicated `receiveMessage` function on the recipient 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. ## Backwards Compatibility @@ -171,11 +174,10 @@ Existing cross-chain messaging protocols implement proprietary interfaces. We re ## Security Considerations -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. +### Handling addresses + +Interoperable Addresses (ERC‑7930) rely on CAIP‑350 serialization. Using non‑canonical encodings can lead to silent delivery failures. Gateways SHOULD reject non‑canonical encodings and MAY normalize them before emission. ## Copyright Copyright and related rights waived via [CC0](../LICENSE.md). - -[CAIP-10]: https://github.com/ChainAgnostic/CAIPs/blob/3da24e4e912ae179713b2b1b11d6ecb5df06a8dc/CAIPs/caip-10.md -[CAIP-2]: https://github.com/ChainAgnostic/CAIPs/blob/cbee09d2885065ba15482398828d5c5e3ac57faa/CAIPs/caip-2.md