This is the core smart contract for the Geev decentralized giveaway platform, built on the Stellar blockchain using Soroban.
The Geev Core contract enables decentralized giveaway creation and management with transparent, trustless winner selection. It implements:
- Giveaway Creation: Create giveaways with customizable parameters
- Participant Registration: Users can enter giveaways before the deadline
- Winner Selection: Random selection using ledger-based PRNG after giveaway ends
- Prize Claiming: Winners can claim their prizes once selected
- Random Selection: Uses
env.prng()for pseudo-random number generation - Time-based: Can only execute after the giveaway's
end_time - Status Validation: Only works on
Activegiveaways - Participant Indexing: Maintains
ParticipantIndexmapping for efficient lookup
// Giveaway status states
pub enum GiveawayStatus {
Active, // Accepting entries
Claimable, // Winner selected, prize claimable
Completed, // Prize claimed
Cancelled, // Giveaway cancelled
}
// Winner selection methods
pub enum SelectionMethod {
Random, // Random selection (current implementation)
FirstCome, // First valid entries
Manual, // Manual selection by creator
}
// Main giveaway structure
pub struct Giveaway {
pub id: u64,
pub creator: Address,
pub title: String,
pub description: String,
pub category: String,
pub selection_method: SelectionMethod,
pub winner_count: u32,
pub participant_count: u32,
pub end_time: u64,
pub status: GiveawayStatus,
pub winner: Option<Address>,
pub created_at: u64,
}GiveawayKey(u64)- Store/retrieve giveaways by IDParticipantIndexKey(u64, u32)- Map participant index to addressCounterKey- Generate unique IDsEntryKey(u64)- Store individual entries
Create a new giveaway with specified parameters.
Parameters:
creator: Address- Creator's wallet addresstitle: String- Giveaway titledescription: String- Detailed descriptioncategory: String- Giveaway categoryselection_method: SelectionMethod- How winners are selectedwinner_count: u32- Number of winnersduration_seconds: u64- Duration from creation time
Returns: u64 - Unique giveaway ID
Add a participant to an active giveaway.
Parameters:
giveaway_id: u64- ID of the giveawayparticipant: Address- Participant's wallet addresscontent: String- Entry content/submission
Returns: u64 - Unique entry ID
Select a winner randomly when the giveaway period ends.
Parameters:
giveaway_id: u64- ID of the giveaway
Requirements:
- Giveaway must be
Active - Current time must be after
end_time - Must have at least one participant
Process:
- Validates giveaway status and timing
- Generates random seed using
env.prng().gen::<u64>() - Calculates winner index:
random_seed % participant_count - Retrieves winner address from
ParticipantIndex - Updates giveaway status to
Claimable - Sets winner address in giveaway struct
Returns: Address - Winner's wallet address
Allow winner to claim their prize.
Parameters:
giveaway_id: u64- ID of the giveawayclaimer: Address- Claimer's wallet address
Requirements:
- Giveaway status must be
Claimable - Claimer must be the selected winner
Returns: bool - Success status
Retrieve giveaway details by ID.
Parameters:
giveaway_id: u64- ID of the giveaway
Returns: Option<Giveaway> - Giveaway data or None
let giveaway_id = GiveawayContract::create_giveaway(
env.clone(),
creator_address,
"Free NFT Giveaway".to_string(),
"Win one of 5 exclusive NFTs!".to_string(),
"nft".to_string(),
SelectionMethod::Random,
5, // 5 winners
86400 // 24 hours duration
);let entry_id = GiveawayContract::add_participant(
env.clone(),
giveaway_id,
participant_address,
"I'd love to win this NFT!".to_string()
);// Advance time beyond end_time
env.ledger().with_mut(|li| {
li.timestamp = giveaway.end_time + 1000;
});
// Select winner
let winner_address = GiveawayContract::pick_winner(env, giveaway_id);let success = GiveawayContract::claim_prize(
env,
giveaway_id,
winner_address
);env.prng() which is ledger-based but not cryptographically secure. For production, consider using a more robust randomness source.
- Time-based Execution: Winner selection only possible after
end_time - Status Validation: Prevents manipulation of completed giveaways
- Participant Count: Ensures at least one participant exists
- Address Authentication: Participants must authenticate their actions
Run contract tests with:
cargo testTests cover:
- ✅ Giveaway creation
- ✅ Participant registration
- ✅ Winner selection with proper timing
- ✅ Error handling for edge cases
- ✅ Prize claiming functionality
The contract defines specific error types:
pub enum Error {
GiveawayNotFound = 1,
GiveawayStillActive = 2,
InvalidStatus = 3,
NoParticipants = 4,
NotCreator = 5,
AlreadyCompleted = 6,
InvalidIndex = 7,
ParticipantAlreadyWinner = 8,
}- Build the contract:
soroban build- Deploy to testnet:
soroban deploy --network testnet- Deploy to local sandbox:
soroban deploy --network localThe contract is designed to integrate with the Geev frontend application:
- API Alignment: Contract methods mirror frontend concepts
- Status Synchronization: Giveaway states match frontend expectations
- Error Compatibility: Error codes map to user-friendly messages
Planned improvements:
- 🔐 Cryptographically secure randomness
- 🔄 Multiple winner selection
- 📊 Merit-based selection algorithms
- ⚖️ Dispute resolution mechanisms
- 🛡️ Advanced participant verification