A provably fair Ethereum lottery powered by Chainlink VRF v2.5
Explore how it works »
Run Locally
·
Report Bug
·
Request Feature
Table of Contents
Well of Reflection is a provably fair onchain game where visitors add ETH to a shared pool (“the Well”). Each visit triggers verifiable randomness via Chainlink VRF v2.5. That randomness is compared against a visitor-chosen imprint to determine whether the Well reflects the entire accumulated depth to the visitor.
-
Make an Offering
A visitor sends a fixed ETH offering (0.003 ETH) along with an imprint value. -
Request Verifiable Randomness
The Well requests a random word from Chainlink VRF, recording the request ID and visitor. -
Resolve the Reflection
The Chainlink VRF Coordinator fulfills the request by delivering a verifiable random word to the Well and the word is compared to the requestor's imprint for a match. -
Claim the Reflection
If the imprint matches the random word under modulo comparison, the Well reflects and awards the entire accumulated depth to the visitor.
The Well operates in discrete, VRF-gated cycles:
- Each offering temporarily pauses the Well while randomness is pending.
- If no reflection occurs the Well unpauses for further offerings from other visitors.
- If a reflection occurs, the Well reflects its accumulated offerings to the visitor and a new cycle begins.
To get a local copy up and running, follow these steps.
- Foundry - Smart contract development toolkit
curl -L https://foundry.paradigm.xyz | bash foundryup
-
Clone the repo
git clone https://github.com/am-hernandez/wellOfReflection.git cd well_of_reflection -
Install dependencies
forge install
-
Copy the environment file and configure
cp .env.example .env
-
Build the contracts
forge build
forge test -vvv-
Start a local Anvil node (in a separate terminal):
make anvil
-
Deploy contracts (VRF infrastructure + Well; use
deployif infra is already deployed):make deploy-all
Or in two steps:
make deploy-infrathenmake deploy. -
Make an offering (as a visitor; use a funded Anvil private key and an imprint):
make offer PK=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 IMPRINT=42
-
Fulfill the VRF request (local only; uses mock coordinator; request ID from step 3):
make fulfill REQUEST_ID=1 RANDOM_WORD=42
Then the visitor can call
receiveReflection()to claim if the well reflected.
make clean # Remove build artifacts
make clean-all # Remove build artifacts + deployments| Command | Description |
|---|---|
make anvil |
Start local Anvil node with 50 funded accounts |
make deploy-all |
Deploy VRF infra then Well (full local setup) |
make deploy-infra |
Deploy VRF coordinator, Link mock, feed, subscription only |
make deploy |
Deploy Well (and wrapper if local); run after deploy-infra |
make offer |
Make an offering; requires PK= and IMPRINT= |
make fulfill |
Fulfill a VRF request (local only); requires REQUEST_ID= |
make read-well |
Read Well state (e.g. on Sepolia; needs WELL_ADDRESS_TESTNET) |
make mineblock |
Mine 10 blocks on Anvil |
make clean |
Remove build cache |
make clean-all |
Remove build cache and deployments |
| Constant | Value | Description |
|---|---|---|
OFFERING_AMOUNT |
0.003 ETH | Required offering per visitor |
REFLECTION_MODULUS |
10,000 | Odds of reflection (1 in 10,000) |
CALLBACK_GAS_LIMIT |
100,000 | Gas limit for VRF callback |
REQUEST_CONFIRMATIONS |
5 | Block confirmations before VRF fulfillment |
// Make an offering with your chosen imprint
function makeOffering(uint256 imprint) external payable;
// Claim your reflection
function receiveReflection() external;
// Quote the current VRF fee
function quoteVrfFee() external view returns (uint256);event RequestSent(uint256 indexed requestId, uint256 indexed wellId, address indexed visitor);
event RequestFulfilled(uint256 indexed requestId, uint256 indexed wellId, address indexed visitor, bool reflected, uint256 depthAtResolution);
event ReflectionReceived(address indexed recipient, uint256 amount);- Core Well contract with VRF integration
- Local deployment scripts with mock VRF
- Simulation framework for testing
- Testnet deployment (Sepolia)
- Frontend interface
- Mainnet deployment
- Multi-well support
See the open issues for a full list of proposed features and known issues.
Contributions are always welcome and are greatly appreciated.
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature) - Commit your Changes (
git commit -m 'Add some AmazingFeature') - Push to the Branch (
git push origin feature/AmazingFeature) - Open a Pull Request
Distributed under the MIT License. See LICENSE for more information.
- Chainlink VRF v2.5 - Verifiable Random Function
- Foundry - Ethereum development toolkit
- Best-README-Template