This section provides a complete guide for enabling ISMP support for solidity contracts deployed on substrate chains.

Runtime Modifications

The following guide assumes you have pallet-ismp and pallet-evm configured for the runtime.
The first step in orchestrating ISMP support for solidity contracts deployed on substrate based EVM chains is to set up the ISMP module for the EVM. The EvmIsmpModule acts as a proxy, it receives all messages on behalf of all contracts then executes the required callback on the target contract.
Adding this proxy module to your ISMP router is very trivial, a guide is given below:
use ismp_evm::module::EvmIsmpModule; pub struct YourModuleRouter; impl IsmpRouter for YourModuleRouter { fn module_for_id(bytes: Vec<u8>) -> Result<Box<dyn IsmpModule>, ismp::Error> { let module_id = ModuleId::from_bytes(&bytes)?; let handler = match module_id { // This ensures all messages to evm contracts are routed to the proxy module ModuleId::EVM(_) => Ok(Box::new(EvmIsmpModule::<Runtime>::default())) _ => Err(ismp::Error::ModuleNotFound(bytes))?, }; Ok(handler) } }
The diagram presents a visual representation of how the module interacts with both pallets
Image without caption


For contracts to be able to dispatch requests and responses, they need to interact with pallet-ismp , solidity contracts can only interact with the substrate runtime through precompiles.
We have implemented three separate precompiles for dispatching requests and post responses.
The recommended address at which these precompiles should be deployed are prescribed below, this is to ensure uniformity for contract deployments across all chains.
Post request dispatch precompile address
Get request dispatch precompile address
Post response dispatch precompile address

Dispatching requests and responses

When dispatching requests and responses to the runtime, the contract needs to abi encode the DispatchPost, DispatchGet or PostResponse that is expected by the precompile, to ensure correct encoding and avoid decoding errors in the precompile execution, a library has been provided in ismp-solidity that exports functions that handle all interactions with the precompiles. This library assumes the precompiles are deployed at the addresses prescribed in the previous section.
You can import SubstrateHost.sol library from ismp-solidity and call the dispatch function to interact with the precompiles.
Below is an example of an interaction with the precompiles in solidity code:
function transfer( address to, bytes memory dest, uint64 amount, uint64 timeout, uint64 gasLimit ) public { _burn(msg.sender, amount); Payload memory payload = Payload({ from: msg.sender, to: to, amount: amount }); DispatchPost memory dispatchPost = DispatchPost({ body: abi.encode(payload.from,, payload.amount), dest: dest, timeoutTimestamp: timeout, to: abi.encodePacked(address(12)), gaslimit: gasLimit }); // Interact with precompile by calling the dispatch function on // the SubstrateHost library SubstrateHost.dispatch(dispatchPost); emit BalanceBurnt(); } function dispatchGet( bytes memory dest, bytes[] memory keys, uint64 height, uint64 timeout, uint64 gasLimit ) public { DispatchGet memory get = DispatchGet({ keys: keys, dest: dest, height: height, timeoutTimestamp: timeout, gaslimit: gasLimit }); // Interact with precompile by calling the dispatch function on // the SubstrateHost library SubstrateHost.dispatch(get); emit GetDispatched(); }

Module interface

Solidity contracts using ISMP need to implement the ismp module interface so they can receive messages from the runtime. The ismp module interface for solidity defined as IIsmpModule is available in ismp-solidity . One important security recommendation is that the functions provided by this interface must only be callable by the ismp-evm host address. This ensures that only the ismp-evm module is authorised to call any of the module callbacks.
The ismp-evm host address is defined as:
Below is an example implementation of the module interface:
address constant HOST = 0x843b131BD76419934dae248F6e5a195c0A3C324D; contract IsmpDemo is IIsmpModule { using SubstrateHost for *; // restricts call to `Host` modifier onlyIsmpHost() { if (msg.sender != HOST) { revert NotIsmpHost(); } _; } function onAccept(PostRequest memory request) public onlyIsmpHost { } function onPostResponse(PostResponse memory response) public onlyIsmpHost { } function onGetResponse(GetResponse memory response) public onlyIsmpHost { } function onGetTimeout(GetRequest memory request) public onlyIsmpHost { } function onPostTimeout(PostRequest memory request) public onlyIsmpHost { } }

Powered by Notaku