Chainfusion starter
No matter what setup you pick from below, run ./deploys.sh
from the project root to deploy the EVM contract, generate a couple of events and deploy the chainfusion starter canister. To understand the steps involved in deploying the project locally, examine the comments in deploy.sh
.
Make sure you have you have Docker and VS Code installed and running, then click the button below
Make sure that Node.js >= 21
, foundry, caddy and dfx >= 0.18
are installed on your system.
Run the following commands in a new, empty project directory:
git clone https://github.com/letmejustputthishere/chainfusion-starter.git # Download this starter project
cd chainfusion-starter # Navigate to the project directory
The Chainfusion canister has been structured in a way that all the coprocessing logic lives in src/dappcon_backend/src/job.rs
and developers don't need to recreate or touch the code responsible for fetching new events, creating signatures or sending transactions. They can solely focus on writing jobs to run upon receiving a new event from an EVM smart contract.
You can find the full flow in the following sequence diagram with Ethereum as an example EVM chain (note that this flow can be applied to any EVM chain):
Here you can find a number of examples leveraging the Chainfusion starter logic:
- On-chain asset and metadata creation for ERC721 NFT contracts
Build your own use-case on top of the Chainfusion starter and share it with the community! Some ideas you could explore:
- A referral canister that distributes rewards to users based on their interactions with an EVM smart contract
- A ckNFT canister that mints an NFT on the ICP when an EVM helper smart contract emits an
ReceivedNft
, similar to theEthDepositHelper
contract the ckETH minter uses. This could enable users to trade NFTs on the ICP without having to pay gas fees on Ethereum.
This project demonstrates how to use the Internet Computer as a coprocessor for EVM smart contracts. The coprocessor listens to events emitted by an EVM smart contract, processes them, and optionally sends the results back. Note that way say EVM smart contracts, as you can not only interact with the Ethereum network, but other networks that are using the Ethereum Virtual Machine (EVM), such as Polygon and Avalanche.
This is an early project and should be considered as a proof of concept. It is not production-ready and should not be used in production environments. There are quite some TODOs in the code which will be addressed over time. If you have any questions or suggestions, feel free to open an issue, start a discussion or reach out to me on the DFINITY Developer Forum or X.
The concept of coprocessors originated in computer architecture as a technique to enhance performance. Traditional computers rely on a single central processing unit (CPU) to handle all computations. However, the CPU became overloaded as workloads grew more complex.
Coprocessors were introduced to offload specific tasks from the CPU to specialized hardware. We see the same happening in the EVM ecosystem. EVM smart contracts, and Ethereum in particular, are a very constrained computing environment. Coprocessors and stateful Layer 2 solutions enable to extend the capabilities of the EVM by offloading specific tasks to more powerful environments.
You can read more about coprocessors in the context of Ethereum in the article "A Brief Into to Coprocessors". The first paragraph of this section was directly taken from this article.
Canister smart contracts on ICP can securely read from EVM smart contracts (using HTTPS Outcalls or the EVM RPC canister) and write to them (using Chain-key Signatures, i.e. Threshold ECDSA). Hence, there are no additional parties needed to relay messages between the two networks, and no additional work needs to be done on the EVM side to verify the results of the computation as the EVM smart contract just needs to check for the proper sender.
Furthermore, canister smart contracts have many capabilities and properties that can be leveraged to extend the reach of smart contracts:
- WASM Runtime, which is much more efficient than the EVM, and allows programming in Rust, JavaScript, and other traditional languages (next to Motoko).
- 400 GiB of memory with the cost of storing 1 GiB on-chain for a year only being $5
- Long-running computations that even allow running AI inference.
- HTTPS Outcalls allow canisters to interact with other chains and traditional web services.
- Chain-key signatures allow canisters to sign transactions for other chains, including Ethereum and Bitcoin.
- Timers allow syncing with EVM events and scheduling other tasks.
- Unbiasable randomness provided by the threshold BLS signatures straight from the heart of ICP's Chain-key technology.
- Serve webcontent directly from canisters via the HTTP gateway protocol
- The reverse gas model frees end users from paying for every transaction they perform
- ~1-2 second finality
- Multi-block transactions
For more context on how ICP can extend Ethereum, check out this presentation from EthereumZuri 2024.
The contract Coprocessor.sol
emits an event NewJob
when the newJob
function is called. The newJob
function sends all funds to the account controlled by the chainfusion_backend
canister and emits the event.
The contract also has a callback
function that can only be called by the chainfusion_backend
canister. This function is called by the chainfusion_backend
canister to send the results of the processing back to the contract.
The source code of the contract can be found in src/foundry/Coprocessor.sol
.
For local deployment of the EVM smart contract and submitting transactions we use foundry. You can take a look at the steps needed to deploy the contract locally in the deploy.sh
script which runs script/Coprocessor.s.sol
.
The chainfusion_backend
canister listens to events emitted by the Ethereum smart contract by periodically calling the eth_getLogs
RPC method via the EVM RPC canister. When an event is received, the canister can do all kinds of synchronous and asynchronous processing. When the processing is done, the canister sends the results back by creating a transaction calling the callback
function of the contract. The transaction is signed using threshold signatures and sent to the Ethereum network via the EVM RPC canister.
You can learn more about how the EVM RPC canister works and how to integrate with it here.