Back
Docs · v1.1 · 2026-05-24

How $RIVALS works

$RIVALS is a betting protocol built on Uniswap V4. Bet on the world's biggest matches (World Cup, UFC, Champions League) with ETH, hold the token to bet without selling your bag, and watch every losing pot buy back and burn supply. Fixed 1,000,000 tokens, no team or VC cut.

The 30-second version
Bet with ETH
Pick a side on a match. Everyone who bets on the winner splits the pot. No bookie sets the odds, the crowd does.
Bet without selling
Hold $RIVALS? Lock it as collateral, borrow ETH against it, and place the bet in one step. Keep your tokens.
Every loss burns supply
5% of each losing pot is used to buy $RIVALS on the open market and burn it forever. Supply only goes down.
Settled on-chain
Results come from a sports oracle. Win and you can claim straight away. Contracts are immutable once live.
01

What it is

$RIVALS is a fixed-supply token that doubles as the engine of a betting venue. One Uniswap V4 hook does three jobs at once.

  1. A market to buy and sell $RIVALS (1% swap fee).
  2. A lender: lock $RIVALS, draw ETH at 40% loan-to-value from idle pool reserves.
  3. A one-tap bet: route that borrowed ETH straight into a match pool.
In plain English
Most betting sites take your tokens or your deposit and set the odds in their favor. Here the contracts hold everything, the crowd sets the odds, and the only cut (5% of losing pots) goes to buying and burning the token, which benefits everyone still holding it.
Under the hood · The contracts involved

$RIVALS is an ERC20 paired with a Uniswap V4 hook (RivalHook) and a pari-mutuel betting contract (BetVault). Bet resolution is read from a sports oracle (Chainlink Sports, with a 3-of-5 multisig fallback). 5% of every losing pool is captured as protocol rake, swapped via an internal V4 trade to $RIVALS, and burned.

02

How the pieces fit

Three actions, four contracts. A holder can lock $RIVALS, receive 40% of its value in ETH (less a 1% fee), and drop that ETH into a match pool, all in a single transaction.

In plain English
Win and the contract repays your loan automatically and hands you the surplus. Lose and you still owe the loan, which can be liquidated if your collateral falls too far. You never had to sell your $RIVALS to play.
Under the hood · Architecture diagram

                    ┌──────────────────────────┐
                    │   Uniswap V4 PoolManager │
                    └──────────┬───────────────┘
                               │ hook callbacks
                               ▼
        ┌──────────────────────────────────┐
        │ RivalHook                        │     ┌──────────────────┐
        │  • LDF bands (100 × 30 ETH)      │     │ BetVault         │
        │  • borrow / repay / liquidate    │────▶│  • pari-mutuel   │
        │  • borrowToBet                   │     │  • oracle read   │
        │  • rakeBurn (called by vault)    │◀────│  • claim/refund  │
        └──────────────────────────────────┘     └──────┬───────────┘
                  │                                     │
                  ▼                                     ▼
        ┌──────────────────┐                  ┌────────────────────┐
        │ $RIVALS (ERC20)   │                  │ Sports oracle      │
        │  • 1M fixed      │                  │ (or multisig fall) │
        └──────────────────┘                  └────────────────────┘
03

The price curve

$RIVALS trades against ETH on a standard constant-product curve, with liquidity spread across 100 price bands so the market stays deep as it grows.

In plain English
Early buyers get most of the supply at the lowest prices, and the curve covers a roughly 7,000x price range. There is no order book, the price is just a function of how much ETH has flowed in.
Under the hood · The math
realTokens × (V + realETH) = K
  • V = 20 ETH - virtual reserve so the curve is defined at zero real ETH
  • K = 20,000,000 - establishes 1,000,000 $RIVALS at launch
  • Spot price = (V + realETH) / realTokens

Liquidity is sliced into 100 bands of 30 ETH each (a Liquidity Distribution Function), covering 0 to 3,000 ETH of cumulative inflow. Each band i holds:

band_i = K / (V + 30i) − K / (V + 30(i+1))

Band 0 (0 to 30 ETH) gets 60% of the supply; later bands taper sharply.

