DEV Community

Husni Rizal
Husni Rizal

Posted on

Building a Frontend for a Rust-Based RISC-V Smart Contract on Polkadot: The Flipper Example

NOTE:
This tutorial builds on top of a really nice post
by Bader Youssef about writing RISC-V Rust contracts on Polkadot.
Be sure to read it first beforehand!

Hey folks, this is Husni, a software engineer with almost five years of experience in blockchain and full-stack development. I've spent most of my professional career diving deep into Polkadot's ecosystem, tinkering with everything from Substrate nodes to dApps.

Recently, I got my hands on this neat little project: a Rust-based smart contract running on PolkaVM, which compiles to RISC-V for that bare-metal efficiency. The example is the classic "Flipper" contract, which toggles a boolean value, but pairing it with a frontend really brings it to life. The codebase is up on GitHub.

After poking around the web and X for frontend tooling, I found that Parity and the Web3 Foundation haven't rolled out anything specific yet for these Rust-style contracts. So I leaned on Ethereum-compatible libs like wagmi and viem, leveraging Polkadot's JSON-RPC adapter. It works surprisingly well, and community repos like this one are stepping in with basic hooks and UI bits.

Let me walk you through why this matters, how to get it running, and some detailed breakdowns of the code. This article is my perspective as someone who's built and broken plenty of these setups.

Why Bother with a Frontend?

Look, most users aren't going to fire up a terminal to poke at a smart contract. They want an app, with something that they can interact with and get real-time feedback. That's where a frontend shines: it turns your Rust logic into something clickable, like flipping that boolean in Flipper. It makes the tech accessible, pulling in users who wouldn't touch a CLI.

Plus, seeing it visualized sparks ideas. I've used simple UIs like this to brainstorm bigger things, like interacting with on-chain governance proposals or token swaps in dApps. It lowers the entry barrier, letting more devs experiment and push the Polkadot ecosystem forward.

A few more perks I've noticed:

  • Wider Reach: Mobile and web users can jump in without installing tools, growing your audience beyond hardcore devs.
  • Better Debugging: A visual layer helps spot contract quirks faster, which is great for teaching newbies too.
  • Showcasing Efficiency: PolkaVM's perks, like cheaper fees and multi-lang support, really pop when demoed in a real app, nudging folks away from plain old EVM.
  • Hybrid Plays: It proves Rust contracts can mingle with Solidity ones using the same frontend stack, opening doors for mixed dApps.

Setting It Up: The Nuts and Bolts

This project splits into a Rust backend for the contract and a Next.js frontend. It taps Polkadot's Ethereum compat layer for smooth sailing.

Tech Stack

  • Contract Side: Rust in no_std mode, PolkaVM for RISC-V, Foundry's cast for JSON-RPC deploys.
  • Frontend: Next.js for React stuff, wagmi for wallets and hooks, viem for contract connection, TypeScript to keep type-safe. Tools: Rust/Cargo, Foundry, Node/npm.
  • Network: Connect to Polkadot testnet at this URL, or spin up a local node.

Step-by-Step Setup

  1. Clone it:
git clone https://github.com/ical10/flipper-pvm.git && cd flipper-pvm
Enter fullscreen mode Exit fullscreen mode
  1. Backend tools: Grab Rust/Cargo if needed, then

cargo install --force --locked cargo-pvm-contract

Install Foundry via

curl -L https://foundry.paradigm.xyz | bash && foundryup

  1. Build the contract:

cd contracts && cargo build

then it will generate target/flipper.debug.polkavm

  1. Deploy: Set envs like
export ETH_RPC_URL="https://services.polkadothub-rpc.com/testnet"
export PRIVATE_KEY=0xYourTestKey
Enter fullscreen mode Exit fullscreen mode


plaintext
Then

cast send --private-key $PRIVATE_KEY --create "$(xxd -p -c 99999 target/flipper.debug.polkavm)" --json
Enter fullscreen mode Exit fullscreen mode


plaintext
Jot down the address.

  1. Frontend:
cd frontend && npm install
Enter fullscreen mode Exit fullscreen mode


plaintext
Add .env.local with

