implement Prize pool escrow + configurable top-N reward split#991
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Collaborator
|
@AJtheManager clean job thank you for taking this with urgency |
11 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
create_eventpreviously only charged a flatcreation_feethat went to theglobal treasury — a platform anti-spam fee, not a prize pool. There was no way
for a creator to fund a prize pool or define how it is split among winners
(the unused
token.rshelpers hinted this was planned but never wired up).This PR lets 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 the top 5). The prize pool is escrowed in the contractaddress, separately from the creation-fee → treasury transfer.
Changes
src/storage_types.rsMAX_REWARD_RANKS: u32 = 5REWARD_PERCENT_TOTAL: u32 = 100Eventstruct gains:prize_pool: i128reward_distribution: Vec<u32>— percentages, 1-based rank orderis_finalized: boolEvent::newtakesprize_poolandreward_distributionand alwaysinitializes
is_finalized: false.src/event.rsEventErrorvariants:InvalidPrizePool = 13—prize_pool < 0InvalidRewardDistribution = 14— empty when funded, more thanMAX_REWARD_RANKSentries, any entry== 0or> 100, sum!= 100(whenfunded), or a non-empty distribution on an unfunded event
InsufficientPrizePoolFunds = 15— creator cannot covercreation_fee + prize_poolvalidate_prize_pool()helper enforcing all of the above. Aprize_pool == 0"fun event" requires an emptyreward_distributionand hasno payouts.
create_eventsignature gainsprize_pool: i128andreward_distribution: Vec<u32>. Flow:fee + prize_poolbefore any transfer, sowe never move only the fee.
prize_pool > 0, escrowprize_poolfrom creator toenv.current_contract_address()— a separate transfer from thecreation-fee transfer.
prize_pool,reward_distribution, andis_finalized: false.(Symbol("event"), Symbol("prize_pool_funded"))with(event_id, prize_pool, reward_distribution)when funded.src/views.rs+src/lib.rsget_event_prize_pool(env, event_id) -> i128get_event_reward_distribution(env, event_id) -> Vec<u32>lib.rswires these through (panickingevent_not_foundon a missing event)and maps the three new errors to
invalid_prize_pool,invalid_reward_distribution, andinsufficient_prize_pool_funds.Acceptance criteria
prize_poolandreward_distributionat creation.prize_poolXLM moves from creator to the contract address (verified viaTokenClient::balance), separate from the creation fee.InvalidRewardDistributioncases are rejected with clear errors.prize_pool == 0requires an emptyreward_distribution(fun events withno payout).
Tests (
tests/event_tests.rs)test_create_event_with_prize_pool_escrows_funds— contract XLM balanceincreases by
prize_pool; creator's decreases bycreation_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→ error.test_create_event_zero_prize_pool_requires_empty_distribution→ error.test_get_event_prize_pool_and_distribution_views— views + stored fields.test_get_event_prize_pool_zero_for_fun_event— fun-event view defaults.The new
create_event/Event::newsignatures rippled across the suite; allexisting call sites were updated (fun events pass
0/ an emptyVec).Verification
cargo test— all suites pass, 0 failures (including the 8 new tests).cargo build --release --target wasm32-unknown-unknown— deploy artifactcompiles cleanly.
Notes / Follow-ups
create_event(two new positionalargs). Off-chain callers (frontend, backend indexer) must pass
prize_pooland
reward_distribution, and the indexer should handle the newprize_pool_fundedevent andprize_pool/reward_distributionfields.is_finalized) isintentionally out of scope here and left for a follow-up.
closes #968