💰
Megapot
  • Overview
    • About Megapot
    • How to play
    • How to provide liquidity
    • How to refer users
    • Earn as a liquidity provider
    • About the Team
    • Megapoints
  • Deep dive
    • Components
    • System Diagram
    • Smart Contract
    • Provably Fair
  • Developers
    • Start Here
    • React UI Kit (Beta)
      • MegapotProvider
      • Jackpot
      • useJackpot
    • Standalone Integration
      • Getting Started
      • Contract Functions
      • Jackpot Page
      • LP Deposit Page
      • History Page
    • Custom ERC-20 Jackpot
  • Developer Reference
    • Testnet & Mainnet
    • Contract Overview & Functions
    • Megapot API
    • Megapot Examples
      • Refer Tickets
      • Gifting Tickets
    • Brand Kit
  • Appendix
    • VIP Program
    • FAQ
    • About Megapot
  • Terms of Service
  • Privacy Policy
  • Responsible Gaming
Powered by GitBook
On this page
  • Overview of smart contract
  • Use the contract directly, now on Basescan!
  • Purchase Tickets
  • View Tickets and Winnings
  • Withdraw Winnings
  • Withdraw Referrer Fees
  • Deposit Liquidity
  • LP Risk Adjustment
  • Withdraw Liquidity
  • Jackpot Drawing
  • How to run the Jackpot
  • Protocol Fee
  • FAQ
  1. Deep dive

Smart Contract

PreviousSystem DiagramNextProvably Fair

Last updated 16 hours ago

Description
Address

USDC Jackpot (Base Mainnet)

USDC TEST Jackpot (Base Mainnet) **TESTING ONLY**

USDC TESTNET Jackpot (Base Sepolia) **TESTING ONLY**

Security Audits

The Megapot protocol above operates autonomously, enabling anyone to build on it, or use it, without permission.

The Megapot app at is a user-facing interface to the protocol and abides by relevant gaming regulations.

Overview of smart contract

  • Players can buy jackpot tickets at any time, for themselves or for others.

  • Players can view their tickets and winnings, as well as withdraw winnings and referrer fees.

  • Liquidity providers deposit liquidity at any time. Their liquidity starts guaranteeing a minimum jackpot starting the next jackpot.

  • The jackpot drawing occurs every 24 hours. A winning ticket is drawn, liquidity providers' balances are updated, fees are distributed to LPs, and then a new minimum jackpot is realized. Learn how this is

  • LPs can edit their position or withdraw liquidity at any time, but it processes after the current jackpot drawing completes.

Use the contract directly, now on Basescan!

  1. Go to the contract on Basescan here:

  2. Click the button in the red box to connect your wallet.

  1. Call the functions below!

purchaseTickets takes in address referrer, uint256 value, address recipient.

  • referrer [default: 0x0x0000000000000000000000000000] is the entity that got a user to buy a ticket. This can be an influencer or an app (often known as a frontend or interface). Requiring a referrer incentivizes KOLs and users to drive traffic to the protocol, while providing baseline revenue for apps.

  • value [default: 1000000 is a $1 ticket] is the amount of USDC that the user wants to spend on tickets. This uses Szabo notation, so 1000000 is 1 USDC (1 ticket).

  • recipient [default: your address, beginning with 0x] is the recipient of tickets. It should be your address, but also lets you to purchase tickets on behalf of another address. This can be used for gifting tickets to an address, or for more complex integrations to assign tickets to a specific wallet address (eg. cross-chain transactions).

Notes:

  • Tickets can only be purchased in increments of ticketPrice, which is 1 USDC (1_000_000 szabo).

  • LP fees and referrer fees are set aside at ticket purchase. The remainder is turned into tickets, where 10000 tickets equal 1 ticketPrice. Thus, a user receives 10000 - feeBps number of tickets.

  • For all cases counting tickets, since they are multiplied by 10000, Bps is added to the var name for clarity (eg. ticketCountTotalBps) This has no impact on Szabo-denominated var like userPoolTotal

  • Players can purchase tickets at any time, except for ~1 minute per day when the jackpot is drawing a winner.

