A decentralized raffle application built on Ethereum and Abstract networks where users can buy tickets for a chance to win the entire jackpot. The application features a continuously rolling pot, where each ticket has a configurable chance to win the growing jackpot. If a player wins, they receive the pot (minus a small fee) and the pot resets.
- Multi-Network Support: Works on Sepolia Testnet and Abstract Testnet
- Connect with Any Wallet: MetaMask, WalletConnect, or Privy embedded wallets
- Buy Single or Multiple Tickets: Purchase up to 10 tickets at once
- Real-Time Updates: Activity feed shows recent tickets purchased and winners
- Customizable Parameters: Admin can customize ticket price, fees, and win probability
- Create Your Own Raffle: Users can deploy their own raffle contracts with custom settings
- Mobile Friendly: Responsive design works on all devices
The project consists of:
-
Smart Contracts:
RollingRaffle.sol: Main contract handling ticket purchases, prize calculations, and pseudo-random winning mechanicsRaffleFactory.sol: Contract factory to create new Rolling Raffle instances with fee splittingFeeSplitter.sol: Handles fee distribution between raffle creator and platform
-
Frontend:
- React application with ethers.js for blockchain interaction
- Privy for user authentication and wallet connection
- React Router for navigation between different raffles
-
Deployment Scripts:
- Scripts for deploying to Sepolia and Abstract networks
- Hardhat tasks for contract administration
The main raffle contract that:
- Processes ticket purchases
- Contains a pseudo-random win determination mechanism
- Maintains the pot balance
- Distributes fees to the fee collector
- Pays out jackpots to winners
- Allows admin configuration of parameters
Key parameters:
ticketPrice: Cost per ticket in ETH (default: 0.0025 ETH)ticketFeePercentage: Fee taken from each ticket (default: 10%)jackpotFeePercentage: Fee taken from jackpot winnings (default: 5%)winChance: The chance to win (default: 1 in 20, or 5%)
Factory contract that:
- Creates new RollingRaffle contracts
- Sets up fee splitting between the creator and platform
- Tracks all created raffles
- Allows pagination through created raffles
Handles fee distribution:
- Splits fees 50/50 between the raffle creator and the platform
- Automatically distributes ETH when received
- Node.js (v16+)
- Yarn or npm
- Git
- Clone the repository:
git clone https://github.com/heyimsteve/evmraffle.git
cd evmraffle- Install dependencies:
npm install --legacy-peer-deps
# or
yarn- Create a
.envfile in the root directory with the following variables:
SEPOLIA_RPC_URL=https://sepolia.infura.io/v3/YOUR_INFURA_KEY
PRIVATE_KEY=your_wallet_private_key
ETHERSCAN_API_KEY=your_etherscan_api_key
VITE_INFURA_ID=your_infura_id
- Start the development server:
npm run dev
# or
yarn dev- Open http://localhost:3000 in your browser.
- Compile contracts:
npx hardhat compile- Run tests:
npx hardhat test- Deploy to Sepolia testnet:
npx hardhat run scripts/deploy.js --network sepolia
# or
npm run deploy:sepolia- Deploy to Abstract testnet:
npx hardhat run scripts/deploy-abstract.js --network abstractTestnet
# or
npm run deploy:abstract- Deploy a Factory contract:
npx hardhat run scripts/deploy-factory.js --network sepoliaThe project includes Hardhat tasks for managing deployed contracts:
# View contract info
npx hardhat raffle:info --network sepolia
# Rescue ETH
npx hardhat raffle:rescue-eth --network sepolia
# Update ticket price to 0.0035 ETH
npx hardhat raffle:update-ticket-price 0.0035 --network sepolia
# Update ticket fee percentage to 8%
npx hardhat raffle:update-ticket-fee 8 --network sepolia
# Update jackpot fee percentage to 12%
npx hardhat raffle:update-jackpot-fee 12 --network sepolia
# Update win chance to 1 in 25
npx hardhat raffle:update-win-chance 25 --network sepolia
# Update fee collector address
npx hardhat raffle:update-fee-collector 0xYourNewAddressHere --network sepolia
# Transfer contract ownership
npx hardhat raffle:transfer-ownership 0xNewOwnerAddressHere --network sepolia- Click "Connect Wallet" to connect using MetaMask, WalletConnect, or a Privy embedded wallet.
- Select the network you wish to use (Sepolia or Abstract Testnet).
- Select the quantity of tickets you want to purchase (1-10).
- Click "Buy Ticket" or "Buy X Tickets".
- Confirm the transaction in your wallet.
- A jackpot wheel animation will show while the transaction is processing.
- You'll be notified if you won the jackpot!
- Connect your wallet.
- Click "Create Raffle" button.
- Configure your raffle parameters:
- Ticket Price
- Ticket Fee Percentage
- Jackpot Fee Percentage
- Win Chance (1 in X)
- Fee Collector Address (optional)
- Deploy the contract by clicking "Deploy Raffle Contract".
- Once deployed, you'll be redirected to your new raffle.
If you're the owner of a raffle contract, you'll see an Admin dropdown with options to:
- Drain Jackpot (withdraw funds to owner)
- Update Ticket Price
- Update Ticket Fee
- Update Jackpot Fee
- Update Fee Collector Address
- Update Win Rate
rolling-raffle-dapp/
├── contracts/ # Smart contract source files
│ ├── RollingRaffle.sol # Main raffle contract
│ └── RaffleFactory.sol # Factory contract for creating raffles
├── scripts/ # Deployment scripts
│ ├── deploy.js # Deploy RollingRaffle to Sepolia
│ ├── deploy-abstract.js # Deploy to Abstract network
│ └── deploy-factory.js # Deploy factory contract
├── tasks/ # Hardhat tasks
│ └── raffle-tasks.js # Tasks for managing raffles
├── src/ # Frontend React application
│ ├── App.jsx # Main application component
│ ├── components/ # UI components
│ └── contracts/ # Compiled contract ABIs
├── hardhat.config.cjs # Hardhat configuration
└── vite.config.js # Vite configuration
Default contract addresses are configured in src/App.jsx:
const CHAIN_CONFIG = {
// Sepolia
11155111: {
name: "Sepolia Testnet",
contractAddress: "0xBf889381DEEA45F83DFc3183F0869368eEA7d1B4",
explorerUrl: "https://sepolia.etherscan.io"
},
// Abstract Testnet
11124: {
name: "Abstract Testnet",
contractAddress: "0xA5785b8987f6E61a635315E6C77E2C852EEBAB0F",
explorerUrl: "https://sepolia.abscan.org"
}
};Factory contract addresses are in src/CreateRaffleModal.jsx:
const FACTORY_CONFIG = {
// Sepolia
11155111: {
address: "0x77A2624a746A97fA900c1C1C744e458d1Cd6bdBF",
name: "Sepolia Testnet",
explorerUrl: "https://sepolia.etherscan.io"
},
// Abstract Testnet
11124: {
address: "0xe986d9beb28019f70f80390665D952a450597Ec0",
name: "Abstract Testnet",
explorerUrl: "https://sepolia.abscan.org"
}
};Privy authentication is configured in src/main.jsx:
const privyAppId = "cm99ldj3z004pl20myevh3m13";- Pseudo-random Number Generation: The contract uses block data for randomness, which is not cryptographically secure. In a production environment, it would be better to use Chainlink VRF.
- Rate Limiting: The frontend includes extensive handling for RPC rate limiting, but you may still encounter issues if interacting too frequently.
- Gas Optimization: The contracts could be further optimized for gas usage, especially for multi-ticket purchases.
- Add Chainlink VRF integration for truly random number generation
- Add time-based jackpot bonuses
- Implement additional networks (Ethereum Mainnet, Arbitrum, etc.)
- Create raffle templates with predefined settings
- Add social features (leaderboards, sharing, etc.)
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.