04

Borrowing against $RIVALS

Lock $RIVALS and borrow ETH against it at 40% of its value. Keep your tokens, get spending power for bets.

In plain English
It works like a home-equity loan against your bag. If the token price drops far enough that your loan is no longer safely covered, your collateral is sold to repay it, the same way any lending market works.
Loan-to-value40%
Liquidation threshold150% (collateral / debt)
Liquidation bounty1% of debt, capped at 0.01 ETH
Origination fee1% of debt, to FeeCollector
Min collateral value0.1 ETH worth of $RIVALS
Under the hood · What borrow() does step by step
  1. Pulls collateral and prices it at spot.
  2. Computes the liquidation ETH level via √0.6 × (V + spotETH) − V and maps it to a bound band.
  3. Withdraws ETH from that band's LP (which sits below current spot, so price is unchanged).
  4. Routes 1% to the fee collector, sends 99% to the user, records the position.

Liquidations sell the collateral via a V4 swap, pay a capped 1% bounty to the caller, and refill the bound band as fresh single-sided ETH LP. No $RIVALS is burned; the band just gets deeper. This is the protocol's self-healing property.

05

How bets pay out

Every match is a pari-mutuel pool: all the money on the losing sides is split among everyone who backed the winner, minus a 5% fee.

In plain English
The more lopsided the crowd, the bigger your share if you are on the right side. Odds keep moving as money comes in and lock at kickoff. You bet against other users, never against the house.

You can stake two ways:

  • Direct ETH - minimum stake 0.05 ETH.
  • Borrowed ETH via borrowToBet() - the hook draws ETH from your collateral and forwards it to BetVault atomically. The ETH never touches your wallet.
Under the hood · Resolution and claiming
  1. resolve(matchId) - anyone can call after the match ends. Reads the oracle, sets winningOutcome.
  2. claim(matchId, outcome) - winners pull stake + (stake × losersPool × 0.95) / winnersPool.
  3. The first winner-claim triggers the buyback and burn (next section).
  4. settleBetPosition(...) - permissionless settler for borrow-routed bets. Auto-repays debt, returns collateral plus surplus, or banks winnings if the position was liquidated mid-bet.
  5. If the oracle does not report within 48h: timeoutRefund(matchId) opens and all stakes are refunded at par.
06

Buyback & burn

5% of every losing pot is used to buy $RIVALS on the protocol's own market and burn it. Every settled match permanently shrinks supply.

In plain English
This is the whole point: betting activity continuously removes tokens from circulation. There is no minting, no team unlock, no inflation, just a one-way ratchet down on a fixed 1,000,000 supply.
Under the hood · The buyback transaction

When the first winner claims, BetVault forwards 5% of the losers' pool to RivalHook.rakeBurn(). Inside an unlockCallback:

1. poolManager.sync(ETH); poolManager.settle{value: rake}();
2. swap(zeroForOne=true, amountSpecified=-rake);
3. poolManager.take(RIVALS, hook, tokensBought);
4. RIVALS.burn(tokensBought);

The burn block is marked lastLiquidationBlock; external swaps in the same block are rejected by beforeSwap, which blocks sandwich attempts around the buyback. Internal swaps (where sender == hook) bypass this gate.

Edge case: if nobody bet the winning outcome, anyone can call sweepNoWinners(matchId) to route the entire pot to a burn. Permissionless, one-shot.

07

Where results come from

Match results are read from a sports oracle, not from the team. The protocol is oracle-agnostic, so the deployment uses whichever feed is wired at launch.

In plain English
Typically results land on-chain 30 to 90 minutes after the final whistle. If an oracle never reports, there is a user-side escape hatch that refunds every stake.
Under the hood · Oracle interface and fallback

Resolution depends on a single interface:

function getOutcomeForFixture(bytes32 feedKey)
    external view
    returns (uint8 outcome, uint64 settledAt, uint8 statusFlag);

// statusFlag:  0 pending  · 1 final  · 2 cancelled  · 3 abandoned