Users can view their tickets and winnings directly from the contract.

usersInfo takes in an address [your address, starting with 0x]. It returns:

  • ticketsPurchasedTotalBps is the amount of tickets a user bought. 1 ticket is shown here as 7000, 2 tickets would show 14000, etc.

  • winningsClaimable is the amount of winnings that a user has, in USDC, with six decimal places.

  • active is a boolean that is true if the user has tickets, false if they have no tickets.

withdrawWinnings lets a user withdraw their winnings.

Check if the address has any amount to withdraw via usersInfo --> winningsClaimable(address).

withdrawReferralFees lets a user withdraw their referrer fees immediately after a ticket is purchased.

  • Check if the address has any amount to withdraw via referralFeesClaimable(address)

  • Note: referralFeesTotal is amount from all referrers collected from the current jackpot.

lpDeposit which takes in an integer riskPercentage and a USDC amount value

lpDeposit(uint256 riskPercentage, uint256 value)

  • riskPercentage is the variance that an LP chooses. This percentage of the liquidity guarantees the minimum jackpot and must be between 1 and 100.

  • At deposit time, the entirety of the deposits goes into the LP reserves, known as principal

  • Your risk percentage determines how much of your principal is used to guarantee the jackpot.

Notes:

  • The risk amount of LP reserves turns into tickets in stakeLps, which is rebalanced after each daily jackpot drawing through runJackpot

  • lpDeposit is also used when an LP deposits more.

lpAdjustRiskPercentage which takes in an integer riskPercentage between 1 and 100.

lpAdjustRiskPercentage(uint256 riskPercentage)

  • You can adjust your risk percentage at any time.

  • Risk adjustment occurs after the next jackpot drawing.

withdrawAllLP

LP reserves can only be withdrawn in full, and cannot be withdrawn partially. This two-step process requires one jackpot drawing to occur before liquidity can be withdrawn.

If LP has any liquidity in range, the contract will set riskPercentage = 0. The function ends at this time.

After the jackpot is run, LP should have no liquidity in range (lp.stake = 0) because stakeLps does not allocate any liquidity if riskPercentage = 0. At this time LP can call withdrawAllLP again to have their liquidity returned.

Jackpot Drawing

Context:

  1. Users buy tickets from the contract. The total number of tickets is represented as userPoolTotal

  2. LPs' guarantee for the jackpot is represented as lpPoolTotal

  3. Every 24 hours, we schedule a backend request to run the jackpot.

    1. Note: This is sufficiently decentralized. Anyone is able to run the jackpot after 24 hours has elapsed. This means if our backend service stops working, anyone can run the jackpot. We will improve on this more in the future.

    1. To request a random number, we send a transaction with a random 32-byte hexadecimal number generated off-chain and receive a sequence number. Entropy calls back to the contract with the generated random number once the request is fulfilled by the provider.

The raffle drawing occurs in runJackpot and there are three situations:

  1. Players bought more tickets than the LPs' jackpot guarantee

  2. Players bought less tickets than the LPs jackpot guarantee, and player wins

  3. Players bought less tickets than the LPs' jackpot guarantee, and LPs win

Before each situation, LP fees are distributed to LPs via distributeLpFees. If no LPs have position in range for that round, LP fees are distributed to the userPoolTotal.

Case #1: Players bought more tickets than the LPs' jackpot guarantee

  • A random number is generated between 1 and the number of tickets bought by users.

  • The jackpot amount userPoolTotal, which already does not include LP fees and referrer fees, is set to be claimable by the user.

  • LPs get their guarantee back fully via returnLpPoolBackToLps

Case #2: Players bought less tickets than the LPs jackpot guarantee, and players win

  • A random number is generated between 1 and the number of tickets guaranteed by LPs. Note, this is multiplied by 10000 to match the number of tickets per ticketPrice.

  • If the random number is less than the number of tickets bought by users, represented as ticketCountTotal, then users win!

  • Jackpot amount lpPoolTotal is set to be claimable by the user.

  • Users' entries are distributed to LPs via distributeUserPoolToLps

