Across is now live on BNB Smart Chain!
Bridge Now!
Across Documentation
V3 Developer Docs
V3 Developer Docs
  • 👋Introduction
    • Welcome to Across
    • What is Across?
    • Technical FAQ
    • Migration Guides
      • Migration from V2 to V3
      • Migration to CCTP
        • Migration Guide for Relayers
        • Migration Guide for API Users
      • Migration Guide for Non-EVM and Prefills
        • Breaking Changes for Indexers
        • Breaking Changes for API Users
        • Breaking Changes for Relayers
        • Testnet Environment for Migration
      • Solana Migration Guide
      • BNB Smart Chain Migration Guide
  • 🚀DEVELOPER QUICKSTART
    • Instant Bridging in your Application
      • Bridge Integration Guide
      • Multichain Bridge UI Guide
      • Single Chain Bridge UI Guide
    • Embedded Crosschain Actions
      • Crosschain Actions Integration Guide
        • Using the Generic Multicaller Handler Contract
        • Using a Custom Handler Contract
      • Crosschain Actions UI Guide
    • Settle Crosschain Intents
    • ERC-7683 in Production
  • 🧠Concepts
    • What are Crosschain Intents?
    • Intents Architecture in Across
    • Intent Lifecycle in Across
    • Canonical Asset Maximalism
  • 🛠️Reference
    • API Reference
    • App SDK Reference
    • Contracts
      • Aleph Zero
      • Arbitrum
      • Base
      • Blast
      • BNB Smart Chain
      • Ethereum
      • Linea
      • Lens Chain
      • Ink
      • Lisk
      • Mode
      • Optimism
      • Polygon
      • Redstone
      • Scroll
      • Soneium
      • Unichain
      • World Chain
      • zkSync
      • Zora
    • Selected Contract Functions
    • Supported Chains
    • Fees in the System
    • Actors in the System
    • Security Model and Verification
      • Disputing Root Bundles
      • Validating Root Bundles
    • Tracking Events
  • 🔁Relayers
    • Running a Relayer
    • Relayer Nomination
  • 📚Resources
    • Release Notes
    • Developer Support
    • Bug Bounty
    • Audits
Powered by GitBook
LogoLogo

Products

  • Across Bridge
  • Across+
  • Across Settlement

Socials

  • Discord
  • Twitter
  • Medium
  • Forum

Resources

  • Blog
  • Across Brand Assets
  • Github

Routes

  • Bridge to Unichain
  • Bridge to Arbitrum
  • Bridge to Optimism
  • Bridge to Linea
  • Bridge to Polygon
  • Bridge to Base
  • Bridge to World Chain
  • Bridge to zkSync
On this page
  • Integrating Across Settlement into Your Application
  • Across Settlement Example
  1. DEVELOPER QUICKSTART

Settle Crosschain Intents

Across Settlement is the only production-ready modular layer for fast, low-cost crosschain Intents and seamless interoperability.

PreviousCrosschain Actions UI GuideNextERC-7683 in Production

Last updated 2 months ago

The future of interoperability is intents and Across Settlement is the only production-ready, modular settlement layer built to facilitate crosschain intents. The Across Bridge and Across+ products build on top of Across Settlement to offer bridging to users and bridge abstraction to dApp developers.

With Across Settlement, any other application or source of crosschain intent order flow can leverage Across Settlement to enable the fastest speeds and lowest fees for their interoperability use-case.

Integrating Across Settlement into Your Application

This guide contains an examples for how to build on top of Across Settlement

If you have further questions or suggestions for this guide, please send a message to the #developer-questions channel in the .

Across Settlement Example

Across Settlement is a very flexible system, so this example won't capture all that you can do. However, it should illustrate the types of integrations that are possible.

Architecture

The example application we're going to build has the following architecture:

  1. User asks for a quote on a crosschain swap from an offchain RFQ system.

  2. Market-maker-relayers bid on the opportunity to fill the user.

  3. The user signs the winning bid as a Permit2 order.

  4. The Permit2 order is passed to the winning market-maker-relayer.

  5. The market-maker-relayer sends a transaction where this order is put onchain.

  6. In that transaction, the user's funds are pulled via Permit2. A bond is submitted by the market-maker-relayer in the transaction as well in the same currency as the user's funds.

  7. An Across deposit is created. The bond + user funds are set as the input amount. The market-maker-relayer is set as the exclusive relayer, so they are the only relayer who can submit the relay on the destination.

This tutorial will not implement the offchain components, but it will show a sample contract implementation for the contract that processes the Permit2 order.

Sample Implementation

Note: the implementation below has not been vetted, validated, or optimized in any way. It is purely meant as an illustrative example. Use this sample code at your own risk. See the comments in the code to understand what each portion of the code is doing.

import {IPermit2} from "permit2/src/interfaces/IPermit2.sol";
import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeTransferFrom.sol";

