| Variable | Where | Risk if leaked |
|---|---|---|
PRIVATE_KEY |
root .env |
Full contract control — CRITICAL |
RELAYER_PRIVATE_KEY |
frontend/.env.local |
Can trigger streak updates — HIGH |
CELOSCAN_API_KEY |
frontend/.env.local |
Rate limit abuse — LOW |
BASESCAN_API_KEY |
frontend/.env.local |
Rate limit abuse — LOW |
Please report security vulnerabilities by opening a private GitHub security advisory at: https://github.com/wkalidev/dailydrop/security/advisories/new
Do NOT open public issues for security vulnerabilities.
Self-audited on 2026-06-13, re-audited on 2026-07-01, and re-audited on 2026-07-18 covering contracts, API routes, SDK, and environment configuration.
The 2026-07-01 pass fixed a critical issue where /api/relayer accepted any successful transaction
hash as proof of check-in without verifying it was sent by the claimed user to the real DailyDrop
contract — see git history for frontend/app/api/relayer/route.ts.
The 2026-07-18 pass fixed: (1) contracts/dailydrop.clar's update-streak-from-relayer accepting an
arbitrary caller-supplied new-streak with no replay/rate-limit protection — the Stacks side had
never received the anti-forgery fix already applied to StreakMaster.sol; (2)
contracts/dailydrop.clar's mint-initial having no supply cap, unlike DailyDrop.sol's
MAX_INITIAL_SUPPLY; (3) the NEXT_PUBLIC_RELAYER_SECRET false-security issue described above.
No third-party audit yet. Use at your own risk.
- Farcaster Frame signature not verified —
/api/frameusesuntrustedData. Full production use requires hub-based signature verification (Neynar or a self-hosted Farcaster Hub). Reflected values fromuntrustedDataare now encoded before being embedded in the frame HTML response. - Leaderboard is address-based — sourced from on-chain transactions for known contracts. Not exhaustive; new users appear as they interact.
- StreakMaster relayer requires trust — the relayer operator can submit any check-in for any user. Mitigated by
CHECKIN_INTERVALenforcement on-chain, theusedTxProofsreplay prevention map, and (as of 2026-07-01)/api/relayervalidating that the submittedtxHashis a confirmed transaction sent by the claimed user to the real DailyDrop contract emitting aCheckIn/RewardClaimedevent. /api/relayerhas no shared-secret gate — a prior version accepted anx-relayer-secretheader sourced fromNEXT_PUBLIC_RELAYER_SECRET, but anyNEXT_PUBLIC_*value is inlined into the public JS bundle, so it was never actually secret and gave a false sense of protection. It has been removed (2026-07-18). Authentication is purely the on-chain receipt check: the route independently re-verifies via RPC thattxHashis a successful transaction sent by the claimeduserto the real DailyDrop contract, emitting a genuineCheckIn/RewardClaimedevent — so a caller cannot fabricate a relay for an address they don't control, and relaying someone else's genuine check-in cannot redirect rewards away from them. Abuse/spam is bounded by the per-address rate limit (3/hour).- Base reward minting may be inactive —
StreakMaster._triggerRewardcallsDailyDrop(base).mintInitial(), which requiresStreakMasterto be theowner()of the BaseDailyDropcontract. As of this audit,deploy.tsnever performs thattransferOwnership, and on-chain inspection shows the BaseDailyDropowner does not match theStreakMasteraddress — reward mints triggered via the relayer path on Base are likely failing silently (caught by atry/catch). Verify on-chain ownership and runtransferOwnershipfrom the current owner key if this is unintentional.