Case #3: Players bought less tickets than the LPs jackpot guarantee, and LPs win

  • Users' entries are distributed to LPs via distributeUserPoolToLps

  • LP pool is returned to LPs in returnLpPoolBackToLps

After one of the above cases is run:

  • Reset all variables.

  • Initialize the next guaranteed jackpot in stakeLps. For every active LP, we take their reserves (lp.principal) and multiply it by riskPercentage, in lp.stake

How to run the Jackpot

Our contract is decentralized -- anyone can run the jackpot every 24 hour. The core team has a scheduled run that does it, in case anything happens, anyone can run it. Here are the steps:

Kick off the jackpot run, which generates a random number from Pyth

  1. For runJackpot - payableAmount (ether) , enter in 0.000015000000000002

    1. Convert this from WEI to ETH, thus, divide by 10^18

  2. For userRandomNumber - bytes32, enter in 0x55fb29339a98ca25bedb7b5aa225041f669ca1407e926a95ce4a9b080ac66907

    1. Note: reusing this is fine, Pyth generates randomness, this seed further maximizes randomness

    2. You can generate your own with Web3.utils.randomHex(32) or openssl rand -hex 32. Prefix with 0x

Request callback from Pyth, which runs the jackpot

NOTE: This should happen automatically, but if it doesn't, you can manually run it.

  1. For these arguments:

    • provider (address)

    • sequenceNumber (uint64)

    • userRandomNumber (bytes32). Add 0x in front

    • Fetch the values from the RequestedWithCallback log from above. This event is emitted with the runJackpot function when our contract is called. Make sure to pass them with the correct signatures.

  2. For the last argument, providerRevelation (bytes32):

    • You will find the providerRevelation in the data field. Add 0x in front

Protocol Fee

There is a protocol fee that is only enabled when this protocol reaches massive scale, defined as LP fees are greater than 10,000 USDC per day. With a LP fee of 30%, that means ~$33k - 50k of tickets are sold. Only then will 1/10 of LP fees be distributed to the protocol treasury.

FAQ

Why is the contract upgrade-able?

We are launching a new protocol and there are many things we cannot anticipate. We want to have the ability to make changes to benefit LPs, apps, and players.

Our contract is secured by a multi signature wallet, with each signer using a cold wallet that is only used for Megapot operations.

We take operational security seriously. Our founder is doxxed (@Patrick_Lung on X), has a strong reputation (ex. Uniswap, Microsoft), and has been in crypto for years.

What changes do you want to make to the smart contract?

  • Increase LP and user limits

    • Optimize search functionality. We have a limit on LPs and user limits so we don't hit block gas limits

  • Allow for delegation for LPs

    • Enable LPs to deposit liquidity from any chain. This allows direct deposits from CEX or fiat.

  • Ticket-based drawings where users can pick numbers

  • Side prizes in addition to the jackpot

  • Dynamic fees to balance the multi-sided network

, trusted by Uniswap and Coinbase , led YOLO Games' audit , Polygon Labs partner , trusted by Solana Foundation

To ensure randomness, we use an entropy protocol.

Go to Basescan > Write Proxy Contract >

Fetch this from Blastscan > Read Proxy Contract >

Go to Basescan > Pyth's Base contract >

Go to the following endpoint: and use the sequence number:

Purchase Tickets
View Tickets and Winnings
Withdraw Winnings
Withdraw Referrer Fees
Deposit Liquidity
LP Risk Adjustment
Withdraw Liquidity
Pyth
RunJackpot
getJackpotFee
RevealwithCallback
https://fortuna.dourolabs.app/v1/chains/base/revelations/[sequenceNumber]
0xbEDd4F2beBE9E3E636161E644759f3cbe3d51B95
0x3368Fc551303aF78543DAA6A7D5Ea978cdB27D0A
0x6f03c7BCaDAdBf5E6F5900DA3d56AdD8FbDac5De
Feb 2025 report by Cantina
Jan 2025 report by Cantina
Dec 2024 report by Domain Expert
July 2024 report by CD Security
Almanax
megapot.io
provably fair and fully transparent
basescan.org/address/0xbEDd4F2beBE9E3E636161E644759f3cbe3d51B95