Skip to main content

Calling onchain from EVMx

EVMx allows you to call smart contracts deployed on other blockchains in a way that feels familiar to standard contract interactions. This capability enables your decentralized applications to seamlessly operate across multiple blockchains.

Basic contract calls​

To call a function on an onchain contract from EVMx, you use a special forwarder address that represents the onchain contract within the EVMx environment. The call syntax is similar to regular Solidity contract calls, with the addition of the async modifier.

Here's a simple example of a value increase function where the onchain call does not return any values:

function increaseOnchain(uint256 amount, address forwarder) external async {
ISomeContract(forwarder).increase(amount);
// (optional) Promise-based pattern to handle asynchronous data retrieval
IPromise(forwarder).then(this.someFunction.selector, abi.encode(someDataToShareWithPromise));
}

Key components​

  • Async Modifier: The async modifier signals that this function will perform operations that interact with blockchains.
  • Forwarder Address: Instead of calling the contract directly, you call a forwarder address that routes your call to the correct contract on the target blockchain.

↘ See a reference implementation of this functionality here.

Sequential batch calls​

One powerful feature of EVMx is the ability to make sequential batch calls to multiple contracts or chains within a single function. Since async functions work with a transaction queue, all calls are processed in order.

Consider this chain-abstracted value update example:

function transfer(uint256 amount, address forwarderChainA, address forwarderChainB) external async {
// First burn tokens on the source chain
ISomeContract(forwarderChainA).increase(amount);
// (optional) Promise-based pattern to handle asynchronous data retrieval
IPromise(forwarderChainA).then(this.someFunction.selector, abi.encode(someDataToShareWithPromise));
// Then mint tokens on the destination chain
ISomeContract(forwarderChainB).decrease(amount);
// (optional) Promise-based pattern to handle asynchronous data retrieval
IPromise(forwarderChainB).then(this.someFunction.selector, abi.encode(someDataToShareWithPromise));
}

The operations are executed in sequence, ensuring that the decrease on chain B happens after the increase on chain A is confirmed.

Chain-abstracted workflow​

The diagram below illustrates how the chain-abstracted batch call works:

Chain-abstracted workflow

The process involves:

  1. An increase operation on the Chain A Forwarder
  2. Forwarding through SOCKET's EVMx
  3. A decrease operation on the Chain B Forwarder
  4. Communication between forwarders and the SOCKET Protocol

Best practices​

  • Chain-Specific Logic: Consider the specific requirements of each blockchain you're interacting with
  • Error Handling: Implement proper error handling for chain-abstracted operations
  • Gas Optimization: Be mindful of gas costs across different chains
  • Transaction Sequencing: Carefully plan the order of operations when making multiple calls

By following these patterns, you can create powerful chain-abstracted applications that seamlessly interact with contracts across multiple blockchains.

Common errors​

Seeing Failed to estimate EIP1559 fees when running EVMx scripts or cast commands

Please ensure you have --legacy flag when running the commands.

Seeing Failed to estimate gas for tx when running EVMx scripts or cast commands

Please ensure you have --with-gas-price 0 flag when running scripts and --gas-price 0 flag when running commands.

I cannot see transactions for my new AppGateway on the EVMx explorer

Please confirm you have updated the APP_GATEWAY variable on the .env file.

If you have exported your .env file, please confirm that the variable is up to date on your environment.

Deploying onchain contracts is reverting with 0x8d53e553 - InsufficientFees()

Please confirm you have deposited enough to pay for fees.

Calling onchain contracts via EVMx is reverting with 0xb9521e1a - AsyncModifierNotUsed()

Please confirm the function you're calling has the async modifier as it is expected to wait for a promise since it is either reading or writing information onchain. See key components for onchain calls.

Calling onchain contracts via EVMx is reverting with generic EVM error

Please confirm you are passing the forwarder contract address and not the onchain contract address. See key components for onchain calls.