HomeEIPs
EIPsERC-7683
ERC-7683

Cross Chain Intents

An interface for cross-chain trade execution systems.
DraftStandards Track: ERC
Created: 2024-04-11
Mark Toda (@marktoda), Matt Rice (@mrice32), Nick Pai (@nicholaspai)
DiscussionsOriginal linkEdit
1 min read
Anyone may contribute to propose contents.
Go propose
Video
Anyone may contribute to propose contents.
Go propose
Original

Abstract

The following standard allows for the implementation of a standard API for cross-chain trade execution systems. This standard provides a generic CrossChainOrder struct, as well as a standard ISettlementContract smart contract interface.

Motivation

Intent-based systems have become the preeminent solution for end-user cross-chain interaction by abstracting away the complexity and time constraints of traditional bridges. One of the key difficulties for cross-chain intents systems is accessing sufficient liquidity and a network of active fillers across chains. This challenge may be exacerbated as the number of distinct chains increases over time. The end result of this is a poor experience for users including higher costs, longer wait times and higher failure rates than necessary.

By implementing a standard, cross-chain intents systems can interoperate and share infrastructure such as order dissemination services and filler networks, thereby improving end-user experience by increasing competition for fulfilling user intents.

Specification

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.

CrossChainOrder struct

A compliant cross-chain order type MUST be ABI decodable into the CrossChainOrder type.

/// @title CrossChainOrder type /// @notice Standard order struct to be signed by swappers, disseminated to fillers, and submitted to settlement contracts struct CrossChainOrder { /// @dev The contract address that the order is meant to be settled by. /// Fillers send this order to this contract address on the origin chain address settlementContract; /// @dev The address of the user who is initiating the swap, /// whose input tokens will be taken and escrowed address swapper; /// @dev Nonce to be used as replay protection for the order uint256 nonce; /// @dev The chainId of the origin chain uint32 originChainId; /// @dev The timestamp by which the order must be initiated uint32 initiateDeadline; /// @dev The timestamp by which the order must be filled on the destination chain uint32 fillDeadline; /// @dev Arbitrary implementation-specific data /// Can be used to define tokens, amounts, destination chains, fees, settlement parameters, /// or any other order-type specific information bytes orderData; }

Cross-chain execution systems implementing this standard SHOULD create a custom sub-type that can be parsed from the arbitrary orderData field. This may include information such as the tokens involved in the swap, the destination chain IDs, fulfillment constraints or settlement oracles.

ResolvedCrossChainOrder struct

A compliant cross-chain order type MUST be convertible into the ResolvedCrossChainOrder struct.

/// @title ResolvedCrossChainOrder type /// @notice An implementation-generic representation of an order /// @dev Defines all requirements for filling an order by unbundling the implementation-specific orderData. /// @dev Intended to improve integration generalization by allowing fillers to compute the exact input and output information of any order struct ResolvedCrossChainOrder { /// @dev The contract address that the order is meant to be settled by. address settlementContract; /// @dev The address of the user who is initiating the swap address swapper; /// @dev Nonce to be used as replay protection for the order uint256 nonce; /// @dev The chainId of the origin chain uint32 originChainId; /// @dev The timestamp by which the order must be initiated uint32 initiateDeadline; /// @dev The timestamp by which the order must be filled on the destination chain(s) uint32 fillDeadline; /// @dev The inputs to be taken from the swapper as part of order initiation Input[] swapperInputs; /// @dev The outputs to be given to the swapper as part of order fulfillment Output[] swapperOutputs; /// @dev The outputs to be given to the filler as part of order settlement Output[] fillerOutputs; } /// @notice Tokens sent by the swapper as inputs to the order struct Input { /// @dev The address of the ERC20 token on the origin chain address token; /// @dev The amount of the token to be sent uint256 amount; } /// @notice Tokens that must be receive for a valid order fulfillment struct Output { /// @dev The address of the ERC20 token on the destination chain /// @dev address(0) used as a sentinel for the native token address token; /// @dev The amount of the token to be sent uint256 amount; /// @dev The address to receive the output tokens address recipient; /// @dev The destination chain for this output uint32 chainId; }

ISettlementContract interface

A compliant settlement contract implementation MUST implement the ISettlementContract interface:

/// @title ISettlementContract /// @notice Standard interface for settlement contracts interface ISettlementContract { /// @notice Initiates the settlement of a cross-chain order /// @dev To be called by the filler /// @param order The CrossChainOrder definition /// @param signature The swapper's signature over the order /// @param fillerData Any filler-defined data required by the settler function initiate(CrossChainOrder order, bytes signature, bytes fillerData) external; /// @notice Resolves a specific CrossChainOrder into a generic ResolvedCrossChainOrder /// @dev Intended to improve standardized integration of various order types and settlement contracts /// @param order The CrossChainOrder definition /// @param fillerData Any filler-defined data required by the settler /// @returns ResolvedCrossChainOrder hydrated order data including the inputs and outputs of the order function resolve(CrossChainOrder order, bytes fillerData) external view returns (ResolvedCrossChainOrder); }

Rationale

Generic OrderData

A key consideration is to ensure that a broad range of cross-chain intent designs can work within the same standard. To enable this, the specification is designed around a standard cross-chain intents flow, while allowing for varying implementation details within that flow.

Standard cross-chain intents flow:

  1. The swapper signs an off-chain message defining the parameters of their order
  2. The order is disseminated to fillers
  3. The filler initiates the trade on the origin chain
  4. The filler fills the order on the destination chain
  5. A cross-chain settlement process takes place to settle the order

Within this flow, implementers of the standard have design flexibility to customize behavior such as:

  • Price resolution, e.g. dutch auctions or oracle-based pricing
  • Fulfillment constraints
  • Settlement procedures.

The orderData field allows implementations to take arbitrary specifications for these behaviors while still enabling integrators to parse the primary fields of the order.

This functionality also motivated the resolve view function and ResolvedCrossChainOrder type. Resolution enables integrating fillers to validate and assess orders without specific knowledge of the orderData field at hand.

Usage of Permit2

Permit2 is not specifically required by this standard, but does provide an efficient and straightforward approach to building standard-adherent protocols. Specifically, the witness functions of permit2 allow swappers to both approve the token transfer and the order itself with a single signature. This also nicely couples the transfer of tokens with a successful initiation of the order.

In contrast, a standard approval model would require two separate signatures - a token approval (either ERC-2612 or on-chain) and a signature to approve the terms of the swap. It also decouples the token approval from the swap, meaning approved tokens could potentially be taken at any time due to a buggy or untrusted settler contract.

When building a standard-compliant settler system around Permit2, the following considerations should be made

  • nonce in the order struct should be a permit2 nonce
  • initiateDeadline in the order struct should be the permit2 deadline
  • A full order struct including the parsed orderData should be used as the witness type during the permit2 call. This ensures maximum transparency to the swapper as they sign their order permit.

Security Considerations

Copyright and related rights waived via CC0.

Further reading
Anyone may contribute to propose contents.
Go propose
Adopted by projects
Anyone may contribute to propose contents.
Go propose

Not miss a beat of EIPs' update?

Subscribe EIPs Fun to receive the latest updates of EIPs Good for Buidlers to follow up.

View all
Serve Ethereum Builders, Scale the Community.
Resources
GitHub
Supported by