DEV Community

tanisha aggarwal
tanisha aggarwal

Posted on

Building a DeFi Staking Platform on SCAI Mainnet with Solidity & React

During my Blockchain Internship at EtherAuthority, I built a fully functional DeFi staking platform from scratch — a smart contract deployed on SCAI Mainnet, a React frontend connected via MetaMask, and real-time blockchain event tracking. Here's everything I learned.
🔗 Live Demo & Code

Live App: https://defi-staking-platform-wc8n.vercel.app
GitHub: https://github.com/Tanisha-aggarwal1085/Defi-Staking-Platform

What is a DeFi Staking Platform?
A DeFi (Decentralized Finance) staking platform allows users to lock up cryptocurrency tokens in a smart contract and earn rewards over time — similar to a savings account, but fully on-chain with no central authority.
In this project, users can:

Stake SCAI tokens and earn 12% APY
Withdraw their stake at any time (no lock-up period)
Claim accrued rewards
View full transaction history from blockchain events

Tech Stack
LayerTechnologySmart ContractSolidity ^0.8.20DevelopmentHardhatFrontendReact + ViteBlockchain Libraryethers.js v6WalletMetaMaskNetworkSCAI Mainnet (Chain ID: 34)HostingVercel

Smart Contract Design
The core of the platform is Staking.sol. Here's the key logic:
solidity// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract Staking {
uint256 public constant APY = 12;
uint256 public constant YEAR = 365 days;

mapping(address => uint256) public stakes;
mapping(address => uint256) public rewards;
mapping(address => uint256) public lastUpdated;

event Staked(address indexed user, uint256 amount, uint256 newTotal);
event Withdrawn(address indexed user, uint256 amount, uint256 newTotal);
event RewardClaimed(address indexed user, uint256 amount);

function _updateReward(address user) internal {
    if (stakes[user] > 0) {
        uint256 timeElapsed = block.timestamp - lastUpdated[user];
        uint256 earned = (stakes[user] * APY * timeElapsed) / (100 * YEAR);
        rewards[user] += earned;
    }
    lastUpdated[user] = block.timestamp;
}

function stake() public payable {
    require(msg.value > 0, "Amount must be greater than 0");
    _updateReward(msg.sender);
    stakes[msg.sender] += msg.value;
    emit Staked(msg.sender, msg.value, stakes[msg.sender]);
}

function withdraw(uint256 amount) public {
    require(stakes[msg.sender] >= amount, "Not enough stake");
    _updateReward(msg.sender);
    stakes[msg.sender] -= amount;
    (bool success, ) = payable(msg.sender).call{value: amount}("");
    require(success, "Transfer failed");
    emit Withdrawn(msg.sender, amount, stakes[msg.sender]);
}

function claimReward() public {
    _updateReward(msg.sender);
    uint256 reward = rewards[msg.sender];
    require(reward > 0, "No rewards");
    rewards[msg.sender] = 0;
    (bool success, ) = payable(msg.sender).call{value: reward}("");
    require(success, "Transfer failed");
    emit RewardClaimed(msg.sender, reward);
}
Enter fullscreen mode Exit fullscreen mode

}
Key Design Decisions:

Time-based APY — Rewards accrue continuously using block.timestamp
Checks-Effects-Interactions — State changes happen before external calls (reentrancy prevention)
Events — Every action emits an event for transparent on-chain history

Reward Calculation Formula
earned = (stakes[user] × APY × timeElapsed) / (100 × YEAR)
This calculates rewards proportionally — the longer you stake, the more you earn.

Frontend Architecture
The React app uses a Context-based architecture to share blockchain state across all pages:
App.jsx (Router)
├── Web3Context.jsx ← wallet + contract logic
├── Dashboard.jsx ← stake/withdraw/claim UI
├── MyStakes.jsx ← balance overview
├── Transactions.jsx ← blockchain event history
└── About.jsx ← platform info
Connecting to MetaMask with ethers.js v6:
javascriptconst connectWallet = async () => {
const provider = new ethers.BrowserProvider(window.ethereum);
await window.ethereum.request({ method: "eth_requestAccounts" });
const signer = await provider.getSigner();
const walletAddress = await signer.getAddress();
const contract = new ethers.Contract(CONTRACT_ADDRESS, ABI, signer);
// read stake and reward...
};
Network Auto-Switch:
javascriptawait window.ethereum.request({
method: "wallet_switchEthereumChain",
params: [{ chainId: "0x22" }], // SCAI Mainnet = 34
});

Deployment to SCAI Mainnet
javascript// hardhat.config.js
module.exports = {
solidity: "0.8.20",
networks: {
scai: {
url: "https://mainnet-rpc.scai.network",
accounts: [process.env.PRIVATE_KEY],
chainId: 34
}
}
};
bashnpx hardhat run scripts/deploy.js --network scai

Contract deployed to: 0xCd279499974Ac556a7DA538e5F1f1B501E46c14c

Challenges I Faced & How I Solved Them

  1. Invalid Contract Address My first deployment had a 41-character address (should be 40). MetaMask flagged every transaction as suspicious. Fix: Always verify address length after deployment.
  2. Shared Loading State All three buttons (Stake, Withdraw, Claim) showed "Processing..." simultaneously because they shared one loading state. Fix: Created separate stakeLoading, withdrawLoading, claimLoading states.
  3. Wrong Network The app was initially deployed on local Hardhat — mentors couldn't test it. Fix: Deployed to SCAI Mainnet and added automatic network switching.
  4. Transaction History Not Persisting Blockchain events (queryFilter) sometimes failed on SCAI RPC. Fix: Dual approach — immediate in-memory update + async blockchain event sync.

What I Learned
✅ How DeFi staking protocols work under the hood
✅ Writing production-safe Solidity with CEI pattern
✅ Deploying to real mainnets (not just testnets)
✅ Debugging MetaMask transaction issues
✅ Building multi-page Web3 dApps with React

Conclusion
Building this DeFi staking platform gave me hands-on experience with the full blockchain development stack — from smart contract design to frontend deployment. The biggest takeaway: real-world blockchain development is 20% writing code and 80% debugging transactions, network issues, and wallet quirks.
If you want to explore the code or try the live app:

🔗 Live: https://defi-staking-platform-wc8n.vercel.app
📂 GitHub: https://github.com/Tanisha-aggarwal1085/Defi-Staking-Platform

Built during Blockchain Internship at EtherAuthority

Top comments (0)