BubblesBubbles

How Bubbles calls resolve



Signed-in users can make two kinds of call per token, from a wallet they prove they control. Proving it means signing a free message, with no transaction:

  • Quality: legit or rug
  • Direction: bullish or bearish


  • One vote per wallet, per token, per kind (and one per account). The price, liquidity, 24h volume and our grade are snapshotted at the moment of the call.

    Resolution (at 7 days and again at 30 days)



    Market data comes from DexScreener: the largest-liquidity Solana pair. On-chain dump events come from Bubbles tracking (devSelling, bundlersSelling).

    Dead: 24h volume under $100, liquidity under $500, or no trading pairs.

    Liquidity pulled: liquidity was at least $5,000 at the call and has fallen below the larger of $1,000 or 20% of its value at the call.

    Bullish / bearish:
  • up when price is up 20% or more → bullish hit.
  • down when price is down 20% or more, the token is dead, or liquidity was pulled → bearish hit.
  • Anything in between is flat and is not scored.


  • Rug / legit:
  • Rug outcome if any of these hold:
  • - the token is dead - liquidity was pulled - price is down 80% or more - a dev/bundler dump event happened and price is down 50% or more - our grade fell by 15 points or more and price is down 50% or more
  • Legit outcome if there is no rug evidence, price is better than −50%, and liquidity is at least 50% of its value at the call.
  • Anything else is inconclusive and is not scored.
  • Our own grade never resolves a call by itself. A grade drop only counts together with an objective price collapse.


  • If there was no live price at the time of the call, the call is rejected and never stored.

    Reputation



  • Each horizon is one result. A call can produce up to 2 scored results (7d and 30d).
  • Hit rate = correct results ÷ scored results.
  • Reputation = the Wilson lower bound of the hit rate (z = 1.64) × 100 × the wallet's average weight. This keeps a single lucky call from topping the board.
  • Ranking: a wallet needs at least 5 scored results to be ranked.
  • Streak: consecutive correct results, counting back from the most recent.


  • Sybil dampening (wallet weight)



    The weight is taken from the wallet's SOL transaction history (read-only RPC, last 100 signatures) at the time of the call:

    | Tier | Requirement | Weight | |---|---|---| | Established | 20 or more transactions, and 30 days or older | 1.0 | | Some history | 5 or more transactions, and 7 days or older | 0.5 | | New | anything less | 0.2 |

    Accounts without a wallet extension (email / X sign-in)



    These calls are recorded against the Solana wallet linked to the account in Privy, including embedded wallets created at email or X sign-in.
  • No in-page signature is possible, so the call counts at the lowest weight (0.2).
  • The exception is a linked wallet with SOL history (5 or more transactions and 7 days or older), which is weighted by its tier instead.
  • An account with no linked wallet votes as itself, at weight 0.2.
  • One vote per account and per wallet still applies.
  • Where a wallet extension is present, a signed message is still required.


  • Badges (always shown with their evidence)



  • sharp caller: 10 or more scored results with a hit rate of 65% or more.
  • rug spotter: 5 or more correct rug calls.
  • on a streak: 5 or more correct in a row.


  • The thresholds live in rep.py (RULES) and are served at /api/rep/leaderboard → rules.

    Live config

    {
     "horizons": {
      "7d": 604800,
      "30d": 2592000
     },
     "bull_bear": {
      "move": 0.2
     },
     "rug": {
      "liq_pulled_frac": 0.2,
      "liq_pulled_floor": 1000,
      "price_crash": -0.8,
      "dump_with_price": -0.5,
      "grade_drop_pts": 15,
      "grade_with_price": -0.5
     },
     "legit": {
      "min_liq_frac": 0.5,
      "min_price": -0.5
     },
     "dead": {
      "vol24": 100,
      "liq": 500
     },
     "dump_kinds": [
      "devSelling",
      "bundlersSelling"
     ],
     "weights": {
      "established": {
       "txs": 20,
       "age_days": 30,
       "w": 1.0
      },
      "some": {
       "txs": 5,
       "age_days": 7,
       "w": 0.5
      },
      "new": {
       "w": 0.2
      }
     },
     "leaderboard": {
      "min_resolved": 5,
      "z": 1.64
     },
     "challenge_ttl": 600
    }