Batched Transactions
Ever since the launch of Flow EVM, it's been possible to supercharge your EVM apps by using Flow Cadence features and contracts. Some benefits, such as native VRF and inexpensive gas without compromising security are built in and either easy or automatic to use. Others, such as the ability to use Cadence to structure and call EVM transactions, are powerful but complicated to configure and use. They also require developers to manage concurrent connections to both networks.
FLIP 316 improves the Flow Client Library (FCL) to support cross-VM functionality between Flow EVM and Flow Cadence.
For EVM developers, this means that you can use the familiar wagmi, viem, and rainbowkit stack you're used to, add FCL, and get features like multi-call write with one signature for users with a Cadence-compatible wallet.
In this tutorial, you'll learn how to create a hybrid application and use some basic cross-VM features.
The FCL functionality described in this tutorial is in alpha. Some steps may change. We'll keep the tutorial updated, but please create an issue or let us know on Discord if something isn't working for you.
Objectives
After completing this guide, you'll be able to:
- Build an app that seamlessly integrates Flow Cadence and Flow EVM connections
- Add Cadence features to your Rainbowkit/wagmi/viem app
- Utilize Flow Client Library (FCL) to enable multi-call contract writes to Flow EVM
Prerequisites
Next.js and Modern Frontend Development
This tutorial uses Next.js. You don't need to be an expert, but it's helpful to be comfortable with development using a current React framework. You'll be on your own to select and use a package manager, manage Node versions, and other frontend environment tasks. If you don't have your own preference, you can just follow along with us and use npm.
Solidity and Cadence Smart Contract Development
Apps using the hybrid approach can interact with both Cadence and Solidity smart contracts. You don't need to be an expert in either of these, but it's helpful to be familiar with how smart contracts work in at least one of these languages.
Onchain App Frontends
We're assuming you're familiar with wagmi, viem, and rainbowkit. If you're coming from the Cadence, you might want to take a quick look at the getting started guides for these platforms. They're all excellent and will rapidly get you up to speed on how the EVM world commonly connects their apps to their contracts.
Getting Started
For this tutorial, we'll be starting from a fork of the FCL + RainbowKit + Wagmi Integration Demo built by the team.
Fork the repo so you can push your work freely to your own copy, then follow the setup instructions.
Project Overview
Open the cross-vm app scaffold in your editor, run it, and view the site in your browser:
You'll see:
Connect with a Cadence-compatible wallet.
In a production app, you'll want to manage this process carefully. Non-Cadence EVM wallets may be able to connect, but they will not be able to use any Cadence features.
Send Batch Transactions
The first demo built into this scaffold is multi-call contract write.
On Flow, this isn't an unstable experimental feature - it's a demonstration of the power of EVM + Cadence.
Click Send Batch Transaction Example
and approve the transaction. You'll see three lines appear on the page, similar to:
Currently, the Flow wallet sponsors all gas for all transactions signed with the wallet on both testnet and mainnet!
Cadence Parent Transaction
The first line is the transaction id of the Flow Cadence transaction that calls both of the EVM transactions. Search for it in Testnet Cadence Flowscan.
Cadence transactions are more complicated than those in Solidity contracts. Rather than being restricted to running functions present on the contract, they can run arbitrary code as long as the caller has access to all of the resources required by the transaction.
You can see the code of the transaction in the Script
tab, but we've included it here for convenience:
In this case, it's checking that the caller of the Cadence transaction has permission to control to the EVM account, which is built in for Cadence Owned Accounts. The execute
phase then iterates through the EVM transactions and uses the Cadence accounts own permissions to sign the EVM transactions.
The loop also handles a check for the optional flag to cancel all of the transactions if any one of them fails. In other words, you could set up a 20 transaction arbitrage attempt and unwind everything if it fails at any step!
EVM Child Transactions
The next two lines show the transaction hashes for the EVM transactions. You can view this in Testnet EVM Flowscan by searching for the transaction hashes, the same as any other.
Look up both transactions.
The first is calling the deposit()
function to wrap FLOW and move it to EVM.
The second is calling the ERC-20 approve()
function to give another address the authority to spend those tokens.
For the demo, the code for this is hard-coded into src/app/page.tsx
:
It's called with the useBatchTransaction
hook via the sendBatchTransaction(calls)
function.
Code Evaluator
The demo also has an embedded code evaluator that you can use to experiment with snippets of code from fcl
or wagmi
.
For example:
Will return your Cadence address. This snippet:
Returns the current Cadence VM block number.
Calling Your Own Contract
Next, we'll update the starter to connect to and call functions in our own contract. For this, we'll use a simple Button Clicker Contract. You can deploy your own copy, or use the one deployed at 0xA7Cf2260e501952c71189D04FAd17c704DFB36e6
.
Set Up Contract Imports
The following steps assume deployment with Hardhat Ignition. If you are using a different deployment method, import the contract address and abi as appropriate.
In your fork of the app, add a folder called contracts
to the src
folder. In it, copy over ['deployed_addresses.json] from
ignition/deployments/chain-545in the Button Clicker repo, and
ignition/deployments/chain-545/ClickTokenModule#ClickToken.json`.
Next, create a folder called constants
and add a file called contracts.ts
to it.
In it, import the contract artifact and addresses file, and create export a constant with this information.
Build Traditional Functionality
This isn't a wagmi tutorial, so we'll give you some components to speed up the process. Add a folder called components
inside src
and add the following files.
TheButton.tsx
TopTenDisplay.tsx
Content.tsx
Then, import and add <Content />
to page.tsx
:
You'll now see the button and scoreboard from the contract. Test it out and earn a few points!
Supercharge your EVM App With Cadence
Now let's supercharge it. With the power of Cadence, you can use multi-call write and give your users way more tokens with a single click and single signature!
For the first pass, we'll skip some organization best practices.
Import clickToken
into page.tsx
and update calls
to instead call the mint
function from the Button Clicker contract.
Try clicking the Send Batch Transaction Example
button again. You'll have to manually refresh the page when the EVM transaction hash appears to see the score update. We haven't wired in the query invalidation yet.
Next, use some JavaScript to put 10 copies of the transaction call into the array:
Click the button again and manually refresh page once the transaction hashes appear.
You just minted 10 tokens from 10 transactions with one signature!
Conclusion
In this tutorial, you reviewed the demo starter for building hybrid applications that utilize a common EVM stack and integrate with Flow Cadence. You then added functionality to interface with another contract that mints ERC-20 tokens. Finally, you supercharged your app by using the power of Cadence for EVM multi-call contract writes.
Now that you have completed the tutorial, you should be able to:
- Build an app that seamlessly integrates Flow Cadence and Flow EVM connections
- Add Cadence features to your Rainbowkit/wagmi/viem app
- Utilize Flow Client Library (FCL) to enable multi-call contract writes to Flow EVM