NEXT_PUBLIC_CONTRACT_ADDRESS=0xYourAddress
NEXT_PUBLIC_RPC_URL=https://services.polkadothub-rpc.com/testnet
Enter fullscreen mode Exit fullscreen mode

Fire it up with npm run dev.

Boom – you're up and running locally, frontend talking to the contract.

How It All Hangs Together

The Rust contract compiles to RISC-V bytecode, deploys through Polkadot's Revive pallet (handles EVM and PVM), and the frontend uses Ethereum-like calls to interact.

Run the backend post-deploy with cast call for reads or cast send for writes. What about the frontend? npm run dev loads it at localhost:3000. Connect a wallet like MetaMask, see the state, hit "Flip".

The flow:

  1. Wallet connect via wagmi.
  2. Query get() with viem to show true/false.
  3. Button triggers flip() tx via wagmi.
  4. Tx hits JSON-RPC, PolkaVM runs Rust, updates storage, emits event.
  5. Frontend refreshes the state.

It's a bare-bones UI: state display and flip button. Under the hood, the contract uses get_storage/set_storage for the boolean. Frontend makes it feel like any Ethereum dApp, it is abstraction at its finest.

Code Deep Dive

Codebase splits: contracts/ for backend, frontend/ for UI.

Backend Bits

  • Cargo.toml: Rust deps like alloy-sol-types for ABI, pallet-revive-uapi for host calls; with RISC-V targets.
  • src/flipper.rs: Core logic in no_stdsol! for ABI, get() checks selector, pulls from storage; flip() toggled -> storage updated -> event emitted.
  • Flipper.sol: Solidity ABI stub for viem encoding.

Frontend Breakdown

  • package.json: Deps – next, react, wagmi, viem, react-query; scripts for dev/build.
  • next.config.ts: Next.js tweaks, like wagmi transpiles.
  • tsconfig.json: TS config for React/Next.
  • app/page.tsx: Center of the dApp – wagmi's useAccount/useConnect for wallets; useContractRead for state; useContractWrite for flips. Simple render: connect, read state, button for updating state. Pulls ABI and address from env.
  • Extras: .prettierrc for clean code, README for tips.

Env handling in .env.local, Next.js app router for structure.

Pros and Cons of the Frontend Setup

The frontend (Next.js with wagmi/viem/React Query/TS) borrows Ethereum maturity for Polkadot. The backend itself gets PolkaVM speed, but frontend's where user magic happens. As a fresh repo (minimal commits), it's got solid stuff but room for growth.

Pros

  • Easy Integration: Wagmi/viem plug right into Ethereum tools.
  • Snappy UX: Next.js SSR/SSG for fast loads; React Query caches and refetches seamlessly.
  • Safe and Modular: TS ensures type-safety; wagmi hooks keep code reusable.
  • Chain Flexibility: Wagmi manages multi-chain, cuts boilerplate.
  • Extensible: Next.js APIs for future backend; font opts boost perf.
  • VM Bridge: Works for Rust or Solidity calls in Polkadot's setup.

Cons

  • Semantic Differences: Revive's "almost compatible" EVM layer has subtle opcode and execution differences that might break viem/wagmi assumptions, causing unexpected errors in reads, writes, or events. References: 1, 2
  • Account & Wallet Glitches: Native Polkadot accounts need manual Ethereum mapping; without it, MetaMask connections fail or signing drops in the frontend. Reference: 1
  • JSON-RPC Adapter Overhead: The proxy might adds latency and translation bugs on spec mismatches, slowing real-time polling and transaction UX. References: 1, 2
  • Tooling & Bytecode Limits: Incomplete EVM bytecode support and partial Hardhat integration force extra hacks, slowing testing and deployment workflows. Reference: 1

Wrapping Up
As a PoC, this frontend nails basics for a Rust contract like Flipper. For beefier stuff with multi-calls, you'll tweak hooks and errors for PVM quirks. Rust PVM's early days mean fast changes from Parity/community. This is great for innovation, but plan for maintenance.

Projects like this are important stepping stone for Polkadot dApps, merging Rust power with web ease. Tools will polish up, speeding adoption. Grab the repo, hack away. It's a killer starting point for frontier tech in Web3. Hit me up if you tweak it!

Top comments (0)