DEV Community

IG
IG

Posted on

Building the Foundation: Smart Contracts and Serverless Backend

ARTICLE 1: Smart Contracts & Backend Infrastructure

Introduction

In this first part of our three-part series, we'll build the blockchain foundation for a decentralized raffle platform. By the end, you'll have deployed smart contracts to Lisk Sepolia testnet and set up Firebase Cloud Functions to serve blockchain data without gas costs.

What You'll Learn:

  • Deploying provably fair raffle contracts
  • Creating custom ERC20 test tokens
  • Setting up serverless blockchain APIs
  • Best practices for contract security

Prerequisites:

  • Node.js 18+ installed
  • Basic Solidity knowledge
  • Firebase account
  • Lisk Sepolia testnet ETH (Get from faucet)

Part 1: Understanding the Architecture

The Three-Layer System

┌─────────────────────────────────────────┐
│   Layer 3: Flutter Mobile App           │
│   (User Interface - Article 2)          │
└─────────────┬───────────────────────────┘
              │
┌─────────────▼───────────────────────────┐
│   Layer 2: Firebase Functions           │
│   (Serverless API - This Article)       │
└─────────────┬───────────────────────────┘
              │
┌─────────────▼───────────────────────────┐
│   Layer 1: Smart Contracts              │
│   (Blockchain Logic - This Article)     │
│   ├── RaffleToken (RTKN)                │
│   └── SoccerRaffle                      │
└─────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

Why This Architecture?

  • Layer 1 (Smart Contracts): Handles money and trust — must be on blockchain
  • Layer 2 (Cloud Functions): Handles reads — no gas costs for users browsing
  • Layer 3 (Flutter App): Handles UX — hides blockchain complexity

Part 2: Smart Contract Development

2.1: The Test Token (RaffleToken)

Most tutorials skip this, but production apps need custom tokens for:

  • Testing: Faucet functionality for easy user onboarding
  • Control: You manage supply and distribution
  • Branding: Custom name/symbol for your platform

Why 6 Decimals?

Real USDT uses 6 decimals (not 18 like ETH). Matching this prevents confusion when users see balances.

Create contracts/RaffleToken.sol

Key Concepts:

  • decimals(): Controls display precision

    • 6 decimals → 1 RTKN = 1,000,000 smallest units
    • Example: 100.5 RTKN = 100,500,000 units on-chain
  • faucet(): Allows anyone to claim tokens

    • Simplifies testing (no buying/transferring needed)
    • In production, replace with controlled distribution

2.2: The Raffle Contract (SoccerRaffle)

This is the heart of our platform. It manages all raffle logic with these critical features:

Security Mechanisms

  • Commit-Reveal Randomness

    • Creator commits hash of secret seed before raffle ends
    • Reveals seed after to generate winner
    • Prevents manipulation (can’t pick winner beforehand)
  • Emergency Draw

    • If creator doesn’t reveal seed within 1 hour
    • Anyone can trigger fallback randomness
    • Ensures raffles always conclude
  • ReentrancyGuard

    • Prevents reentrancy attacks on token transfers
    • Critical for financial contracts

Create contracts/SoccerRaffle.sol


Part 3: Hardhat Setup & Deployment

3.1: Project Initialization

# Create project directory
mkdir soccer-raffle
cd soccer-raffle

# Initialize Node project
npm init -y

# Install Hardhat
npm install --save-dev hardhat

# Initialize Hardhat project
npx hardhat init
# Select: "Create a TypeScript project"

# Install dependencies
npm install --save-dev @nomicfoundation/hardhat-toolbox
npm install @openzeppelin/contracts dotenv
Enter fullscreen mode Exit fullscreen mode

3.2: Configure Hardhat

Create hardhat.config.ts:


3.3: Create .env File

# Get private key from MetaMask:
# Settings → Security & Privacy → Show Private Key

DEPLOYER_PRIVATE_KEY=your_private_key_here
LISK_TESTNET_RPC=https://rpc.sepolia-api.lisk.com
Enter fullscreen mode Exit fullscreen mode

⚠️ CRITICAL: Add .env to .gitignore immediately!


3.4: Deployment Scripts

Deploy RaffleToken First.
Create scripts/deployRaffleToken.ts:


3.5: Deploy to Lisk Sepolia

# Step 1: Deploy token
npx hardhat run scripts/deployRaffleToken.ts --network liskTestnet

# Copy the token address and add to .env:
# USDT_ADDRESS=0x07Aa1131A1C06B4680458b0547528272BB603358

# Step 2: Deploy raffle contract
npx hardhat run scripts/deploySoccerRaffle.ts --network liskTestnet

# Step 3: Verify contracts (optional but recommended)
npx hardhat verify --network liskTestnet 0xYOUR_TOKEN_ADDRESS
npx hardhat verify --network liskTestnet 0xYOUR_RAFFLE_ADDRESS 0xYOUR_TOKEN_ADDRESS "Soccer Raffle Token" "SRT"
Enter fullscreen mode Exit fullscreen mode

