You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/blockchain-development-tutorials/native-vrf/commit-reveal-cadence.md
+56-45Lines changed: 56 additions & 45 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -19,68 +19,78 @@ keywords:
19
19
20
20
# Secure Randomness with Commit-Reveal in Cadence
21
21
22
-
Randomness is a critical component in blockchain applications, enabling fair and unpredictable outcomes for use cases like gaming, lotteries, and cryptographic protocols. The most basic approach to generating a random number on EVM chains is to utilize block hashes, which combines the block hash with a user-provided seed and hashes them together. The resulting hash can be used as a pseudo-random generator seed. However, this approach has limitations. The block hash can be manipulated by a validator influencing the random source used to compute transactions. The block proposer has the freedom to decide what to include into a block and can through different combinations till they find a favorable random source.
22
+
Randomness is a critical component in blockchain applications. It allows fair and unpredictable outcomes for use cases like gaming, lotteries, and cryptographic protocols.
23
23
24
-
[Chainlink VRF][chainlink-vrf] is a popular tool that improves on this by providing another approach for generating provably random values on Ethereum and other blockchains by relying on a decentralized oracle network to deliver cryptographically secure randomness from off-chain sources. However, this dependence on external oracles introduces several weaknesses, such as cost, latency, and scalability concerns.
24
+
The most basic approach that you can use to generate a random number on EVM chains is to use block hashes, which combines the block hash with a user-provided seed and hashes them together. You can use the has that results as a pseudo-random generator seed. However, this approach has limitations. A validator that influences the random source used to compute transactions can manipulate the block hash. The block proposer can decide what to include into a block and can iterate through different combinations until they find a favorable random source.
25
25
26
-
In contrast, Flow offers a simpler and more integrated approach with its native onchain Randomness Beacon at the protocol level, eliminating reliance on external oracles and sidestepping their associated risks.
26
+
[Chainlink VRF][chainlink-vrf] is a popular tool that improves on this. It provides another approach you can use to generate provably random values on Ethereum and other blockchains. It relies on a decentralized oracle network to deliver cryptographically secure randomness from off-chain sources. However, this dependence on external oracles introduces several weaknesses, such as cost, latency, and scalability concerns.
27
27
28
-
In addition to instant randomness that is available to any transaction (via `revertibleRandom` function), Flow provides a solution to reverted transaction. Commit-Reveal schemes on Flow also rely on protocol-native secure randomness and they fix the issue of post-selection by trustless users. Commit-Reveal tools on Flow can be used within both Cadence and Solidity smart contracts. This tutorial will focus on the Cadence case.
28
+
In contrast, Flow offers a simpler and more integrated approach with its native onchain Randomness Beacon at the protocol level, which eliminates reliance on external oracles and sidestepping their associated risks.
29
+
30
+
In addition to instant randomness that is available to any transaction (via `revertibleRandom` function), Flow provides a solution to the problem of a user reverting a transaction with an unfavorable outcome. Commit-Reveal schemes on Flow also rely on protocol-native secure randomness and they fix the issue of post-selection by trustless users. Commit-Reveal tools on Flow can be used within both Cadence and Consumer Decentralized Finance (DeFi) contracts. This tutorial focuses on Cadence.
29
31
30
32
## Objectives
31
33
32
34
By the end of this guide, you will be able to:
33
35
34
-
- Deploy a Cadence smart contract on the Flow blockchain
35
-
- Implement commit-reveal pattern for randomness to ensure fairness
36
-
- Interact with onchain randomness features on Flow
37
-
- Build and test the Coin Toss game using the Flow Testnet
36
+
- Deploy a Cadence smart contract on the Flow blockchain.
37
+
- Implement commit-reveal pattern for randomness to ensure fairness.
38
+
- Interact with onchain randomness features on Flow.
39
+
- Build and test the Coin Toss game with the Flow Testnet.
38
40
39
41
## Prerequisites
40
42
41
43
You'll need the following:
42
44
43
-
- Flow Testnet Account: An account on the Flow Testnet with test FLOW tokens for deploying contracts and executing transactions (e.g., via [Flow Faucet][flow-faucet]).
44
-
- Flow CLI or Playground: The Flow CLI or Flow Playground for deploying and testing contracts (install via [Flow Docs][flow-docs]).
45
+
- Flow Testnet Account: an account on the Flow Testnet with test FLOW tokens to deploy contracts and execute transactions (for example, via [Flow Faucet][flow-faucet]).
46
+
- Flow CLI or Playground: the Flow CLI or Flow Playground to deploy and test contracts (install via [Flow Docs][flow-docs]).
45
47
46
48
## Overview
47
49
48
50
In this guide, we will explore how to use a commit-reveal scheme based on the Flow Random Beacon to achieve secure, non-revertible randomness. This mechanism mitigates post-selection attacks, where participants attempt to reject unfavorable random outcomes after they are revealed.
49
51
50
-
To illustrate this concept, we will build a Coin Toss game on Flow, demonstrating how smart contracts can leverage a commit-reveal scheme for fair, tamper-resistant results.
52
+
To illustrate this concept, we will build a Coin Toss game on Flow, which demonstrates how smart contracts can leverage a commit-reveal scheme for fair, tamper-resistant results.
51
53
52
54