Primary: a Chainlink Sports Data Streams adapter. Fallback: a 3-of-5 multisig MultisigResolver keyed off a public scores feed, gated by a one-hour challenge window. After 48h with no report, timeoutRefund opens.

08

Tokenomics

One million tokens, all of it sold into the open market. No team bag, no VC round, no unlock schedule to dump on you.

Total supply1,000,000 $RIVALS (fixed)
Team allocation0%
VC / private round0%
Initial distribution100% via the V4 pool, seeded across 100 bands
Deflation5% of every losing pool, burned
Burn ceilingNone - burns continue while pool depth lasts
In plain English
The only address that gets tokens early is the deployer's pre-launch buy, and they pay the same 1% fee as everyone else. It is fully visible on-chain.
Under the hood · Bootstrap disclosure

The deployer may call ownerBootstrapBuy() before start() opens public swaps, paying the same 1% swap fee as any buyer. The ETH committed is at the deployer's discretion and is verifiable via the BootstrapBuy(buyer, ethIn, tokensOut) event. This pristine first entry is intentional: it sets a clean starting price with no front-running.

09

Launch sequence

Launch is a fixed recipe of deploy steps ending in a single atomic bundle that opens trading with no chance to front-run it.

Under the hood · Full deploy steps
  1. Deploy FeeCollector with a multisig owner.
  2. Deploy the $RIVALS ERC20, mint 1M to the deployer.
  3. Mine a CREATE2 salt encoding the V4 hook permission flags 0x3ACC.
  4. Deploy RivalHook at the mined address.
  5. Transfer 1M $RIVALS from deployer to hook.
  6. Deploy BetVault(hook, oracle, multisig).
  7. hook.setBetVault(vault) - one-shot, self-bricks.
  8. hook.initializePool(), then seedBands(0, 50) and seedBands(50, 100).
  9. Register the opening slate of matches in BetVault.
  10. Final atomic bundle: ownerBootstrapBuy + start(). Public swaps open.
  11. Later rounds are registered progressively as brackets settle.
  12. After the final match resolves, ownership of both contracts is renounced.
10

Risks

Read these before you bet. This is v1 software handling real money.

Smart-contract risk
The hook is a custom V4 design with single-sided LP-as-loan-book accounting. v1 launches without a full third-party audit; source is verified on Etherscan and ships with an internal adversarial review plus a full end-to-end production simulation against a real V4 PoolManager. Do not bet more than you can afford to lose.
Oracle risk
The sports oracle may not cover every fixture at launch. If a feed is missing, the fallback is a multisig resolver - centralized, gated by a challenge window. timeoutRefund is the user-side escape after 48h.
Liquidation risk
Borrow positions are liquidated when collateral / debt falls below 1.5x. A mid-bet liquidation removes the loan, but the bet stake still resolves; winnings on liquidated bets are banked for separate withdrawal.
Bootstrap concentration
The deployer's pre-public buy can be sizeable. After start(), that position is just like any other holder's - subject to swap fees and transparent on-chain.
Regulatory
$RIVALS is not offered to U.S. persons or other restricted jurisdictions. The contracts are permissionless on-chain; the frontend enforces geo-blocking and a terms-of-service gate.
11

Beyond one tournament

The contracts do not expire. $RIVALS is the token; the protocol is the venue. The same lending hook, pari-mutuel pools, and burn engine work for any tournament with a fixed set of resolvable fixtures.

In plain English
$RIVALS launches around the World Cup and already runs UFC and Champions League markets. New competitions plug in as new fixtures, no new token.
  • More fight cards and league seasons - same contracts, same burn.
  • Future major tournaments - an extra BetVault bound to the same hook and token, sharing the burn.
  • Bigger brackets - multi-vault architecture as volume grows.

Continuity is a stated commitment, not a contract obligation. If the utility does not carry, the fixed supply still does.

12

Contracts & references

Once deployed, contract addresses and Etherscan links populate here. For now:

$RIVALS

This document is informational only and is not financial, legal, or tax advice. Smart contracts are immutable; bugs are non-refundable. Bets are pari-mutuel and settle via a sports oracle (or fallback resolver) - outcomes are final. Not available to U.S. persons.