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:
The process involves:
- An increase operation on the Chain A Forwarder
- Forwarding through SOCKET's EVMx
- A decrease operation on the Chain B Forwarder
- 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.
- See how to Deposit fees.
- Check your AppGateway fee balance.
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.