53
55
54
56
### What is the Coin Toss Game?
55
57
56
-
The Coin Toss Game is a decentralized betting game that showcases the commit-reveal pattern. Players place bets without knowing the random outcome, ensuring fairness and resistance to manipulation.
58
+
The Coin Toss Game is a decentralized betting game that showcases the commit-reveal pattern. Players place bets without knowing the random outcome, which ensures fairness and resistance to manipulation.
57
59
58
60
The game consists of two distinct phases:
59
61
60
-
1. Commit Phase - The player places a bet by sending Flow tokens to the contract. The contract records the commitment to use a future random value from the Flow Random Beacon. The player receives a Receipt, which they will use to reveal the result later.
61
-
2. Reveal Phase - Once the random value becomes available in the `RandomBeaconHistory` contract, the player submits their Receipt to determine the outcome:
62
+
1. Commit Phase - To place a bet, the player sends Flow tokens to the contract. The contract records the commitment to use a future random value from the Flow Random Beacon. The player receives a Receipt, which they will use to reveal the result later.
63
+
2. Reveal Phase - When the random value becomes available in the `RandomBeaconHistory` contract, the player submits their Receipt to determine the outcome:
62
64
- If the result is 0, the player wins and receives double their bet.
63
65
- If the result is 1, the player loses, and their bet remains in the contract.
64
66
65
-
### Why Use a Commit-Reveal scheme?
67
+
### Why use a Commit-Reveal scheme?
66
68
67
69
Similarly to revertible randomness, Commit-Reveal inherits the security of Flow native randomness beacon:
68
70
69
71
- Ensures security - The Flow Random Beacon provides cryptographically unpredictable and non-biased randomness.
70
72
- Ensure fairness - The Flow Random Beacon uses a Verifiable Random Function (VRF) under the hood which allows any external client or user to verify that randoms were generated fairly.
71
-
- Reduces reliance on external oracles - The randomness is generated natively onchain, avoiding additional complexity, third party risk and cost.
73
+
- Reduces reliance on external oracles - The randomness is generated natively onchain, and avoids additional complexity, third party risk and cost.
72
74
73
75
In addition, commit-reveal patterns solve the issue of revertible randoms:
74
76
75
-
- Prevents user manipulation - Players cannot selectively reveal results after seeing the random results.
77
+
- Prevents user manipulation - Players cannot evaluate the outcome and choose to revert the transaction if they do not like the result.
78
+
-
79
+
80
+
81
+
:::info
76
82
77
-
## Building the Coin Toss Contract
83
+
One of the powers of Cadence transactions is that a developer can set post-conditions that must be true, or the transaction will revert. This is very useful for scenarios such as guaranteeing a user receives their purchase in a complex and multi-step transaction, but it also means that they can set conditions to reject the transaction. In an instant-win lottery, this would allow users to test large numbers of tickets for a win without paying the purchase price.
78
84
79
-
In this section, we'll walk through constructing the `CoinToss.cdc` contract, which contains the core logic for the Coin Toss game. To function properly, the contract relies on supporting contracts and a proper deployment setup.
85
+
:::
80
86
81
-
This tutorial will focus specifically on writing and understanding the `CoinToss.cdc` contract, while additional setup details can be found in the [original GitHub repo][github-repo].
87
+
## Build the Coin Toss contract
82
88
83
-
### Step 1: Defining the `CoinToss.cdc` Contract
89
+
In this section, we'll walk through how to construct the `CoinToss.cdc` contract, which contains the core logic for the Coin Toss game. To function properly, the contract relies on supporting contracts and a proper deployment setup.
90
+
91
+
This tutorial will focus specifically on how to write and understand the `CoinToss.cdc` contract, while you can find additional setup details in the [original GitHub repo][github-repo].
92
+
93
+
### Step 1: Define the `CoinToss.cdc` contract
84
94
85
95
Let's define our `CoinToss.cdc` and bring the other supporting contracts.
### Step 2: Implementing the Commit Phase With`flipCoin`
118
+
### Step 2: Implement the commit phase with`flipCoin`
109
119
110
-
Let's define the first step in our scheme; the commit phase. We do this through a `flipCoin` public function. In this method, the caller commits a bet. The contract takes note of a future block height and bet amount, returning a `Receipt` resource which is used by the former to reveal the coin toss result and determine their winnings.
120
+
Let's define the first step in our scheme; the commit phase. We do this through a `flipCoin` public function. In this method, the caller commits a bet. The contract takes note of a future block height and bet amount and returns a `Receipt` resource, which the former uses to reveal the coin toss result and determine their winnings.
111
121
112
122
```cadence
113
123
access(all) fun flipCoin(bet: @{FungibleToken.Vault}): @Receipt {
@@ -124,10 +134,11 @@ access(all) fun flipCoin(bet: @{FungibleToken.Vault}): @Receipt {
124
134
}
125
135
```
126
136
127
-
### Step 3: Implementing the Reveal Phase With `revealCoin`
137
+
### Step 3: Implement the reveal phase With `revealCoin`
138
+
139
+
Now we implement the reveal phase with the `revealCoin` function. Here, the caller provides the Receipt they recieve at commitment. The contract then "flips a coin" with `_randomCoin()` providing the Receipt's contained Request. The reveal step is possible only when the protocol random source at the committed block height becomes available.
128
140
129
-
Now we implement the reveal phase with the `revealCoin` function. Here the caller provides the Receipt given to them at commitment. The contract then "flips a coin" with `_randomCoin()` providing the Receipt's contained Request. The reveal step is possible only when the protocol random source at the committed block height becomes available.
130
-
If result is 1, user loses, but if it's 0 the user doubles their bet. Note that the caller could condition the revealing transaction, but they've already provided their bet amount so there's no loss for the contract if they do.
141
+
If result is 1, the user loses, but if it's 0, the user doubles their bet. Note that the caller could condition the revealed transaction, but they've already provided their bet amount, so there's no loss for the contract if they do.
131
142
132
143
```cadence
133
144
access(all) fun revealCoin(receipt: @Receipt): @{FungibleToken.Vault} {
@@ -155,18 +166,18 @@ access(all) fun revealCoin(receipt: @Receipt): @{FungibleToken.Vault} {
155
166
}
156
167
```
157
168
158
-
The final version of `CoinToss.cdc`should look like [this contract code][coin-toss-contract-code].
169
+
The final version of `CoinToss.cdc`will look like [this contract code][coin-toss-contract-code].
159
170
160
-
## Testing CoinToss on Flow Testnet
171
+
## Test CoinToss on Flow Testnet
161
172
162
-
To make things easy, we've already deployed the `CoinToss.cdx` contract for you at this address: [0xb6c99d7ff216a684][coin-toss-contract]. We'll walk through placing a bet and revealing the result using[run.dnz][run-dnz], a Flow-friendly tool similar to Ethereum's Remix.
173
+
To make things easy, we've already deployed the `CoinToss.cdx` contract for you at this address: [0xb6c99d7ff216a684][coin-toss-contract]. We'll walk through how to place a bet and reveal the result with[run.dnz][run-dnz], a Flow-friendly tool similar to Ethereum's Remix.
163
174
164
-
### Placing a Bet with flipCoin
175
+
### Place a bet with flipCoin
165
176
166
-
First, you'll submit a bet to the CoinToss contract by withdrawing Flow tokens and storing a receipt. Here's how to get started:
177
+
First, you'll submit a bet to the CoinToss contract. To do this, you'll withdraw Flow tokens and store a receipt. Here's how to get started:
167
178
168
-
1. Open Your Dev Environment: Head to [run.dnz][run-dnz].
169
-
2. Enter the Transaction Code: Paste the following Cadence code into the editor:
179
+
1. Open Your Dev Environment: head to [run.dnz][run-dnz].
180
+
2. Enter the Transaction Code: paste the following Cadence code into the editor:
3. Set Your Bet: A modal will pop up asking for the betAmount. Enter a value (e.g., 1.0 for 1 Flow token) and submit
201
-
4. Execute the Transaction: Click "Run," and a WalletConnect window will appear. Choose Blocto, sign in with your email, and hit "Approve" to send the transaction to Testnet.
211
+
3. Set Your Bet: a window will appear that asks for the `betAmount`. Enter a value (such as 1.0 for 1 Flow token) and submit.
212
+
4. Execute the Transaction: click "Run," and a WalletConnect window will appear. Choose Blocto, sign in with your email, and click "Approve" to send the transaction to Testnet.
202
213
203
214