Expected Output:

✅ RaffleToken deployed at: 0x07Aa1131A1C06B456758b0547528272BB603358
✅ Deployer balance: 10000000.0 RTKN

✅ SoccerRaffle deployed at: 0x5c6A781D663B689b7922A6339AD3eDe910023C6d
Enter fullscreen mode Exit fullscreen mode

Part 4: Firebase Cloud Functions

4.1: Why Cloud Functions?

Problem: If users need ETH just to VIEW raffles, 99% will bounce.
Solution: Firebase Functions act as free RPC proxy.

✅ Users browse raffles with zero gas costs
✅ Only pay gas when joining
✅ Dramatically improves conversion funnel


4.2: Functions Setup

# Install Firebase CLI
npm install -g firebase-tools

# Login
firebase login

# Initialize Firebase in project
firebase init functions

# Select:
# - TypeScript
# - ESLint: Yes
# - Install dependencies: Yes
Enter fullscreen mode Exit fullscreen mode

4.3: Install Dependencies

cd functions
npm install ethers
Enter fullscreen mode Exit fullscreen mode

4.4: Contract ABI Configuration

Create functions/src/contracts/SoccerRaffleABI.ts:

Key Concept: Human-Readable ABIs

// Traditional (verbose)
{
  "name": "getRaffleDetails",
  "type": "function",
  "stateMutability": "view",
  "inputs": [{"name": "raffleId", "type": "uint256"}],
  "outputs": [{"name": "creator", "type": "address"}, ...]
}

// Human-readable (clean)
"function getRaffleDetails(uint256 raffleId) view returns (address creator, ...)"
Enter fullscreen mode Exit fullscreen mode

4.5: Cloud Functions Implementation

Create functions/src/index.ts:


4.6: Deploy Functions

cd functions
npm run build
firebase deploy --only functions
Enter fullscreen mode Exit fullscreen mode

4.7: Test Your Functions

# Test getActiveRaffles
curl https://us-central1-your-project.cloudfunctions.net/getActiveRaffles

# Test getRaffleDetails
curl -X POST \
  https://us-central1-your-project.cloudfunctions.net/getRaffleDetails \
  -H "Content-Type: application/json" \
  -d '{"raffleId": "1"}'

# Test getTokenBalance
curl -X POST \
  https://us-central1-your-project.cloudfunctions.net/getTokenBalance \
  -H "Content-Type: application/json" \
  -d '{"address": "0x74Ba7b9E6B10DE652b1Cbf9d2B187943d7b5C617"}'
Enter fullscreen mode Exit fullscreen mode

Part 5: Creating Test Raffles

5.1: Test Raffle Script

Create scripts/createTestRaffle.ts:

Run it:

# Add raffle address to .env
RAFFLE_CONTRACT_ADDRESS=0x5c6A781D663B689b7975A6339AD3eDe910023C6d

# Create test raffle
npx hardhat run scripts/createTestRaffle.ts --network liskTestnet
Enter fullscreen mode Exit fullscreen mode

Part 6: Security Best Practices

6.1: Smart Contract Security

✅ Implemented:

  • ReentrancyGuard on all state-changing functions
  • SafeERC20 for token transfers
  • Access control (Ownable)
  • Pausable functionality
  • Input validation on all parameters

⚠️ Additional Recommendations:

  • Professional Audit (OpenZeppelin / Trail of Bits)
  • Bug Bounty Program
  • Gradual Rollout with low stakes
  • Consider Nexus Mutual coverage

6.3: Deployment Checklist

Before Mainnet:

  1. Smart contracts audited
  2. All tests passing
  3. Gas optimization completed
  4. Admin keys secured (multisig)
  5. Monitoring via Tenderly/Defender
  6. Emergency pause tested
  7. Legal compliance verified

Conclusion: What We’ve Built

Deployed Infrastructure:

  • RaffleToken (RTKN) — 10M supply with 6 decimals, faucet enabled
  • SoccerRaffle Contract — commit-reveal randomness, emergency draw
  • Firebase Cloud Functions — 8 endpoints, zero-gas reads

Key Takeaways:

  1. Test Tokens Simplify User Onboarding
  2. Commit-Reveal Is Essential for Fairness
  3. Cloud Functions Improve UX
  4. Always Deploy Token First

Next Steps

In Article 2, we’ll build the Flutter mobile app that connects to these contracts:

  • Automatic wallet creation
  • Seamless token approval
  • Real-time transaction monitoring
  • Beautiful, gas-free UX

Coming Up:

  • Flutter project architecture
  • Web3Dart integration
  • Riverpod state management
  • Transaction lifecycle handling

Resources

Deployed Contracts:

  • RaffleToken: 0x07Aa1131A1C06B4680458b0547528272BB603358
  • SoccerRaffle: 0x5c6A781D663B689b7975A6339AD3eDe910023C6d

Documentation:

Tools:

Questions or issues? Drop a comment below or open an issue on GitHub!

END OF ARTICLE 1

Top comments (0)