Skip to content

Creating a Cross-Chain UserOperation with EIL SDK

The EIL SDK is designed to promote declarative code via the builder pattern. However, this guide focuses on the readability of individual lines instead.

Step 1. Create the CrossChainBuilder

This is the main object you will use to construct the Cross-Chain UserOperation. It is responsible for coordinating the creation, signing, execution, and cleanup for the multiple actions required to make a Cross-Chain operation.

const crossChainBuilder: ICrossChainBuilder = sdk.createBuilder()

Step 2. Create the necessary batches

Each "batch" contains a set of actions to be executed on the specified chain.

These actions will be performed as a single UserOperation on that chain, using the underlying Smart Account batching feature. Depending on the signature scheme being used, this UserOperation may be authorized by its own individual signature, or by the EIL multi-chain signature.

Note: Gas payment is not automatically covered by the EIL SDK. In general, the user is expected to pay gas on at least one of the chains involved, either directly or by using a non-EIL Paymaster contract.

const batchBuilder: BatchBuilder = crossChainBuilder.startBatch(chainId)

Step 3. Supply all desired actions for the current chain

The action is represented by an instance of a BaseAction interface.

The EIL SDK provides the following actions:

  1. ApproveAction - issue an ERC-20 token approval
  2. TransferAction - transfer an ERC-20 token
  3. CallAction - make a call to the specified to address with the provided data
  4. FunctionCallAction - encode data and make a call to the specified target contract functionName with args
  5. VoucherRequestAction - request from the EIL Cross-Chain Liquidity Providers (XLPs) to move assets from the current chain to destinationChainId chain.
  6. SetVarAction - similar to FunctionCallAction, expects a uint256 or bytes32 return value to be assigned as a value of the setVar Runtime Variable

Example usage:

import { parseAbi } from 'viem'

const name = 'John'
const abi = parseAbi([
  'function helloWorld(string name) external',
])

batchBuilder.addAction(new FunctionCallAction({
  target: targetAddress,
  functionName: 'helloWorld',
  args: [name],
  abi: abi,
  value: 0n
}))

Step 4. Build, sign, and execute the prepared batch

Once all desired actions are provided to the crossChainBuilder and its batches, the resulting Cross-Chain UserOperation needs to be signed, with a signature verifiable by the Smart Accounts used on appropriate chains.

The EIL SDK does not require a specific signature scheme. We do define the default EIL Single Cross-Chain Signature format, and we recommend all Smart Accounts add support to it at their earliest convenience.

const callback = (type: CallbackType, action: SingleChainBatch, index: number, revertReason?: string) => {
    console.log('action executed: ', type, action, index, revertReason)
}

const signedCrossChainBatch: CrossChainExecutor = await crossChainBuilder.buildAndSign()
await signedCrossChainBatch.execute(callback)

Execution Callback

The callback parameter of the execute function allows your application to observe the progress and errors occurring during the execution of a Cross-Chain UserOperation. This execution is potentially a long, multistep, multi-transaction, multi-chain process with retriable steps, and the CallbackType enum provides the necessary insight using the following values:

export enum CallbackType {
  // submitting a UserOperation for execution
  Executing = 'executing',
  // userOperation completed execution
  Done = 'done',
  // UserOperation execution reverted
  Failed = 'failed',
  // before executing: UserOperation is waiting for vouchers to be signed by previous UserOperations
  // (called after those previous UserOperations are executed and submitted their voucher requests)
  WaitingForVouchers = 'waitingForVouchers',
  // a voucher was signed by a provider. called just before "executing".
  VoucherSigned = 'voucherSigned'
}

Receiving the assets moved across chains

When using the VoucherRequestAction action type, the EIL SDK will prepare the assets to be moved to the destination chain. However, the assets will not automatically appear on the destination chain.

You can request to activate all requested Vouchers for a given chain with the useAllVouchers() function.

crossChainBuilder
    .startBatch(chainId)
    .useAllVouchers()

Troubleshooting

Waiting For Vouchers Time Out

The most likely issue to arise when using the EIL SDK is a failure to acquire the requested Voucher object. The Voucher is used in EIL to move assets, such as Native ETH or ERC-20 tokens, from the origin chain to the destination.

However, as this is not a purely technical action and has economic consequences and risk for the involved parties, there is no guarantee a suitable Cross-Chain Liquidity Provider (XLP) can be found.

The application can try to mitigate the issue by doing the following:

  1. Increase the maximum fee paid to the XLP The fee structure of the EIL ensures a fair market-rate fee is charged by the XLPs. It is possible that the application is requesting a Voucher below the current market rate.

  2. Lower the values used when filtering the XLPs