fix(prediction_market): validate referrer registration before paying … - #179
Conversation
…referral fee place_bet transferred the 0.5% referral fee to the registry and called credit() without checking that the stored referrer is still registered. If the referrer's profile was missing (archived TTL, bad migration, legacy wipe), credit() silently dropped the already-transferred XLM. - place_bet now resolves get_referrer() and verifies it via the new referral_registry.is_registered_referrer() view before transferring; unattributable fees stay with the market (AccumulatedFees) instead - add is_registered_referrer(address) view to referral_registry - regression tests: unregistered referrer never paid; retained path also used via cached HasReferrer=false on repeat bets - update affected market tests for retained no-referrer referral slices and queued bonus-point claims - restore referral_registry sources wiped by merge corruption (from 1ed3350); repair corrupt-era damage in leaderboard/prediction_market tests (missing braces, duplicate fns, sdk-26 ContractEvents API)
|
Hey @EneGab, This PR cannot be reviewed automatically because it does not reference the issue it solves. Add |
…-that-the-referrer-is-registered-unregistered-referrers-get-paid
|
Hey @EneGab, This PR cannot be reviewed automatically because it does not reference the issue it solves. Add |
Muyideen-js
left a comment
There was a problem hiding this comment.
@EneGab This PR addresses the core issue by adding is_registered_referrer and routing fees to the market when the referrer is unregistered. However, it introduces severe regressions and lacks CI verification. The record_bet function in leaderboard is now a no-op, breaking stats tracking. The removal of legacy add_pts and add_bonus_pts breaks backward compatibility. Tests contain errors: duplicate registrations, incorrect expected values (e.g., referrer points should be 8 not 3), and the test suite cannot be run on the dev machine. CI status is 'none', so we cannot approve. Please fix the leaderboard regression, restore legacy functions or provide migration, correct the tests, and run the full test suite in CI. Also, ensure the PR is rebased on the latest main to avoid merge corruption.
|
Noted! |
Summary
place_betpaid out the 0.5% referral fee whenever the bettor's profilenamed a referrer — without ever verifying that the referrer is actually
registered. The XLM was transferred to the referral registry before
credit()was invoked, andcredit()silently returnedfalsewhen thereferrer's profile could not be found. Result: the fee left the market,
was never credited to the referrer's earnings, and became permanently
stranded inside the registry contract.
This branch closes that hole with pre-validation and adds defense in depth
so unattributable fees are never shipped out of the market contract.
Root cause
In
prediction_market/src/lib.rs(place_bet):referral_registry.get_referrer(user)returnsSome(addr)from thebettor's stored profile.
referral_feeto the registry andcalled
credit(...).addrstill resolves to a live registration.A missing/archived/wiped referrer profile made
credit()drop thefunds on the floor.
Realistic triggers: referrer profile TTL archival, a bad migration or
legacy-key wipe leaving the bettor's profile pointing at an address whose
registration no longer exists.
Changes
referral_registry/src/lib.rsis_registered_referrer(referrer: Address) -> bool— exposes registration state so callers can verify before paying.
main by merge corruption (introduced via fix(referral_registry): hold no-referrer fees as admin-withdrawable surplus #141/fix(referral_registry): cap referrer lifetime earnings #142; restored from the
last clean state
1ed3350). Also repaired corrupt-era artifacts:truncated
add_bonus_ptsinvoke fragment inregister_referral,duplicate/garbled
ReferralErrorvariants (final:Paused = 7,ReferrerNotRegistered = 8,IncompatibleInterface = 9), and missingbraces.
prediction_market/src/lib.rsplace_betnow resolves the referrer viaget_referrer()andvalidates it through
is_registered_referrer()before any transfer:credit()(unchanged behavior)credited to the same market's fee ledger via
credit_market_fees(market_id, referral_fee)— it stays protocolrevenue, admin-withdrawable through the existing provenance-checked
withdrawal path ([HIGH]
withdraw_feeslets a fee recipient drain the entire accumulator to an arbitrary address with no cap or provenance check #57/[MEDIUM] Legacy key migration creates inconsistent state between pre-upgrade and post-upgrade users #78 machinery), instead of being lost forever.HasReferrercache records the negative result too, sorepeat bets by the same user skip re-validation consistently.
this code path: unclosed brace in
get_governor_count, broken eventpublishes in
execute_set_config(referenced out-of-scope variables),and mis-gated
get_market_ttl.leaderboard/src/lib.rsrecord_betbody and removed duplicated legacypoint/bonus block (merge corruption repair required for the workspace
to build).
Behavior change (intentional)
Bets placed by users without a registered referrer now retain their
full 2% fee in the market's
AccumulatedFees(previously only the 1.5%platform share landed there). Consequences:
cancel_marketreclaimTests
New regression tests (
prediction_market/src/tests.rs):test_unregistered_referrer_fee_routed_to_market— wipes thereferrer's registration post-registration (simulating archive/wipe),
bets, asserts full 2% stays in
AccumulatedFees/market ledger and thereferrer receives nothing.
test_unregistered_referrer_cached_false_across_bets— second bettakes the cached
HasReferrer = falsepath with identical outcome.Updated assertions (~12 sites) where behavior legitimately changed:
no-referrer fee totals, per-market ledgers, cancel-reclaim leftovers,
empty-side resolution withdrawals, migration/cap/two-step-withdraw tests,
and e2e flow.
Point-claim alignment: bonus points are queued by design; inserted
claim_pending_rewards(...)before point assertions in market, e2e, andregistry tests, and corrected corrupt-era expected values (e.g. referrer
earns 3 pts/referred-bet; welcome 5 pts go to the registrant).
Corruption repairs in test suites (required to compile at all):
duplicate test function, two missing braces, double registrations that
panicked, moved-value borrow, and sdk-26
ContractEventsAPI misuse(3 sites across leaderboard/referral_registry/prediction_market).
Verification
cargo check --workspace --testspasses clean (GNU toolchain).linker unavailable; MinGW fails linking cdylib test targets). Reviewers
should run
cargo test --workspacein a working toolchain.Closes [CRITICAL]
register_referraldoesn't validate that the referrer is registered — unregistered referrers get paid #176