// Across SpokePool Interface
interface AcrossV3SpokePool {
  function depositV3(
    address depositor,
    address recipient,
    address inputToken,
    address outputToken,
    uint256 inputAmount,
    uint256 outputAmount,
    uint256 destinationChainId,
    address exclusiveRelayer,
    uint32 quoteTimestamp,
    uint32 fillDeadline,
    uint32 exclusivityDeadline,
    bytes calldata message
  ) external;
}

// Sample crosschain order
struct CrossChainOrder {
  address rfqContract;
  address swapper;
  address relayer;
  address recipient;
  address inputToken;
  address outputToken;
  uint256 inputAmount;
  uint256 relayerBondAmount;
  uint256 outputAmount;
  uint256 destinationChainId;
  uint256 nonce;
  uint256 deadline;
}

// A typestring is required for Permit2 to be able to process the order as witness data.
string constant ORDER_WITNESS_TYPESTRING = "CrossChainOrder witness)CrossChainOrder(address rfqContract,address swapper,address relayer,address recipient,address inputToken,address outputToken,uint256 inputAmount,uint256 relayerBondAmount,uint256 outputAmount,uint256 destinationChainId,uint256 nonce,uint256 deadline)";

contract RFQSwapper {
  using SafeERC20 for IERC20;

  IPermit2 public immutable permit2;
  AcrossV3SpokePool public immutable spokePool;
  
  constructor(address _permit2, address _spokePool) {
    permit2 = Permit2(_permit2);
    spokePool = AcrossV3SpokePool(_spokePool);
  }
  
  // The initiate function:
  // 1. Takes in an order and swapper signature.
  // 2. Verifies the signature and order validity.
  // 3. Passes along the tokens and instructions to the Across SpokePool
  //    where the order will be filled, that fill verified, and then settled.
  function initiate(CrossChainOrder memory order, bytes calldata signature) {
    // This code is the basic process for validating and pulling in tokens
    // for a Permit2-based order.
    // It's somewhat involved, but it does most of the work in validating the
    // order and signature.
    permit2.permitWitnessTransferFrom(
      // PermitTransferFrom struct init
      IPermit2.PermitTransferFrom({
        permitted: IPermit2.TokenPermissions({
          token: order.inputToken,
          amount: order.inputAmount
        }),
        nonce: order.nonce,
        deadline: order.deadline
      }),
      // SignatureTransferDetails struct init
      IPermit2.SignatureTransferDetails({
        to: address(this),
        requestedAmount: order.inputAmount
      }),
      order.swapper,
      keccak256(abi.encode(order));
      ORDER_WITNESS_TYPESTRING,
      signature
    );
    
    // Pull in the bond from the msg.sender.
    IERC20(order.inputToken).safeTransferFrom(msg.sender, order.relayerBondAmount);
    
    // Full input amount for Across's purposes both the user amount
    // and the bond amount.
    // In the case that the relay is filled correctly, the relayer
    // gets the full input amount (including the bond).
    // In the case that the depositor is refunded, they receive the bond
    // as compensation for the relayer's failure to fill.
    uint256 amount = order.inputAmount + order.relayerBondAmount;
    
    // Now that all the tokens are in this contract, Across contract needs
    // to be approved to pull the tokens from here.
    IERC20(order.inputToken).safeIncreaseAllowance(address(spokePool), amount);
    
    // Fill deadline is arbitrarily set to 1 hour after initiation.
    uint256 fillDeadline = block.timestamp + 3600;
    
    // Call deposit to pass the order off to Across Settlement.
    spokePool.deposit(
      order.swapper,
      order.recipient,
      order.inputToken,
      order.outputToken,
      order.inputAmount,
      order.outputAmount,
      order.destinationChainId,
      order.relayer,
      block.timestamp,
      fillDeadline, // 1 hour deadline
      fillDeadline, // Exclusivity for the entire fill period
      "" // No message
    );
  }
}

Conclusion

As is shown in the example above, Across Settlement can be used as a tool to verify crosschain intent fulfillment in many different setups. The primary advantage is that the integrating protocol can abstract away the complexity of the verification and fulfillment, so they don't have to deal with the security, timing, and asynchrony challenges of building a crosschain system.

Across Settlement provides additional advantages over naive crosschain settlement systems, which ultimately lead to better execution of intent fulfillment for users and relayers:

  1. Relayer Crosschain Management: With Across’ settlement architecture, repayment is made on the relayer’s chain of choice, reducing overhead and complexity of managing crosschain positions. This lowers costs for relayers, enabling better pricing and execution for end-users. It is enabled by Across’ Hub and Spoke model, where passive LPs extend loans to relayers for taking on time-value risk as funds are rebalanced through canonical bridges by the protocol.

Aggregated and Optimistic Verification: The Across Settlement system aggregates valid fills events off-chain to create a repayment bundle, which is then optimistically verified by . This verification and repayment mechanism scales gas cost of repayment at O(1) instead of O(N) with the number of fills. This offers an order of magnitude in gas savings vs. other approaches and ultimately leads to better pricing for users and more profit for relayers.

🚀
Across Discord
UMA's Optimistic Oracle