# RAIN Risk Markets — Arbitrum One Mainnet Deployment

**Date:** 2026-07-27 · **Chain:** Arbitrum One (42161) · **Deployer/Governance:** `0x74a435596b7C76d99320eF960FbF6e4750257aC2`

## Contract Addresses

| Contract | Address | Deploy Tx |
|---|---|---|
| MarketRegistry | `0x076149f4293549b78C909315B3465805922fDf70` | `0x230e35364f16b6c36a4f3fc20d20eeb6eb1bdfb175422610e6e2d701662118b9` |
| RiskVault | `0x9eDCB60620Ad062C4EbA71d5B457eA08fc1EadE8` | `0x2b7c852008cce967db1cf19b5bc730ba30ec180b4ba8bb212681959448eb4945` |
| FeeSplitter | `0x0dd5cE18cFdc7345f0caA212B94747c052EfA947` | `0x0cc14e085989c7c95ecf1add6f8604e42fb35cf2e5bf92cff99de6b01517fd38` |
| VRFAdapter | `0x2afFca69f8aa481afDCE3c15669225246dC2008B` | `0xcd846c122f822d0548a33ec943ea0104185c915a16861b7cfba79f90a01c9676` |
| RiskEngine | `0x16700BA3141Dd73ea0139B1e6663B6b40268d99d` | `0x752f9c20610479d2a73ef71fa886dabbe8fbab43c28fa66331b688a047b89758` |

## External Addresses (verified)

- USDC (native Arbitrum): `0xaf88d065e77c8cC2239327C5EDb3A432268e5831` — decimals()==6, symbol "USDC" verified on-chain
- LINK: `0xf97f4df75117a78c1A5a0DBb814Af92458539FB4` — **NOTE:** the address given in the task brief (`0xf97f...45d02c95`) has no code on Arbitrum; the correct address above was taken from Chainlink's official VRF v2.5 supported-networks docs and verified (symbol "LINK").
- VRF Coordinator v2.5: `0x3C0Ca683b403E37668AE3DC4FB62F4B29B6f7a3e` (Chainlink docs)
- Key hash: `0x8472ba59cf7134dfe321f4d61a430c4857e8b19cdd5230b09952a92671c24409` (30 gwei lane)

## Wiring Txs

- `vault.setEngine`: `0x24b96bee53fca0a7fa6d31dc9bc693b81026506676ab65591d38068866e531a7`
- `splitter.setEngine`: `0x5eee2df8dec4bbf6b3c5303875590717b6f87df42a178182630e2111e57e3e3f`
- `vrf.setEngine`: `0x1c409e114a8fd3fcb4c6945c26f1ccb906b623c2e144bef31927cc7ee75009aa`
- 5× `listMarket` (even-money 1.975x, 4x, 10x, 36.5375x, ~100x @ EV 0.9875):
  `0xb0a88a4d…eebdab`, `0x3b41ae78…840120a`, `0x06f12eaf…7ec48d`, `0x9212ca49…dca230`, `0x61ee9913…44b6b7`

## Chainlink VRF v2.5 Subscription

- **Sub ID:** `89227813476920981096392676009477736066099074454582175463472230943458630375262`
- createSubscription tx: `0x07692ab24e16404fb31e5ded64ba63405e1faaeb09994daff25f948f98b44a56`
- Funded with **3.0 LINK** via `LINK.transferAndCall(coordinator, 3e18, abi.encode(subId))`: `0xa4844276a326a46828cc9333fb42a637f8563f66d803533ef2acf848f2db9f39` (chose LINK funding — VRFAdapter requests with `nativePayment:false`, so LINK is what actually gets billed)
- addConsumer(VRFAdapter): `0xfe30f10106c8b14ccb60d1b54a5c5a96b84f23b32e7e0431fd5b95f23c4ea733`

## ETH→LINK Swap

- LiFi (Kyberswap route): 0.014 ETH → 3.1257 LINK, tx `0x0d816df5c47e78b787989b9127f1b44498fd16db202d357d0bf79039db77aa86`
- (First send attempt failed on a transient "max fee < base fee" race; re-quoted and retried successfully.)

## Safety Config

- RiskVault TVL cap: **2,000 USDC** (`tvlCap = 2_000_000_000`, verified on-chain)
- All governance roles: deployer wallet

## Smoke Test (read-only, all ✅)

