Intents

Everclear supports the direct integration of solver networks, and makes no assumptions about signaling, discovery, matching, or execution of the intent.

Lifecycle

Creation

Intents are created by calling newIntent on the Spoke contracts:

/**
   * @notice Creates a new intent
   * @param _destination The destination chain of the intent
   * @param _to The destinantion address of the intent
   * @param _inputAsset The asset address on origin
   * @param _outputAsset The asset address on destination
   * @param _amount The amount of the asset
   * @param _data The data of the intent
   * @return _intentId The ID of the intent
   * @return _intent The intent object
   */
  function newIntent(
    uint32 _destination,
    address _to,
    address _inputAsset,
    address _outputAsset,
    uint256 _amount,
    bytes calldata _data
  ) external returns (bytes32 _intentId, Intent memory _intent);

This method will debit funds from the caller, emit an IntentAdded event, and insert an Intent message into the queue.

Intent Queue Dispatch

Periodically, messages within this queue is dispatched to the clearing chain by offchain agents.

Offchain agents respect configured thresholds for queue size and age of oldest item when evaluating whether or not to dispatch messages.

Once the message arrives on the clearing chain, the intent is marked as Added.

Intent Fulfillment

At any point after intent creation, solvers can fill the intent by calling fillIntent on the destination Spoke contract if they have sufficient balance stored on-chain:

Everclear makes no assumptions about solver selection or intent execution. Adding liquidity can be done at the time of intent fulfillment.

  /**
   * @notice fills an intent
   * @param _intent The intent structure
   * @return _fillMessage The enqueued fill message
   */
  function fillIntent(Intent calldata _intent) external returns (FillMessage memory _fillMessage);

This method will debit funds from the stored balance of the caller, emit an IntentFilled event, and insert a Fill message into the queue.

Fill Queue Dispatch

Periodically, messages within this queue is dispatched to the clearing chain by offchain agents.

Offchain agents respect configured thresholds for queue size and age of oldest item when evaluating whether or not to dispatch messages.

Once the message arrives on the clearing chain, the intent is marked as Filled if the Intent message is not present. If both messages have arrived, the intent is marked as Completed and is enqueued for settlement.

When intents are marked for settlement, their solver has balance on the clearing chain that can be claimed on any of the supported spokes with sufficient liquidity.

Settlement Queue Dispatch

Periodically, offchain agents will dispatch the enqueued settlements. Offchain agents will by default settle to the intent destination chain if there is sufficient available liquidity, otherwise will settle to the solver-configured domain with the highest available liquidity.

Offchain agents respect configured thresholds for queue size and age of oldest item when evaluating whether or not to dispatch messages.

Once an intent is dispatched for settlement, it is marked as SETTLED.

Settlement Processing

Once the dispatched settlements arrive on the spoke contracts, funds are sent to the solver.

How can I reduce my settlement latency?

There is a tradeoff between batch latency and system base messaging costs. Offchain agents hosted by Connext will be subject to configured thresholds, but solvers can always make their own cost vs. latency tradeoffs by dispatching the queues themselves and including the estimated hyperlane fee in the msg.value of the following functions:

Intent and Fill Queue Methods

interface ISpokeGateway {
  /**
   * @notice Quotes cost of sending a message to the transport layer
   * @param _message The message to send
   * @return _fee The fee to send the message
   */
  function quoteMessage(bytes memory _message) external returns (uint256 _fee);
}

interface IConnextSpoke {
  /**
   * @notice Process the intent queue messages to send a batching message to the transport layer
   * @param _amount The amount of messages to process
   */
  function processIntentQueue(uint32 _amount) external payable;

  /**
   * @notice Process the fill queue messages to send a batching message to the transport layer
   * @param _amount The amount of messages to process
   */
  function processFillQueue(uint32 _amount) external payable;
}

Settlement Queue Methods

interface IHubGateway {
  /**
   * @notice Get quote for sending a message from the hub to a spoke
   * @param chainId The chain id of the spoke
   * @param _message The message to send
   * @return _fee The id message of the transport layer
   */
  function quoteMessage(uint32 chainId, bytes memory _message) external returns (uint256 _fee);
}

interface IConnextHub {
  /**
   * @notice Read only struct for the ticker and the amount of items to be processed
   * @param tickerHash The hash of the ticker symbol
   * @param amount The amount of queue items to be processed
   */
  struct TickerAmount {
    bytes32 tickerHash;
    uint32 amount;
  }

  /**
   * @notice Read only struct  for the token settlement
   * @param tickerAmounts The ticker and the amount of items to be processed
   * @param domain The settlement domain
   * @param batchSize The sum of all ticker amounts
   */
  struct TokenSettlement {
    TickerAmount[] tickerAmounts;
    uint32 domain;
    uint32 batchSize;
  }
  
  /**
   * @notice Process the settlement queue
   * @param _settlements The token settlements to process
   */
  function processSettlementQueue(TokenSettlement[] memory _settlements) external payable;
}

Last updated