Web3SoliditySecurity

Building Secure Staking Platforms with Solidity & Web3.js

A deep dive into creating production-ready staking contracts with daily reward distribution and security best practices.

HJ
Hassan Javed
December 2025
8 min read

Introduction

Staking platforms are at the core of DeFi — allowing users to lock their tokens and earn rewards over time. But building one that's secure, gas-efficient, and production-ready takes careful planning.

In this article, I'll walk through the architecture and key decisions behind a staking platform I built for a client using Solidity and Web3.js.

Smart Contract Architecture

The staking contract needs three core functions:

**stake()** — Users deposit tokens into the contract
**unstake()** — Users withdraw their staked tokens
**claimReward()** — Users claim accumulated daily rewards

function stake(uint256 _amount) external {

require(_amount > 0, "Cannot stake 0");

stakingToken.transferFrom(msg.sender, address(this), _amount);

stakedBalance[msg.sender] += _amount;

lastStakeTime[msg.sender] = block.timestamp;

emit Staked(msg.sender, _amount);

}

Security Considerations

1. **Reentrancy Protection** — Always use ReentrancyGuard from OpenZeppelin

2. **Integer Overflow** — Solidity 0.8+ has built-in overflow checks

3. **Access Control** — Only admin can set reward rates

4. **Timelock** — Add minimum staking period to prevent flash loan attacks

Frontend Integration with Web3.js

The DApp frontend connects to the contract using Web3.js or Ethers.js. Key interactions:

Connect wallet (MetaMask)
Approve token spending
Call stake/unstake/claim functions
Display real-time reward calculations

Reward Calculation

Daily rewards are calculated based on:

Amount staked
Duration staked
Annual Percentage Yield (APY)

const dailyReward = (stakedAmount * APY) / 365 / 100;

const totalReward = dailyReward * daysSinceLastClaim;

Key Takeaways

Always audit your contracts before deployment
Use proxy patterns for upgradeability
Test extensively on testnets before mainnet
Keep the frontend simple and user-friendly
Monitor gas costs and optimize where possible

Building secure staking platforms requires a deep understanding of both smart contract development and frontend integration. The combination of Solidity's security patterns with Web3.js's flexibility makes it possible to create robust DeFi applications.

solidity
function stake(uint256 _amount) external { require(_amount > 0, "Cannot stake 0"); stakingToken.transferFrom(msg.sender, address(this), _amount); stakedBalance[msg.sender] += _amount; lastStakeTime[msg.sender] = block.timestamp; emit Staked(msg.sender, _amount); }
javascript
const dailyReward = (stakedAmount * APY) / 365 / 100; const totalReward = dailyReward * daysSinceLastClaim;