> For the complete documentation index, see [llms.txt](https://docs.evently.market/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.evently.market/developers/oracle-vrf.md).

# Oracle & VRF Integration

Two MegaETH-native capabilities power automatic market resolution and provably fair randomness in evently: **Redstone Pull-model Oracle** and **Drand BLS12-381 VRF**.

***

## Redstone Pull-model Oracle

### How it works

Redstone uses the **Pull model**: price data is NOT stored on-chain. Instead, a keeper (off-chain script) fetches the latest signed price package from Redstone and injects it as calldata when calling `resolveMarketWithOracle()`.

The contract inherits from `RedstoneConsumerNumericBase` and reads the price inline using `getOracleNumericValueFromTxMsg(feedId)`. Signature verification happens automatically — the call reverts if fewer than 3 valid `redstone-primary-prod` signers are present in the calldata.

### Integration — Keeper script

```js
const { WrapperBuilder } = require("@redstone-finance/evm-connector");
const { ethers } = require("hardhat");

const contract = await ethers.getContractAt("EventlyMarkets", MARKETS_ADDRESS);

const wrapped = WrapperBuilder
  .wrap(contract)
  .usingDataService({
    dataServiceId: "redstone-primary-prod",
    uniqueSignersCount: 3,
    dataFeeds: [feedId],  // e.g. "ETH"
  });

await wrapped.resolveMarketWithOracle(marketId, evidenceHash);
```

### Authorized signers

The contract hardcodes 5 `redstone-primary-prod` signer addresses in `getAuthorisedSignerIndex()`. Minimum threshold is 3 (`getUniqueSignersThreshold()`). Any call with fewer valid signatures will revert.

### Encoding price feed IDs

The `priceFeedId` parameter in `createOracleMarket` is `bytes32`. Encode it as a right-padded ASCII string:

```ts
import { padHex, toHex, stringToBytes } from "viem";

const feedId = padHex(toHex(stringToBytes("ETH")), { size: 32, dir: "right" });
```

### Strike price precision

Strike prices use **8 decimal places** (same as Redstone USD feeds):

| Value    | Encoded          |
| -------- | ---------------- |
| $3,000   | `300000000000`   |
| $100,000 | `10000000000000` |
| $0.50    | `50000000`       |

***

## Drand BLS12-381 VRF (MegaETH Native)

MegaETH exposes a native precompile for verifying **Drand quicknet BLS12-381** randomness proofs. evently uses this for:

1. **Monthly dispute lottery** — `distributeMonthlyDisputeRewards(month, vrfProof, vrfMessage)` draws a single winner-takes-all
2. **Weekly Lucky Trader raffle** — `drawLuckyTrader(week, vrfProof, vrfMessage, bonusAmount)` draws one winner from that week's active traders

### Interface

```solidity
interface IDrandVerifier {
    function verify(bytes calldata proof, bytes calldata message) external view returns (bool);
}
```

The contract calls `IDrandVerifier(drandVerifier).verify(vrfProof, vrfMessage)` and reverts if the proof is invalid.

### Winner derivation

```solidity
uint256 winnerIndex = uint256(keccak256(vrfProof)) % count;
address winner = entries[winnerIndex];
```

The VRF proof itself is the source of entropy — it is deterministic given the Drand round and cannot be manipulated by the caller.

### Admin setup

Set the precompile address before any draw:

```solidity
setDrandVerifier(0x...precompile...);
```

The address is network-specific. Confirm the MegaETH Drand precompile address from the official MegaETH documentation before deployment.

### Fetching a Drand proof (off-chain)

```js
// Fetch latest quicknet round
const res = await fetch("https://api.drand.sh/52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971/public/latest");
const { round, signature } = await res.json();

// vrfProof = signature (hex-encoded BLS12-381 G1 point)
// vrfMessage = round number encoded as 32-byte big-endian uint
const vrfProof = "0x" + Buffer.from(signature, "base64").toString("hex");
const vrfMessage = ethers.utils.hexZeroPad(ethers.utils.hexlify(round), 32);
```

***

## Events

| Event                                                      | When emitted                     |
| ---------------------------------------------------------- | -------------------------------- |
| `OracleResolution(marketId, feedId, price, winningOption)` | Oracle market resolved           |
| `DisputeLotteryWinner(month, winner, amount)`              | Monthly dispute lottery drawn    |
| `LuckyTraderWinner(week, winner, bonusAmount)`             | Weekly lucky trader drawn        |
| `DrandVerifierUpdated(newVerifier)`                        | Drand precompile address updated |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.evently.market/developers/oracle-vrf.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