204
215
205
216
5. Track it: You can take the transaction id to [FlowDiver][flow-diver][.io](https://testnet.flowdiver.io/tx/9c4f5436535d36a82d4ae35467b37fea8971fa0ab2409dd0d5f861f61e463d98) to have a full view of everything that's going on with this `FlipCoin` transaction.
206
217
207
-
### Revealing the Coin Toss Result
218
+
### Reveal the coin toss result
208
219
209
-
Let's reveal the outcome of your coin toss to see if you've won. This step uses the receipt from your bet, so ensure you're using the same account that placed the bet. Here's how to do it:
220
+
Let's reveal the outcome of your coin toss to see if you've won. This step uses the receipt from your bet, so ensure you use the same account that placed the bet. Here's how to do it:
210
221
211
222
1. Return to your Dev Environment: Open [run.dnz][run-dnz] again.
212
223
2. Enter the Reveal Code: Paste the following Cadence transaction into the editor:
@@ -215,7 +226,7 @@ Let's reveal the outcome of your coin toss to see if you've won. This step uses
215
226
import FlowToken from 0x7e60df042a9c0868
216
227
import CoinToss from 0xb6c99d7ff216a684
217
228
218
-
/// Retrieves the saved Receipt and redeems it to reveal the coin toss result, depositing winnings with any luck
229
+
/// Retrieves the saved Receipt, redeems it to reveal the coin toss result, and deposits the winnings with any luck
219
230
///
220
231
transaction {
221
232
@@ -238,27 +249,27 @@ transaction {
238
249
}
239
250
```
240
251
241
-
After running this transaction, we reveal the result of the coin flip and it's 1! Meaning we have won nothing this time, but keep trying!
252
+
After we run this transaction, we reveal the result of the coin flip and it's 1! It means we haven't won anything this time, but keep trying!
242
253
243
254
You can find the full transaction used for this example, with its result and events, at [FlowDiver.io/tx/][flow-diver-tx].
244
255
245
256
## Conclusion
246
257
247
-
The commit-reveal scheme, implemented within the context of the Flow Randomness Beacon, provides a robust solution for generating secure and non-revertible randomness in decentralized applications. By leveraging this mechanism, developers can ensure that their applications are:
258
+
The commit-reveal scheme, implemented within the context of the Flow Randomness Beacon, provides a robust solution to generate secure and non-revertible randomness in decentralized applications. When developers leverage this mechanism, they can ensure that their applications are:
248
259
249
-
- Fair: Outcomes remain unbiased and unpredictable.
250
-
- Resistant to post-selection: Protects against trustless users who cannot reverse their commitments.
260
+
- Fair: outcomes remain unbiased and unpredictable.
261
+
- Resistant to post-selection: protects against trustless users who cannot reverse their commitments.
251
262
252
-
The CoinToss game serves as a practical example of these principles in action. By walking through its implementation, you've seen firsthand how straightforward yet effective this approach can be—balancing simplicity for developers with robust security for users. As blockchain technology advances, embracing such best practices is essential to creating a decentralized ecosystem that upholds fairness and integrity, empowering developers to innovate with confidence.
263
+
The CoinToss game serves as a practical example of these principles in action. Now that you've walked through its implementation, you've seen firsthand how straightforward yet effective this approach can be, as it balances simplicity for developers with robust security for users. As blockchain technology advances, it's essential that you embrace such best practices to create a decentralized ecosystem that upholds fairness and integrity, which empowers developers to innovate with confidence.
253
264
254
265
This tutorial has equipped you with hands-on experience and key skills:
255
266
256
267
- You deployed a Cadence smart contract on the Flow blockchain.
257
268
- You implemented commit-reveal to ensure fairness.
258
269
- You interacted with onchain randomness features on Flow.
259
-
- You built and tested the Coin Toss game using the Flow Testnet.
270
+
- You built and tested the Coin Toss game with the Flow Testnet.
260
271
261
-
By harnessing the built-in randomness capabilities on Flow, you can now focus on crafting engaging, user-centric experiences without grappling with the complexities or limitations of external systems. This knowledge empowers you to create secure, scalable, and fair decentralized applications.
272
+
When you harness the built-in randomness capabilities on Flow, you can create engaging, user-centric experiences without grappling with the complexities or limitations of external systems. This knowledge empowers you to create secure, scalable, and fair decentralized applications.
0 commit comments