Mega Mojos 🌱
Overview
A lottery game like Mega Millions or Powerball simulated on Chia Blockchain.
Idea
- A player buys ticket by selecting a number from 0-99 and send 1000 mojos to a ticket smart coin.
- Each ticket smart coin puzzle curries in
PK
: the lottery official has theSK
to sign the spend.ORACLE_PUZZLE_HASH
: puzzle hash of the oracle who announces the winning number and block height.NUMBER
: a selected number.BLOCK_HEIGHT
: each drawing has to happen after this block height (time simulation).
- Once the blockchain reaches the specific block height, the winning number is announced. The lottery offical will gather all tickets and spend them together with the oracle.
- The lottery offical will take 10% cut and divide the rest to winners who pick the correct number.
- If there is no winner, the whole reward will be given to the fabulous Chia farmer 🧑🌾.
Chia Concept
State
Active tickets can be found by scanning the blockchain and looking for unspent coins with specific puzzle hashes (i.e., puzzle hash is unique for tickets with the same number and block height).
Aggregated Signatures
A ticket coin can be spent only when the aggregated signature includes the signature from the lottery official. An oracle coin can be spent only when the aggregated signature includes the signature from the approver. The spend bundle has to have these two signatures aggregated.
Announcements
A ticket coin can be spent only if the oracle coin announces the same winning number and block height is also spent in the same block.
Block Height Assertion
A ticket coin can be spent only when the specific block height is reached. The lottery official can't spend the ticket coins prematurely.
Hidden Information
A ticket's number and block height are revealed only when the coin is spent.
Chialisp
Oracle
(mod
(
APPROVER_PK
BLOCK_HEIGHT
winning_number
)
(include condition_codes.clib)
(list
(list AGG_SIG_ME APPROVER_PK (sha256 BLOCK_HEIGHT winning_number))
(list CREATE_PUZZLE_ANNOUNCEMENT (sha256 (q . "block_height") BLOCK_HEIGHT))
(list CREATE_PUZZLE_ANNOUNCEMENT (sha256 (q . "winning_number") winning_number))
)
)
When the oracle is spent, it announces block height
and winning number
which all tickets will have to verify. The approver of the lottery official has to sign the spend too.
The approver has to be different key from the official who sign the spend for tickets.)
Ticket
(mod (
PK
ORACLE_PUZZLE_HASH
NUMBER
BLOCK_HEIGHT
winning_number
player_puzzle_hash
winning_amount
)
(include condition_codes.clib)
; if this is winning ticket, also CREATE_COIN to the ticket owner
(defun-inline possibly_winner
(
PK
NUMBER
player_puzzle_hash
winning_amount
conditions
)
(if (= NUMBER winning_number)
(c
(list CREATE_COIN player_puzzle_hash winning_amount)
conditions
)
conditions
)
)
; main
(possibly_winner
PK
NUMBER
player_puzzle_hash
winning_amount
(list
(list AGG_SIG_ME PK (sha256 winning_number winning_amount))
(list ASSERT_HEIGHT_ABSOLUTE BLOCK_HEIGHT)
(list ASSERT_PUZZLE_ANNOUNCEMENT (sha256 ORACLE_PUZZLE_HASH (sha256 (q . "block_height") BLOCK_HEIGHT)))
(list ASSERT_PUZZLE_ANNOUNCEMENT (sha256 ORACLE_PUZZLE_HASH (sha256 (q . "winning_number") winning_number)))
)
)
)
A ticket is differentiated by number
and block height
. For example, if alice buys a ticket with number 42
and block height 101
, next drawing, the block height will be different, so even if the number is the same, the puzzle hash will not be the same.
(
PK
ORACLE_PUZZLE_HASH
NUMBER
BLOCK_HEIGHT
...
)
The ticket puzzle checks the selected NUMBER
and the winning_number
. If they match, CREATE_COIN
condition with the winning_amount
(provided by the lottery official) to the puzzle hash of the original ticket buyer.
(CREATE_COIN player_puzzle_hash winning_amount)
To make sure the ticket coin is not spent by any malicious user 🥷, it will verify signature and annoucements.
(AGG_SIG_ME PK (sha256 winning_number winning_amount))
(ASSERT_HEIGHT_ABSOLUTE BLOCK_HEIGHT)
(ASSERT_PUZZLE_ANNOUNCEMENT (sha256 ORACLE_PUZZLE_HASH (sha256 (q . "block_height") BLOCK_HEIGHT)))
(ASSERT_PUZZLE_ANNOUNCEMENT (sha256 ORACLE_PUZZLE_HASH (sha256 (q . "winning_number") winning_number)))