Skip to content

[Contract]-Prize pool escrow + configurable top-N reward split #968

@grantfox-oss

Description

@grantfox-oss

event::create_event (src/event.rs) only charges a flat creation_fee that
goes to the global treasury (event.rs:99-101) — this is a platform
anti-spam fee, not a prize pool. There is currently no way for a creator to
fund a prize pool or define how it's split among winners. src/token.rs has
unused helpers (collect_entry_fee, distribute_winnings,
calculate_winnings) that hint this was planned but never wired up.

Goal

Let a creator deposit an XLM prize pool when creating an event, and define what
percentage of it each leaderboard rank receives (e.g. [40, 30, 20, 5, 5] for
top 5).

Requirements

  1. Event struct gains:

    pub prize_pool: i128,
    pub reward_distribution: Vec<u32>, // percentages, 1-based rank order, sum == 100 when prize_pool > 0
    pub is_finalized: bool,
  2. New constants in src/storage_types.rs:

    pub const MAX_REWARD_RANKS: u32 = 5;
    pub const REWARD_PERCENT_TOTAL: u32 = 100;
  3. event::create_event signature gains:

    prize_pool: i128,
    reward_distribution: Vec<u32>,
  4. New EventError variants:

    • InvalidPrizePool = 13prize_pool < 0
    • InvalidRewardDistribution = 14 — any of:
      • prize_pool > 0 and reward_distribution.is_empty()
      • reward_distribution.len() > MAX_REWARD_RANKS
      • any entry == 0 or > 100
      • sum(reward_distribution) != 100 (only enforced when prize_pool > 0;
        if prize_pool == 0, reward_distribution must be empty — this is a
        "fun event", no payouts)
    • InsufficientPrizePoolFunds = 15 — creator's XLM balance < prize_pool
  5. Flow changes in create_event:

    • Validate reward_distribution as above.
    • If prize_pool > 0: transfer prize_pool from creator to
      env.current_contract_address() (escrow) — this is a second,
      separate transfer from the existing creation_fee → treasury transfer.
      Do not conflate the two.
    • Store prize_pool, reward_distribution, is_finalized: false on Event.
    • Emit (Symbol("event"), Symbol("prize_pool_funded")) with
      (event_id, prize_pool, reward_distribution).
  6. New read-only views (src/views.rs + lib.rs):

    pub fn get_event_prize_pool(env: Env, event_id: u64) -> i128;
    pub fn get_event_reward_distribution(env: Env, event_id: u64) -> Vec<u32>;

Acceptance criteria

  • Creator can specify prize_pool and reward_distribution at creation
  • prize_pool XLM moves from creator to the contract address (verify
    via TokenClient::balance in tests), separate from the creation fee
  • All InvalidRewardDistribution cases are rejected with clear errors
  • prize_pool == 0 requires an empty reward_distribution (fun events with no payout)

Testing checklist (tests/event_tests.rs)

  • test_create_event_with_prize_pool_escrows_funds — assert contract's XLM
    balance increases by prize_pool and creator's decreases by
    creation_fee + prize_pool
  • test_create_event_reward_distribution_must_sum_to_100[50, 30, 10] → error
  • test_create_event_too_many_reward_ranks — 6 entries → error
  • test_create_event_zero_entry_in_distribution_rejected[100, 0] → error
  • test_create_event_insufficient_balance_for_prize_pool
  • test_create_event_zero_prize_pool_requires_empty_distribution
  • test_get_event_prize_pool_and_distribution_views

Metadata

Metadata

Assignees

Labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions