Summary
The four contracts (prediction_market, pulse_token, referral_registry, leaderboard) can each be upgraded independently via their upgrade() entry points. There is no cross-contract version check: a governor can upgrade one contract without upgrading the others, breaking the cross-contract ABI.
Impact
- If the leaderboard adds a new storage key that
prediction_market expects, but the market contract wasn't upgraded, the cross-contract call reverts or reads garbage.
- If
pulse_token changes its mint signature, the leaderboard's reward call breaks.
- If
referral_registry changes its register_referral return type, place_bet fails mid-flow.
- ABI mismatches are silent on deployment — they only surface at runtime when a user triggers the affected call path.
Fix
- Add an
interface_version() or contract_version() entry point to every contract.
- Have the governor set a coordinated "version bundle" via
set_config that pins all four versions together.
- Reject calls from contracts whose version does not match the expected set.
- Add a migration path: store an interface compatibility matrix in instance storage.
Summary
The four contracts (prediction_market, pulse_token, referral_registry, leaderboard) can each be upgraded independently via their
upgrade()entry points. There is no cross-contract version check: a governor can upgrade one contract without upgrading the others, breaking the cross-contract ABI.Impact
prediction_marketexpects, but the market contract wasn't upgraded, the cross-contract call reverts or reads garbage.pulse_tokenchanges itsmintsignature, the leaderboard'srewardcall breaks.referral_registrychanges itsregister_referralreturn type,place_betfails mid-flow.Fix
interface_version()orcontract_version()entry point to every contract.set_configthat pins all four versions together.