Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .claude/scheduled_tasks.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"sessionId":"1ebdada4-6239-4cd6-9e17-3a75dc054408","pid":17384,"procStart":"Sat Jun 6 18:57:49 2026","acquiredAt":1780796215558}
24 changes: 24 additions & 0 deletions .githooks/pre-push
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env bash
# RangeGuard pre-push hook — mirrors CI (.github/workflows/ci.yml) so a push can't fail the same
# checks CI runs: forge fmt --check, forge build, forge test. Enable once with `make hooks`
# (sets core.hooksPath=.githooks). Bypass a single push with `git push --no-verify`.
set -euo pipefail

# Run from the repo root regardless of where git invokes the hook.
cd "$(git rev-parse --show-toplevel)"

if ! command -v forge >/dev/null 2>&1; then
echo "[pre-push] forge not found on PATH — skipping local checks (CI will still run them)."
exit 0
fi

echo "[pre-push] 1/3 forge fmt --check"
forge fmt --check

echo "[pre-push] 2/3 forge build"
forge build >/dev/null

echo "[pre-push] 3/3 forge test"
forge test >/dev/null

echo "[pre-push] OK — fmt clean, build OK, tests pass. Pushing."
16 changes: 16 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -407,3 +407,19 @@ Current target: Demo script (RangeGuardDemo.s.sol), then frontend dashboard.
Carry-ins: payout recipient = v4 sender (owner=sender MVP). The Callback Proxy is PER NETWORK under
Omni — for any future host chain confirm it at dev.reactive.network/origins-and-destinations before
deploying the hook (it is NOT the legacy 0x…fffFfF).

Session 13 carry-ins (live-demo blockers found + fixed):
1. REACTIVE react() vmOnly BUG: the local AbstractPausableReactive port detected the ReactVM via
`vm = extcodesize(0x8888)==0`. On Lasna Omni's unified CometBFT EVM the system contract 0x8888
exists in EVERY context, so vm is ALWAYS false and react()'s `vmOnly` reverted "VM only" on every
delivered event — the reactive could process nothing. FIX: react() now uses `onlySystem`
(msg.sender == SYSTEM 0x8888), the upstream Omni guard. Redeployed reactive
0x5eb9c8C021fB3474aA1f2d9EE5f53f6DbA5fFee1 on Lasna; OLD 0xC0e6… is SUPERSEDED + paused.
2. CALLBACK DELIVERY needs a PROXY RESERVE (the big gotcha): reactive callbacks dispatch on Lasna
(lREACT spent) but only LAND on the Sepolia hook if the hook holds a reserve on the host-chain
Callback Proxy (0xc9f3…7bDA). The proxy uses a reserve/depositTo model — funding the hook's raw
balance does NOTHING. Symptom of the gap: reserves(hook)=0, debt=0, no Sepolia tx, no revert
trace. FIX/STEP (MANDATORY after any hook redeploy): `make fund-hook-proxy`
(proxy.depositTo{0.05 ETH}(hook)); verify `make reserves-hook`. The hook already inherits
AbstractPayer (pay()) and all reactive-callable fns take the leading RVM-id address placeholder,
so neither of those was the issue — only the reserve.
47 changes: 45 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
deploy-hook deploy-hook-dry stage-init-seed mint-usdc \
faucet deploy-reactive deploy-reactive-dry \
reactive-balance reactive-paused reactive-topup reactive-pause reactive-resume \
deps
fund-hook-proxy reserves-hook reset-pool-tick hooks deps

# Load local env vars when present (PRIVATE_KEY, SEPOLIA_RPC_URL, etc.)
-include .env
Expand All @@ -15,6 +15,7 @@ export
HOOK_SCRIPT := script/DeployRangeGuardHook.s.sol:DeployRangeGuardHook
STAGE_SCRIPT := script/StageInitSeedPool.s.sol:StageInitSeedPool
REACTIVE_SCRIPT := script/DeployRangeGuardReactive.s.sol:DeployRangeGuardReactive
RESET_SCRIPT := script/ResetPoolTick.s.sol:ResetPoolTick

ANVIL_RPC_URL ?= http://127.0.0.1:8545
SEPOLIA_CHAIN_ID := 11155111
Expand All @@ -26,13 +27,21 @@ LASNA_RPC_URL ?= https://lasna-omni-rpc.rnk.dev/
# e.g. `make deploy-reactive HOOK_ADDRESS=0x...`.
DEPLOYER ?= 0x193D1F3E085efc80e1027891FaA770E81ECC4A1d
HOOK_ADDRESS ?= 0xFead6CeaD66f86101f0D0fc5A9B97888FA54a7C0
REACTIVE_ADDRESS ?= 0xC0e6b70c8FF75962541183fdc247E7B07AD6B70b
# Session 13 redeploy (vmOnly->onlySystem Omni fix). The Session-12 0xC0e6… is SUPERSEDED/paused.
REACTIVE_ADDRESS ?= 0x5eb9c8C021fB3474aA1f2d9EE5f53f6DbA5fFee1
MOCK_USDC_ADDRESS ?= 0x04feCef5110c5e52794fdA3D935BC2Cc0ee428CA
FAUCET ?= 0x9b9BB25f1A81078C544C829c5EB7822d747Cf434
FAUCET_VALUE ?= 0.1ether
RGAS_FUND_AMOUNT ?= 0.05ether
SEED_USDC_AMOUNT ?= 10000000000 # 10,000 USDC (6 decimals)