- `vault.totalAssets()` = 0; `vault.tvlCap()` = 2,000e6
- `registry.marketCount()` = 5
- `vault.engine()` = RiskEngine; `vrfAdapter.engine()` = RiskEngine; `vrfAdapter.subId()` = sub ID
- `coordinator.getSubscription(subId)` → balance 3.0 LINK, owner = deployer, consumers = [VRFAdapter]
- No USDC deposit test performed (wallet holds no USDC, per instructions)

## Frontend

- CONFIG updated in `rain-risk-markets/app/app.js` (chainId 42161 already set; 4 protocol addresses filled in)
- Pushed to rainsandbox-xyz repo (agentbase workflow `b086e87d-01e0-4c20-9b0b-3e73df8a0cd1`), commit `cce81e24`, redeployed → **live**
- Verified https://rainsandbox.xyz/app/app.js serves the real addresses; `/app/` already existed on the site (LAUNCH APP links unchanged)

## Balances After Deployment

- ETH: **0.02007** (well above the 0.012 floor)
- LINK in wallet: **0.1257** · LINK in VRF sub: **3.0**

## Deviations & Notes

1. **LINK address correction** (see above) — task brief's LINK address was invalid on Arbitrum; used official Chainlink-docs address.
2. **Arbiscan verification skipped** — no `ARBISCAN_API_KEY` (or ETHERSCAN key) in the environment. Contracts are unverified; can be done later with `forge verify-contract` once a key is available.
3. Used the existing `Deploy.s.sol` unmodified (it is fully env-driven): `USDC`, `VRF_COORDINATOR`, `VRF_KEY_HASH`, `VRF_SUB_ID`, `TVL_CAP=2000000000` passed via env. `--skip-simulation` used to save time; all txs confirmed on-chain.
4. Agentbase repo update done via `update-code.cjs`/`redeploy.cjs` (skill's supported path) rather than a manual git clone/push — same result, verified live.

---

# DEMO MODE (Play-Money) Deployment — v1.3.0

**Date:** 2026-07-27 · **Chain:** Arbitrum One (42161) · Deployer: `0x74a435596b7C76d99320eF960FbF6e4750257aC2`

## RUSD + Demo Protocol Stack

| Contract | Address |
|---|---|
| RUSD (RISK Dollar, 6 dec, 100M supply) | `0x260c7019E760763988843Bc5b873d749b5937469` |
| MarketRegistry (demo) | `0xADf3B1270961231ff925C8885843c597502A3d44` |
| RiskVault (demo, asset=RUSD, cap 100M) | `0xEcF918c851d9259DDaEc48d51D8363CBaDe3A18F` |
| FeeSplitter (demo) | `0x46F8478aeDbE189ffa85CE06BFF767c57b7d403c` |
| VRFAdapter (demo) | `0x17fb4Fc8778aF721D28846F64A391F7D7374d47f` |
| RiskEngine (demo) | `0x4fd901d0f18d738142F86A82AC1895D4B0C6EBa5` |

- Deployed via `script/DeployDemo.s.sol` (single broadcast: token + stack + wiring + 5 canonical markets + 10M RUSD house-bankroll deposit).
- Same 5 markets as mainnet stack (1.975×, 4×, 10×, 36.5375×, ~100×).
- VRF: reuses the existing v2.5 subscription (3 LINK). addConsumer(demo VRFAdapter): `0x05460cc52296d0c3133f7613f0743bede9e8b2209dcb654326c85fd185b6fa5a`. Sub now has 2 consumers (live + demo adapters).
- Sanity checks ✅: totalAssets = 10,000,000 RUSD; nextMarketId = 5; vault.engine & vrf.engine = demo RiskEngine; consumer registered.

## Faucet (REDEEM CODE)

- Faucet wallet: [REDACTED — operated by the site owner]. Funded with ETH + RUSD for demo claims.
- Backend: `POST https://api.rainsandbox.xyz/faucet` `{address, code}` → sends 0.0003 ETH + 1,000 RUSD. Redeem code available from the site owner. 24h per-address limit (in-memory), kill switch.
- Backend configuration: [REDACTED — environment details omitted from the public release].
- Test claim ✅ to `0x7B61dc9eE9875Cde4d0D9b1deE3dDa6C92FAA79F`: ETH tx `0xa9293d20fefbe21346ce45d612d4d5dcb367cf7de1a16c6d6d8fc839169adf50`, RUSD tx `0x3260ec88d5e04ab8bc82e20b19cabefbadba7d92ae020ac63b028da5ab8de089`. On-chain confirmed (0.0003 ETH + 1000 RUSD). Repeat claim → 429; wrong code → 403. ✅

## Frontend v1.3.0

- DEMO/LIVE toggle (header, defaults to DEMO, persisted in localStorage `rainMode`).
- DEMO mode auto-creates an in-browser burner wallet (ethers.Wallet, obfuscated in localStorage `rainDemoBurnerV1`), signs via public RPC — no extension needed. Banner shows address + demo-wallet note.
- 🎁 REDEEM CODE button → POSTs to the faucet, refreshes balances.
- Market game names in list + position feed: Coin Flip / Even Money, 4× Multiplier, 10× Multiplier, Roulette — Single Number, Long Shot 100×.
- Deployed via agentbase (frontend commit `86a38dfc`, backend commit `6fe26323`), both `live`; verified `v1.3.0` served at rainsandbox.xyz/app/app.js.

## Balances After Demo Deployment

- Deployer ETH: **0.01590** · Deployer RUSD: 85,000,000 (100M − 10M vault − 5M faucet)

## User Flow

1. Open https://rainsandbox.xyz/app/ — DEMO mode is default; a demo wallet is created automatically in the browser.
2. Click **🎁 REDEEM CODE**, enter the demo code (ask the site owner) → receive 1,000 RUSD + 0.0003 ETH gas.
3. Trade any market or deposit into the vault — real on-chain txs, VRF settlement, play money.
4. Switch to **🔴 LIVE** for the real USDC stack (browser wallet / WalletConnect / Coinbase).

---

# ROULETTE — v1.7.0

**Date:** 2026-07-27 · New page https://rainsandbox.xyz/app/roulette.html (+ `roulette.js`), full European single-zero roulette on the DEMO stack (RUSD), shared burner wallet with the main app. Deployed commit `80aa0d8f`.

## New Markets on Demo MarketRegistry (`0xADf3B1270961231ff925C8885843c597502A3d44`)

All two-outcome (win/lose), EV = 987,499 ppm (≤ 98.75% spread floor):

| ID | Bet type | prob (ppm) | payoutX | tx |
|---|---|---|---|---|
| 5 | Even-money (red/black/even/odd/1-18/19-36), 18/37 | 486,486 | 2.029863× | `0xb2e11c97b0d16ee6853a631a9671cee98c5c30fe5d9d4a206f6dc261e4b47ed0` |
| 6 | Corner (4-number quad), 4/37 | 108,108 | 9.134384× | `0xd7c0b3c2caf8eb565797a24973f289515607577de998d0573ad5109ea74a8285` |
| 7 | Dozen / Column, 12/37 | 324,324 | 3.044794× | `0xc7654f5870694088e24eebde33e52d6b279c3364bae3586893dafb37192226e7` |

- Straight bets reuse existing market **#3** (prob 27,027 = 1/37, 36.5375×) — verified via `getMarket(3)`.
- All verified on-chain via `getMarket` (active, EV 987,499). `nextMarketId` = 8.
- Mapping recorded in `app/roulette.js` `MARKETS` config.
- Wheel presentation: win/loss decided on-chain by Chainlink VRF; displayed pocket derived client-side consistent with the verified outcome (covered number on WIN, non-covered on LOSS), seeded by settlement tx hash. Honest "ⓘ provably fair" note on page.
- Deployer ETH after registrations: **0.01589**.

## Roulette v1.9.0 (2026-07-27)

**Batch betting decision — NO periphery contract deployed.** RiskEngine.placePosition
attributes positions to `msg.sender` (`positions[id].trader = msg.sender`) and
settlement pays `p.trader` directly (also void refunds → `p.trader`). There is no
owner/onBehalf/recipient parameter. A `RouletteTable` periphery calling placePosition
would become the trader: all VRF payouts and timeout refunds would flow to the
periphery, requiring escrow bookkeeping + an extra claim tx per user (worse UX, new
custody risk) — clean attribution is impossible without modifying the core engine.
Instead the frontend now broadcasts all placePosition txs **in parallel** (Promise.all
fan-out with sequential explicit nonces, single approval, no inter-send waits).

Other v1.9.0 changes: RAIN logo drawn into wheel hub (circular clip, canvas);
wheel comes to a complete stop on the result (new "stopped" phase, zero residual
drift); persistent results sidebar (last 50 spins, localStorage, colored number
chips + MULTI chip, net win/loss per spin).
