Like2Win
Follow + Like = Win $DEGEN
The problem Like2Win solves
Like2Win - Supporting the DEGEN Ecosystem
🎯 Our Mission
Recognize and reward users who support the DEGEN ecosystem through the tipping system - the engine of Farcaster's economy.
💜 Why DEGEN Deserves Recognition
DEGEN has transformed Farcaster by creating:
- Real economy - Tips that give monetary value to social interaction
- Authentic incentives - Rewards for quality content
- Community building - Tips create genuine connections
- Mass adoption - Thousands of daily active users
Like2Win exists to reward those who make this possible: DEGEN tippers.
🎮 Fair Recognition System
DEGEN Tippers 🪙
- Follow @Like2Win + LIKE = 1 ticket
- Why: You already contribute to the ecosystem with tips
Regular Users 👥
- Follow @Like2Win + LIKE + RECAST + COMMENT = 1 ticket
- Why: Free participation requires maximum engagement
= Same ticket, effort proportional to your DEGEN ecosystem contribution
🚀 Impact
- For DEGEN ecosystem: Recognition for its most valuable supporters
- For tippers: Rewards for keeping the economy running
- For Farcaster: More engagement and viral growth
- For everyone: Fair system where contribution = benefits
🎯 Simple Proposition
"We reward those who make the DEGEN economy work with simplified raffle participation, while maintaining democratic access for everyone."
Bi-weekly raffles | DEGEN prizes | Automatic system | Fair for all
Like2Win: Where your support for the DEGEN ecosystem becomes real winning opportunities.
Challenges I ran into
🐛 Critical Smart Contract Compilation Issues
OpenZeppelin v5 Breaking Changes
Problem: The smart contract wouldn't compile in Remix due to deprecated OpenZeppelin patterns:
// This failed ❌
constructor(address _degenToken) {
degenToken = IERC20(_degenToken);
}
// Missing required parameter for Ownable
Solution: Updated to OpenZeppelin v5 syntax:
// This worked ✅
constructor(address _degenToken) Ownable(msg.sender) {
require(_degenToken != address(0), "Invalid token address");
degenToken = IERC20(_degenToken);
}
Also had to replace deprecated toEthSignedMessageHash():
// Old way ❌
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
messageHash.toEthSignedMessageHash()
// New way ✅
import "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";
using MessageHashUtils for bytes32;
messageHash.toEthSignedMessageHash()
🔧 TypeScript Compilation Nightmares
Implicit 'any' Parameter Errors
Problem: API routes failing with cryptic TypeScript errors:
// This crashed ❌
const totalTickets = userTickets.reduce((sum, ut) => sum + ut.tickets, 0);
// Error: Parameter 'ut' implicitly has an 'any' type
Solution: Added explicit typing:
// This worked ✅
const totalTickets = userTickets.reduce((sum: number, ut: any) => sum + ut.tickets, 0);
NextResponse vs Plain Object Returns
Problem: Mixing NextResponse with plain objects in internal functions caused runtime crashes:
// This was broken ❌
function executeDailyRaffleInternal() {
return NextResponse.json({ success: true }); // Wrong context!
}
Solution: Separated concerns properly:
// This worked ✅
async function executeDailyRaffleInternal() {
// Internal logic returning plain objects
return { success: true, winner: selectedWinner };
}
export async function POST() {
const result = await executeDailyRaffleInternal();
return NextResponse.json(result); // Wrap at API boundary
}
📦 Mysterious Missing Dependencies
The tslib.es6.mjs Mystery
Problem: Server crashing on startup with:
Error: ENOENT: no such file or directory, open 'node_modules/tslib/tslib.es6.mjs'
Solution: Found the file was nested in a subdirectory and manually copied it:
cp node_modules/@metamask/sdk/node_modules/tslib/tslib.es6.mjs node_modules/tslib/
This was a dependency resolution issue where the main tslib installation was incomplete.
🗄️ Prisma Integration Failures
Client Initialization Issues
Problem: Prisma client randomly failing to initialize in development:
Error: @prisma/client did not initialize yet. Please run "prisma generate"
Solution: Created fallback API without Prisma dependencies:
// Created /api/automation/daily-raffle-simple/route.ts
// Simulates all functionality without database calls
export async function POST(request: NextRequest) {
// Pure simulation logic that always works
return NextResponse.json({
success: true,
message: 'Full daily cycle completed (simulated)',
simulation: { /* mock data */ }
});
}
🤖 GitHub Actions YAML Syntax Hell
Escape Character Nightmares
Problem: Workflow file with malformed YAML:
This was broken ❌
run: |
curl -X POST ${{ secrets.VERCEL_URL }}
-d "{"action": "${{ github.event_name }}", "authorization": "${{ secrets.AUTOMATION_SECRET }}"}"
Solution: Simplified and properly escaped:
This worked ✅
run: |
curl -X POST ${{ secrets.VERCEL_URL }}
-H "Content-Type: application/json"
-d '{"action": "full_daily_cycle", "authorization": "${{ secrets.AUTOMATION_SECRET }}"}'
🔐 Smart Contract Security Vulnerabilities
Signature Replay Attacks
Problem: Original contract was vulnerable to replay attacks:
// Vulnerable ❌
bytes32 messageHash = keccak256(abi.encodePacked(raffleId, _participant, _ticketCount, block.timestamp));
// Attacker could replay old signatures
Solution: Added nonce system:
// Secure ✅
mapping(address => uint256) public userNonces;
bytes32 messageHash = keccak256(abi.encode(raffleId, _participant, _ticketCount, _nonce));
require(_nonce == userNonces[_participant], "Invalid nonce");
userNonces[_participant]++; // Increment after use
🚀 Key Learnings
- Always check OpenZeppelin version compatibility before deployment
- Type everything explicitly in TypeScript, even if it seems obvious
- Keep fallback systems for critical dependencies like databases
- Test YAML syntax thoroughly before pushing to production
- Security audit early - vulnerabilities are easier to fix during development
The most valuable lesson: Build redundant systems. The fallback API saved the entire project when Prisma failed, allowing continuous development and
testing while debugging the main system in parallel.
Smart Contract Address(es)
0x6dd600a1afac3d0921ea588adf58d96c39c052e4
Other Onchain Proof
Project: Like2Win - Daily DEGEN Raffles on FarcasterSmart Contract: 0x6dd600a1afac3d0921ea588adf58d96c39c052e4
(Base)Token Integration: DEGEN (0x4ed4E862860beD51a9570b96d89aF5E1B0Efefed)Funding Amount: 3,500 DEGEN tokensTraction:
Automated daily rewards system with real token distribution
Tracks Applied (1)
Top 5 New Mini Apps
Technologies used
Cheer Project
Cheering for a project means supporting a project you like with as little as 0.0025 ETH. Right now, you can Cheer using ETH on Arbitrum, Optimism and Base.