# Host-chain (Sepolia) Callback Proxy for Lasna->Sepolia callbacks. CRITICAL: reactive callbacks
# only LAND if the hook has a RESERVE on this proxy (proxy uses a reserve/depositTo model, NOT the
# hook's raw balance). Without `make fund-hook-proxy`, callbacks dispatch on Lasna (lREACT spent)
# but silently never execute on Sepolia (reserves(hook)=0, debt=0, no revert trace).
CALLBACK_PROXY ?= 0xc9f36411C9897e7F959D99ffca2a0Ba7ee0D7bDA
PROXY_DEPOSIT_AMOUNT ?= 0.05ether

# ----------------------------------------------------------------------------
# Help
# ----------------------------------------------------------------------------
Expand All @@ -46,6 +55,7 @@ help:
@echo " make coverage - Coverage report"
@echo " make clean - Remove build artifacts"
@echo " make deps - (info) dependencies are VENDORED; no install needed"
@echo " make hooks - Enable the version-controlled git pre-push hook (mirrors CI)"
@echo ""
@echo "Sepolia host-chain deploy (needs PRIVATE_KEY + SEPOLIA_RPC_URL in .env):"
@echo " make deploy-hook-dry - Simulate the hook deploy (prints mined address)"
Expand All @@ -65,6 +75,13 @@ help:
@echo " make reactive-pause - Pause the Cron heartbeat (owner only)"
@echo " make reactive-resume - Resume the Cron heartbeat (owner only)"
@echo ""
@echo "Callback delivery funding (Sepolia) — REQUIRED after any hook (re)deploy:"
@echo " make fund-hook-proxy - Deposit $(PROXY_DEPOSIT_AMOUNT) into the Callback Proxy reserve for the hook"
@echo " make reserves-hook - Show the hook's reserve on the Callback Proxy"
@echo ""
@echo "Demo recording prep (Sepolia):"
@echo " make reset-pool-tick - Nudge the live pool tick back to ~\$$2,000 (centre of the demo range)"
@echo ""
@echo "Local:"
@echo " make deploy-anvil-dry / deploy-anvil - Simulate / broadcast the hook deploy on anvil"

Expand Down Expand Up @@ -103,6 +120,12 @@ deps:
@echo " forge-std, v4-hooks-public, reactive-lib-omni (see lib/reactive-lib-omni/VENDORED.md)."
@echo "A fresh 'git clone' + 'forge build' works with no submodule init."

# Point git at the version-controlled hooks dir so the pre-push hook (fmt --check + build + test,
# mirroring CI) runs for everyone who opts in. One-time per clone. Bypass a push with --no-verify.
hooks:
@git config core.hooksPath .githooks
@echo "Enabled .githooks (pre-push runs forge fmt --check + build + test). Bypass: git push --no-verify"

# ----------------------------------------------------------------------------
# Local (anvil)
# ----------------------------------------------------------------------------
Expand Down Expand Up @@ -157,3 +180,23 @@ reactive-pause:

reactive-resume:
@cast send $(REACTIVE_ADDRESS) "resume()" --rpc-url $(LASNA_RPC_URL) --private-key $(PRIVATE_KEY)

# ----------------------------------------------------------------------------
# Callback delivery funding (Sepolia) — MANDATORY after any hook (re)deploy.
# Reactive callbacks dispatch on Lasna (lREACT) but only LAND on Sepolia if the hook holds a
# RESERVE on the Callback Proxy. depositTo(hook) credits that reserve; the proxy draws destination
# gas from it. Direct ETH to the hook does NOT work (proxy uses reserves, not the hook balance).
fund-hook-proxy:
@cast send $(CALLBACK_PROXY) "depositTo(address)" $(HOOK_ADDRESS) --value $(PROXY_DEPOSIT_AMOUNT) \
--rpc-url $(SEPOLIA_RPC_URL) --private-key $(PRIVATE_KEY)

reserves-hook:
@cast call $(CALLBACK_PROXY) "reserves(address)(uint256)" $(HOOK_ADDRESS) --rpc-url $(SEPOLIA_RPC_URL)

# ----------------------------------------------------------------------------
# Demo recording prep
# ----------------------------------------------------------------------------
# Re-centre the live pool tick to ~$2,000 before recording the demo (a single bounded swap; unused
# input is refunded). Run, confirm the tick is in range, then run RangeGuardDemo.s.sol.
reset-pool-tick:
@forge script $(RESET_SCRIPT) --rpc-url $(SEPOLIA_RPC_URL) --broadcast --private-key $(PRIVATE_KEY) -vv
Loading
Loading