Building Your First Token-Gated Staking App on Rootstock (With RIF Tokens & Thirdweb)


Let me tell you about the time I built my first token-gated staking dApp on Rootstock. It was one of those projects that started as a "what if" idea and turned into a really rewarding learning experience.
I remember sitting there with my coffee, staring at the Rootstock documentation, wondering how to combine Bitcoin's security with Ethereum's smart contract flexibility.
Turns out, it's not as complicated as I thought - and I'm going to walk you through exactly how to do it.
Why This Project Changed How I Think About Web3
When I first heard about token-gating, I'll admit I was skeptical.
But after implementing it with RIF tokens, I saw how powerful it can be for creating exclusive communities. What really surprised me was how smoothly everything worked on Rootstock.
The Bitcoin-level security gave me peace of mind, while the EVM compatibility meant I could use all my favorite Ethereum tools.
Getting Started: What You'll Need
Before we dive in, let's get your workspace ready:
Node.js v18+ (Trust me, try Bun - it's like npm but after three cups of coffee)
MetaMask (We'll configure it for Rootstock together)
A Thirdweb account (It's free, and it saved me hours of deployment headaches)
Basic React/Solidity knowledge (Don't worry, we'll take it step by step)
I remember when I first set this up - I spent an embarrassing amount of time trying to configure MetaMask before realizing I'd typoed the Chain ID. Learn from my mistakes!
Step 1: Why Rootstock and RIF Tokens?
Here's what got me excited: Rootstack isn't just another Ethereum clone. It's:
Secured by Bitcoin's mining power (through something called merged mining)
EVM-compatible (meaning all your Ethereum tools work)
Uses RBTC for gas (which is pegged 1:1 with Bitcoin)
And RIF tokens? They're like the Swiss Army knife of the Rootstock ecosystem. We'll use them to create our token-gating mechanism - only RIF holders can stake in our dApp.
Step 2: Setting Up Your Environment
Installing Bun (My New Favorite Tool)
Remember when package installations took forever? Bun changes that. Just run:
“`curl -fsSL https://bun.sh/install | bash`”
The first time I ran this, I may or may not have fist-pumped when I saw how fast it was.
Configuring MetaMask for Rootstock
Here are the settings that worked for me:
Network Name: Rootstock Testnet
RPC URL: https://public-node.testnet.rsk.co
Chain ID: 31 (This is the one I kept forgetting)
Currency Symbol: tRBTC
Pro tip:
You can also add to the list - Rootstock Networks to MetaMask Automatically
“Bookmark the Rootstock faucet” - “you'll need testnet RBTC”.
Getting the Starter Code
git clone https://github.com/lovesonnuel/TokenGated.git
You can also add Rootstock Networks to MetaMask Automatically
bun install
When I first cloned this, I was pleasantly surprised by how clean the structure was. It saved me so much boilerplate setup.
Step 3: Building the Staking Contract
This is where things get interesting. Let me share the key insights I learned while building the token-gating mechanism.
The RIF Balance Check (This Took Me a Few Tries)
Here's the implementation that finally worked for me:
solidity
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract RIFGatedStaking { // RIF Token Addresses - I messed these up the first time! address public constant RIF_TESTNET = 0x19F64674D8A5B4E652319F5e239eFd3bc969A1fE; address public constant RIF_MAINNET = 0x2aCc95758f8b5F583470bA265Eb685a8f45fC9D5;
mapping(address => uint256) public stakingBalance;
function stake(uint256 amount) external {
require(
checkRIFBalance(msg.sender) >= 1 ether,
"You need at least 1 RIF to stake - go grab some first!"
);
_stake(msg.sender, amount);
}
function checkRIFBalance(address user) internal view returns (uint256) {
IERC20 rifToken = IERC20(RIF_TESTNET); // Remember to change to mainnet!
return rifToken.balanceOf(user);
}
function _stake(address user, uint256 amount) internal {
// Actual staking logic goes here
stakingBalance[user] += amount;
}
}
The first time I tested this, I forgot to switch to testnet RIF tokens in my wallet. Rookie mistake!
Step 4: Deploying with Thirdweb
I was skeptical about using another platform for deployment, but Thirdweb genuinely surprised me. Here's how it went:
Go to Thirdweb Dashboard
Selected "Deploy New Contract" → "Staking" template
Configured with:
Name: My First RIF Staking
Description: Learning as I go!
Click deploy and confirmed in MetaMask
The whole process took about 3 minutes. I timed it.
Step 5: Building the Frontend
This was the fun part - seeing everything come together. Here's the component that made me feel like a real Web3 developer:
javascript
import { useContract, useContractRead } from "@thirdweb-dev/react";
function StakingInterface() { const { contract } = useContract("YOUR_CONTRACT_ADDRESS"); const { data: stakedBalance } = useContractRead( contract, "getStakingBalance", [userAddress] );
const stakeTokens = async (amount) => { try { await contract.call("stake", [amount]); alert("Success! Your tokens are now staked."); } catch (error) { console.error("Oops, something went wrong:", error); } };
return (
Your Staked Balance: stakedBalance | '0'
<button onClick={() => stakeTokens(10)}> Stake 10 Tokens </button>
);}
The first time I saw "Success!" alert pop up? Magical.
Lessons Learned (The Hard Way)
Testnet vs Mainnet: I once wasted an hour debugging before realizing I was on the wrong network. Now I always double-check.
Gas Estimates: Rootstock transactions need a bit more gas than I initially thought. Adding 20% to the estimate solved my failed transactions.
Token Addresses: Writing down the correct RIF addresses saved me countless headaches:
Testnet: 0x19F64674D8A5B4E652319F5e239eFd3bc969A1fE
Mainnet: 0x2aCc95758f8b5F583470bA265Eb685a8f45fC9D5
Where to Go From Here
This project opened my eyes to what's possible with Rootstock. Some ideas I'm playing with next:
Adding tiered rewards for long-term stakers
Creating a leaderboard for top stakers
Integrating with RIF's other services like storage
If you're as excited about this as I am, come join the conversation in the Rootstock Discord. I'm there pretty regularly, usually asking questions or sharing what I've learned.
Remember, every expert was once a beginner. My first staking contract had bugs that would make you laugh (they still make me cringe). But each mistake taught me something valuable. So dive in, make mistakes, and most importantly - have fun building!
Got stuck? Hit me up on Twitter @lovesonnuel. I'm happy to help fellow developers navigate these waters.
Enjoy!
Wrapping Up
You’ve just built a secure, token-gated staking dApp on Rootstock!
GitHub Repository Link: https://github.com/lovesonnuel/TokenGated.git
What’s Next?
Dive deeper into Rootstock’s docs [here] https://dev.rootstock.io
Optimize gas costs with transaction batching.
Join the Rootstock Discord for help and ideas!
Useful Links
Rootstock Docs https://rootstock.io
Thirdweb Dashboard https://thirdweb.com
Starter Code https://github.com/thirdweb-example/rootstock-staking-dapp
Stuck? Ask in the Rootstock Discord https://discord.gg/rootstock
Other important links
Start experimenting with the Rootstock testnet today.
Developers Overview https://dev.rootstock.io/developers/
Testnet https://explorer.testnet.rootstock.io/
Engage with Rootstock on social media, join webinars, and participate in discussions.
Socials:
Follow on X: https://x.com/rootstock_io?s=21
Follow on Instagram: https://www.instagram.com/rootstock_io?igsh=OW0ydHBlNTQyZmZo
Discord: https://discord.com/invite/rootstock
Subscribe to my newsletter
Read articles from Emmanuel Uzodinma directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
