All projects
ArchivedNov 2025 → Dec 2025

GrimStake

A full-stack Web3 staking application built with Solidity, Hardhat, Next.js, Wagmi, RainbowKit, and viem. Grim Stake is a testnet staking platform.

Gallery

Grim Stake — Testnet Staking dApp

A full-stack Web3 staking application built with Solidity, Hardhat, Next.js, Wagmi, RainbowKit, and viem.
Grim Stake is a testnet staking platform demonstrating:

  • ERC-20 staking
  • Real-time rewards
  • Claiming rewards
  • Unstaking
  • Pool analytics (TVL, APR, reward rate)
  • Auto-adding tokens to MetaMask

Deployed live on Sepolia Testnet.

Preview


Table of Contents

Overview

Architecture

Smart Contracts

  • MockERC20Token.sol
  • GrimStake.sol

Backend Deployment Guide

Frontend Setup

Frontend Features

Hook Architecture

User Workflow

Project Structure

Running the Frontend

CoinMarketCap Integration

Overview

Grim Stake provides a fully functional staking environment:

  • Stake ERC-20 test tokens
  • Earn block-based rewards
  • Claim and unstake at any time
  • Add tokens directly to MetaMask
  • Live statistics from contract reads
  • Modern UI built with Tailwind, RainbowKit, Framer Motion

All functionality runs on Sepolia Testnet.

Architecture

Backend

  • Solidity smart contracts managed via Hardhat
  • Pools and reward accounting handled in GrimStake

Frontend

  • Next.js dApp using Wagmi v2, viem, and RainbowKit

Smart Contracts

MockERC20Token.sol

A lightweight ERC-20 token with:

  • mint(address,uint256)
  • approve
  • transfer
  • transferFrom

Constructor:

constructor(string memory _name, string memory _symbol)

Deploy multiple variants by changing constructor arguments.

GrimStake.sol

Maintains staking pools and rewards.

Pool Structure

Pool {
uint256 totalStaked;
uint256 rewardRatePerSecond;
}

User Structure

UserInfo {
uint256 amount;
uint256 rewardDebt;
}

Key Functions

  • addPool(token, rewardRate)
  • stake(token, amount)
  • unstake(token, amount)
  • pendingRewards(user, token)
  • claim(token)
  • getPoolStats(token)
  • getUserStake(user, token)

Backend Deployment Guide

1. Clone the Repository

git clone https://github.com/YOUR_REPO/grim-vault.git
cd grim-vault/grim-contract
npm install

2. Compile Contracts

npx hardhat compile

3. Deploy Using Remix (Testnet)

GrimStake

  • Open GrimStake.sol
  • Compile
  • Select "Injected Provider – MetaMask"
  • Deploy and copy the contract address

MockERC20

Deploy multiple tokens as needed:

Example:

name: GrimToken
symbol: GRIM

4. Add Token Pool

addPool(<TokenAddress>, <RewardRatePerSecond>)

Fast-demo example:

1e17

5. Fund the Reward Pool

mint(<admin>, 10000e18)
transfer(<GrimStake>, 5000e18)

Frontend Setup

cd ../frontend
npm install

Wagmi Codegen (wagmi.config.ts):

deployments: {
GrimStake: {
11155111: "0x...grimstake"
}
}

Generate typed contracts:

npx wagmi generate

Creates: src/generated.ts

Frontend Features

  • Token selection
  • Add token to MetaMask
  • Approve + stake
  • Unstake
  • Claim rewards
  • Live pool stats
  • User position
  • Neon glass UI with animations

Hook Architecture

Hook

Role

useStake

Handles approve + stake lifecycle

useUnstake

Unstaking workflow

useClaimRewards

Reward claims

usePendingRewards

Real-time reward tracking

usePoolStats

TVL, APR, rewardRate

useUserStakeInfo

User stake amount

useApprove

ERC-20 approve using MockERC20 ABI

User Workflow

Connect wallet to Sepolia

Add GRIM token to MetaMask

Mint test tokens

Approve + stake

Watch rewards accumulate

Claim rewards

Unstake

Project Structure

grim-vault/
├─ grim-contract/
│ ├─ contracts/
│ │ ├─ GrimStake.sol
│ │ └─ MockERC20Token.sol
│ ├─ hardhat.config.js
└─ frontend/
├─ src/generated.ts
├─ lib/contracts/
├─ components/
├─ public/
└─ app/

Running the Frontend

npm run dev

URL: http://localhost:3000

CoinMarketCap Integration

Displays:

  • Market price
  • 24h price change
  • Market cap

1. Add keys to .env.local

NEXT_PUBLIC_CMC_API_KEY=<YOUR_API_KEY>

2. Fetch Helper

export async function fetchCMCPrice(symbol: string) {
const key = process.env.NEXT_PUBLIC_CMC_API_KEY;

const res = await fetch(
`https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest?symbol=${symbol}`,
{ headers: { 'X-CMC_PRO_API_KEY': key } }
);

const json = await res.json();
return json.data[symbol];
}

3. Use in Pool Overview

const [price, setPrice] = useState(null);

useEffect(() => {
fetchCMCPrice(selected.symbol).then((p) => {
setPrice(p.quote.USD);
});
}, [selected]);

4. Render

Market Price: $ {price?.price.toFixed(2) ?? "—"}
24h Change: {price?.percent_change_24h.toFixed(2) ?? "—"} %
Market Cap: $ {price?.market_cap.toLocaleString() ?? "—"}

End