Skip to content

Commit 154d7f4

Browse files
chore: remove dead code (IRitualWallet, static precompile) + live v3 proof + doc polish
- Removed unused IRitualWallet interface and LLM_INFERENCE_PRECOMPILE constant (dead code — judgeAll uses configurable LLM_PRECOMPILE immutable). - Added MAX_ANSWER_LENGTH edge case to honesty notes (checked at reveal only; self-correcting with v3 refund). - Updated honesty notes: dropped obsolete cozfuttu#1 (dead constant) and cozfuttu#2 (wallet). - Root README: clarified workshop vs homework structure with verified contract addresses + deploy notes. - Flow status table: replaced v2 proof references with live v3 proof (bounty 1, two participants, 5 tx hashes on 0x97e19070...). - .deploy-info.txt: added commit-reveal live proof entries (v3, bounty 1). - 52/52 tests passing.
1 parent 086da73 commit 154d7f4

4 files changed

Lines changed: 75 additions & 72 deletions

File tree

‎README.md‎

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,30 @@
1-
## Starter for Ritual workshop on 23th June 2026
1+
# Ritual Academy Bootcamp #1 — Homework Submission
22

3-
/hardhat -> Where we'll write the smart contract
3+
Fork of [cozfuttu/ritual-chain-workshop](https://github.com/cozfuttu/ritual-chain-workshop).
44

5-
/web -> Where the frontend lives.
5+
## Repository layout
6+
7+
| Directory | What it is |
8+
|---|---|
9+
| **`bounty-judge/`** | **Homework submission** — Foundry project with the commit-reveal `BountyJudge` (Track 1), Ritual TEE `RitualBountyJudge` (Track 2), 52 tests, and deploy script. See [`bounty-judge/README.md`](./bounty-judge/README.md) for the full lifecycle, architecture comparison, and reflection. |
10+
| `hardhat/` | Original workshop starter. Contains the unmodified `AIJudge.sol` (public submissions — the flaw we fix in the homework). Not used by the submission. |
11+
| `web/` | Original workshop frontend. Built for `AIJudge.sol` (public `submitAnswer` flow). Not wired to the commit-reveal `BountyJudge`. |
12+
13+
## Quick start
14+
15+
```bash
16+
# Run the homework test suite
17+
cd bounty-judge
18+
forge test # 52/52 passing
19+
20+
# Deploy to Ritual Chain testnet
21+
cp .env.example .env # set RITUAL_RPC_URL + DEPLOYER_PRIVATE_KEY
22+
forge script script/Deploy.s.sol --rpc-url ritual --broadcast
23+
```
24+
25+
## Deployed (Ritual testnet, chainId 1979)
26+
27+
- BountyJudge v3: `0x97e1907022c1AE5B276F2D45907DF96399a38c4F`
28+
- RitualBountyJudge: `0x35Cd23637A8C5a8a61fD9A32D49A2fc1250f5A09`
29+
30+
RPC: `https://rpc.ritualfoundation.org` · Explorer: `https://explorer.ritualfoundation.org`

‎bounty-judge/.deploy-info.txt‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ Constructor: none
3333
52 passing (40 BountyJudge + 10 RitualBountyJudge + 2 RitualMsTimestamp),
3434
covering refund (5 cases) + judging attestation binding (1 case).
3535

36+
--- Commit-reveal proven live on v3 (bounty 1, two participants) ---
37+
createBounty : 0x15485e2e29ffb417d01feb9809b9dd4fbdcfbb5387592d5f51612129ae01e75d
38+
submitCommitment : 0xb43e3bc9051c26148c821cac80263273a85e3d9793752fc759a170ce05711949 (P1)
39+
submitCommitment : 0x5d8857ec150b96bc1ab203d26d8017ca5adbc5c867855cf51ba93dd06a24bc85 (P2)
40+
revealAnswer : 0x5229cff2d40516d996ba9535da9f5b082691978bad3ac7d0cecbe19dcf3f96c3 (P1, verified)
41+
revealAnswer : 0x5920a784a6252a7e548bcb83adcaf8c2e02618434784f4d8ee6ad806d853e4ca (P2, verified)
42+
revealedCount = 2 (both verified against keccak256(answer,salt,sender,bountyId))
43+
3644
--- Why Ritual Chain (not Base) ---
3745
judgeAll() calls the LLM inference precompile at 0x0802, which only exists on
3846
Ritual Chain (chainId 1979); a Base mainnet deployment could not run judgeAll.

‎bounty-judge/README.md‎

Lines changed: 37 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -223,37 +223,34 @@ precompile `0x0000000000000000000000000000000000000802` and deploys
223223

224224
### Commit-reveal flow status (Ritual Chain testnet)
225225

226-
Proved **live on-chain** (bounty 2, two participants) using **standard
227-
second-based deadlines** — which only work because of the ms normalisation:
226+
Proved **live on-chain on the v3 deployment** (`0x97e1907022...`) —
227+
bounty 1, two participants, standard second-based deadlines:
228228

229229
| Step | TX Hash | Status |
230230
|------|---------|--------|
231-
| `createBounty` (0.001 RITUAL, second-based deadlines) | `0x05a19b02e42c99ad22835fbca3a9509c02142e046d52137373cf0893e32714de` | ✅ |
232-
| `submitCommitment` (participant 1) | `0x2e50ef72865cb69cedbc55354ae97696f0bab8a178bdfe19932b749e36a3469a` | ✅ |
233-
| `submitCommitment` (participant 2) | `0xcd78b35700a6e7ccf4e39ab2b37868f2a6d8316a56531b5171cb43732cd02240` | ✅ |
234-
| `revealAnswer` (participant 1, commitment verified) | `0xb51211e616130d5815afbfb37474036db63c7c6d35ff6b0afed413c66e186e4e` | ✅ |
235-
| `revealAnswer` (participant 2, commitment verified) | `0x6e692a3a15a69c6528331f5592134ead619ed0882f564480072ce5ef8237188d` | ✅ |
236-
| `judgeAll` (LLM precompile 0x0802) | blocked by Ritual billing — see note | ⏳ |
231+
| `createBounty` (0.0001 RITUAL) | `0x15485e2e29ffb417d01feb9809b9dd4fbdcfbb5387592d5f51612129ae01e75d` | ✅ |
232+
| `submitCommitment` (participant 1) | `0xb43e3bc9051c26148c821cac80263273a85e3d9793752fc759a170ce05711949` | ✅ |
233+
| `submitCommitment` (participant 2) | `0x5d8857ec150b96bc1ab203d26d8017ca5adbc5c867855cf51ba93dd06a24bc85` | ✅ |
234+
| `revealAnswer` (participant 1, commitment verified) | `0x5229cff2d40516d996ba9535da9f5b082691978bad3ac7d0cecbe19dcf3f96c3` | ✅ |
235+
| `revealAnswer` (participant 2, commitment verified) | `0x5920a784a6252a7e548bcb83adcaf8c2e02618434784f4d8ee6ad806d853e4ca` | ✅ |
236+
| `judgeAll` (LLM precompile 0x0802) | blocked by Ritual billing (executor 0xB42e435c..., 0.311 RITUAL reservation) — see note | ⏳ |
237237
| `finalizeWinner` | after `judgeAll` | ⏳ |
238238

239-
The **commit-reveal core** (the anti-cheating mechanism the assignment asks
240-
for) is proven end-to-end on Ritual: commitments are hidden during submission,
241-
both reveals verified against `keccak256(answer, salt, msg.sender, bountyId)`,
242-
and `revealedCount == 2`.
243-
244-
> **`judgeAll` status (honest).** The LLM precompile call was attempted live.
245-
> Two Ritual-specific requirements were discovered and resolved:
246-
> 1. **Executor must be TEE-registered** — `executorAddress` in the LLM request
247-
> cannot be `0x0802`; it must be a registered executor such as
248-
> `0xB42e435c4252A5a2E7440e37B609F00c61a0c91B` (resolved — error cleared).
249-
> 2. **Wallet pre-payment** — Ritual reserves a fixed `0.311 RITUAL` of wallet
250-
> balance per inference (independent of `maxCompletionTokens`). The deployer
251-
> wallet had insufficient testnet RITUAL, so the live call could not
252-
> complete. The contract path itself is correct (verified against the
253-
> workshop's request encoding and the same 5-tuple output decode rivaleuc
254-
> uses); completing it only needs a wallet funded via the Ritual testnet
255-
> faucet. `judgeAll`/`finalizeWinner` are fully exercised in the 46-test
256-
> suite with a mocked precompile.
239+
The **commit-reveal core** — the anti-cheating mechanism the assignment
240+
requires — is live on the current v3 contract: commitments hidden during
241+
submission, reveals verified against
242+
`keccak256(answer, salt, msg.sender, bountyId)`, `revealedCount == 2`.
243+
244+
\> **`judgeAll` status (honest).** The LLM precompile call was attempted live.
245+
\> Two Ritual-specific billing requirements were discovered:
246+
\> 1. `executorAddress` must be a TEE-registered executor (e.g.
247+
\> `0xB42e435c4252A5a2E7440e37B609F00c61a0c91B` — resolved, error cleared).
248+
\> 2. Ritual reserves a fixed **0.311 RITUAL** of wallet balance per inference;
249+
\> the deployer wallet needs pre-funding via the Ritual testnet faucet.
250+
\> The contract path is correct (verified against the workshop's request
251+
\> encoding and the same output decode rivaleuc uses).
252+
\> `judgeAll`/`finalizeWinner` are fully exercised in the 52-test suite
253+
\> with a mocked precompile.
257254

258255
> On Ritual Chain every step is functional, including `judgeAll` (LLM precompile)
259256
> and `finalizeWinner`. This is the key advantage over a Base deployment, where
@@ -355,44 +352,39 @@ Per homework spec. Combined with sender + bountyId, prevents cross-account and c
355352

356353
Rather than over-claiming, here is exactly what this submission does and does not do:
357354

358-
1. **A hardcoded constant survives in the inherited base contract.** `PrecompileConsumer`
359-
(carried over from the workshop) still declares
360-
`address internal constant LLM_INFERENCE_PRECOMPILE = address(0x0802);`.
361-
It is **dead code**: `judgeAll()` uses the configurable `LLM_PRECOMPILE`
362-
immutable (constructor arg, set to `0x0802` on this Ritual deployment),
363-
never the constant. So the *runtime behaviour* is genuinely configurable;
364-
the constant is retained purely for source parity with the workshop base
365-
contract and is harmless.
366-
367-
2. **`IRitualWallet` is retained but unused.** The interface declaration is still
368-
in `BountyJudge.sol`, but no function references it and the wallet parameter
369-
was removed from every function signature. "Wallet removed" refers to the
370-
removed *usage/parameter*, not the type declaration. The contract holds
371-
rewards directly.
372-
373-
3. **"Works on any EVM chain" is only half true.** The commit-reveal logic
355+
1. **"Works on any EVM chain" is only half true.** The commit-reveal logic
374356
(commit/reveal/finalize) is pure EVM and runs anywhere. But `judgeAll()`
375357
unconditionally calls an LLM contract at the configured address — a chain
376358
without that precompile (e.g. Base mainnet) cannot execute
377359
`judgeAll`/`finalizeWinner`. **This is why the deployment targets Ritual
378360
Chain (chainId 1979)**, whose native precompile at `0x0802` makes the full
379361
lifecycle — including AI judging — functional.
380362

381-
4. **AI output is advisory, not authoritative.** `judgeAll()` stores the LLM
363+
2. **AI output is advisory, not authoritative.** `judgeAll()` stores the LLM
382364
result but the contract never parses it or auto-pays. The owner manually
383365
selects the winner in `finalizeWinner()` — a deliberate human-in-the-loop
384366
design, not a limitation.
385367

386-
5. **Track 2 is a design sketch.** `RitualBountyJudge` demonstrates the
368+
3. **Track 2 is a design sketch.** `RitualBountyJudge` demonstrates the
387369
TEE-attested flow (encrypted submit → batch judging → attestation verify →
388370
finalize) but intentionally omits reward escrow/payout: `finalizeWinner()`
389371
locks the winner index without transferring ETH. This matches the rule that
390372
the advanced track may be a design document.
391373

392-
6. **`block.timestamp`-based deadlines.** Validators can nudge
374+
4. **`block.timestamp`-based deadlines.** Validators can nudge
393375
`block.timestamp` by a few seconds; the deadlines are day-scaled windows so
394376
this is immaterial in practice, but it is not cryptographically enforced.
395377

378+
5. **`MAX_ANSWER_LENGTH` is checked at reveal, not commit.** The contract
379+
cannot check the answer length at commit time (the answer is hidden behind
380+
the hash). A participant who commits an answer exceeding 2000 bytes will
381+
be unable to reveal it later — their commitment is permanently locked.
382+
This is self-correcting in v3: if no other participant reveals, the owner
383+
can `refund()` the reward. In a multi-participant bounty the trapped
384+
participant simply forfeits eligibility; the remaining revealed answers
385+
are judged normally. This is a necessary consequence of the one-way hash
386+
property and is explicitly documented as a known trade-off.
387+
396388
---
397389

398390
## Reflection Question

‎bounty-judge/contracts/BountyJudge.sol‎

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,13 @@
11
// SPDX-License-Identifier: MIT
22
pragma solidity ^0.8.24;
33

4-
/**
5-
* @title IRitualWallet
6-
* @notice Interface for the Ritual wallet used to lock bounty rewards.
7-
* Identical to the workshop interface.
8-
*/
94
/**
105
* @title PrecompileConsumer
116
* @notice Base contract for Ritual Chain precompile access.
12-
* Provides the LLM_INFERENCE_PRECOMPILE at 0x0802 and
13-
* helper _executePrecompile() for calling Ritual precompiles.
14-
* (Identical to the workshop base contract.)
7+
* Provides _executePrecompile() for calling Ritual precompiles.
8+
* (Derived from the workshop base contract.)
159
*/
1610
abstract contract PrecompileConsumer {
17-
// Short-running async precompile for LLM inference
18-
address internal constant LLM_INFERENCE_PRECOMPILE = address(0x0802);
19-
2011
/**
2112
* @notice Execute a short-running async precompile.
2213
* Decodes the outer (simmedInput, actualOutput) envelope.
@@ -43,19 +34,6 @@ abstract contract PrecompileConsumer {
4334
}
4435
}
4536

46-
/**
47-
* @title IRitualWallet
48-
* @notice Interface for the Ritual wallet used to lock bounty rewards.
49-
* Identical to the workshop interface.
50-
*/
51-
interface IRitualWallet {
52-
function deposit(uint256 lockDuration) external payable;
53-
function depositFor(address user, uint256 lockDuration) external payable;
54-
function withdraw(uint256 amount) external;
55-
function balanceOf(address) external view returns (uint256);
56-
function lockUntil(address) external view returns (uint256);
57-
}
58-
5937
/**
6038
* @title BountyJudge
6139
* @notice Privacy-preserving AI bounty judge built on Ritual Chain.

0 commit comments

Comments
 (0)