fix: Remove recenterAccess — make recenter() public with TWAP enforcement (#706)

This commit is contained in:
openhands 2026-03-13 22:32:53 +00:00
parent 860b56f216
commit 1a410a30b7
13 changed files with 94 additions and 180 deletions

View file

@ -100,21 +100,6 @@ fund_liquidity_manager() {
"$LIQUIDITY_MANAGER" --value 10ether >>"$LOG_FILE" 2>&1
}
grant_recenter_access() {
bootstrap_log "Granting recenter access to deployer"
cast rpc --rpc-url "$ANVIL_RPC" anvil_impersonateAccount "$FEE_DEST" >>"$LOG_FILE" 2>&1
cast send --rpc-url "$ANVIL_RPC" --from "$FEE_DEST" --unlocked \
"$LIQUIDITY_MANAGER" "setRecenterAccess(address)" "$DEPLOYER_ADDR" >>"$LOG_FILE" 2>&1
cast rpc --rpc-url "$ANVIL_RPC" anvil_stopImpersonatingAccount "$FEE_DEST" >>"$LOG_FILE" 2>&1
if [[ -n "${TXNBOT_ADDRESS:-}" ]]; then
bootstrap_log "Granting recenter access to txnBot ($TXNBOT_ADDRESS)"
cast rpc --rpc-url "$ANVIL_RPC" anvil_impersonateAccount "$FEE_DEST" >>"$LOG_FILE" 2>&1
cast send --rpc-url "$ANVIL_RPC" --from "$FEE_DEST" --unlocked \
"$LIQUIDITY_MANAGER" "setRecenterAccess(address)" "$TXNBOT_ADDRESS" >>"$LOG_FILE" 2>&1
cast rpc --rpc-url "$ANVIL_RPC" anvil_stopImpersonatingAccount "$FEE_DEST" >>"$LOG_FILE" 2>&1
fi
}
call_recenter() {
local recenter_pk="$DEPLOYER_PK"

View file

@ -57,9 +57,6 @@ cat "$ONCHAIN_DIR/deployments-local.json"
echo "=== Funding LiquidityManager ==="
fund_liquidity_manager
echo "=== Granting recenter access ==="
grant_recenter_access
echo "=== Calling recenter() to seed liquidity ==="
call_recenter

View file

@ -33,7 +33,7 @@ DEPLOYMENTS="$REPO_ROOT/onchain/deployments-local.json"
# ── Anvil accounts ─────────────────────────────────────────────────────────────
# Account 8 — adversary (10k ETH, 0 KRK)
ADV_PK=0xdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97
# Account 2 — recenter caller (granted recenterAccess by bootstrap)
# Account 2 — recenter caller (recenter() is permissionless; any account can call it)
RECENTER_PK=0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a
# ── Infrastructure constants ───────────────────────────────────────────────────
@ -116,21 +116,8 @@ POOL=$("$CAST" call "$V3_FACTORY" "getPool(address,address,uint24)(address)" \
"$WETH" "$KRK" "$POOL_FEE" --rpc-url "$RPC_URL" | sed 's/\[.*//;s/[[:space:]]//g')
log " Pool: $POOL"
# ── 3a. Grant recenterAccess FIRST (while original feeDestination is still set) ──
FEE_DEST=$("$CAST" call "$LM" "feeDestination()(address)" --rpc-url "$RPC_URL") \
|| die "Failed to read feeDestination() from LM"
FEE_DEST=$(echo "$FEE_DEST" | sed 's/\[.*//;s/[[:space:]]//g')
log "Granting recenterAccess to account 2 ($RECENTER_ADDR) via feeDestination ($FEE_DEST) ..."
"$CAST" rpc --rpc-url "$RPC_URL" anvil_impersonateAccount "$FEE_DEST" \
|| die "anvil_impersonateAccount $FEE_DEST failed"
"$CAST" send --rpc-url "$RPC_URL" --from "$FEE_DEST" --unlocked \
"$LM" "setRecenterAccess(address)" "$RECENTER_ADDR" >/dev/null 2>&1 \
|| die "setRecenterAccess($RECENTER_ADDR) failed"
"$CAST" rpc --rpc-url "$RPC_URL" anvil_stopImpersonatingAccount "$FEE_DEST" \
|| die "anvil_stopImpersonatingAccount $FEE_DEST failed"
log " recenterAccess granted"
# ── 3b. Set feeDestination to LM itself (fees accrue as liquidity) ─────────────
# ── 3a. Set feeDestination to LM itself (fees accrue as liquidity) ─────────────
# recenter() is now permissionless — no setRecenterAccess() call needed.
# setFeeDestination allows repeated EOA sets; setting to a contract locks it permanently.
# The deployer (Anvil account 0) deployed LiquidityManager and may call setFeeDestination again.
# DEPLOYER_PK is Anvil's deterministic account-0 key — valid ONLY against a local ephemeral
@ -144,7 +131,7 @@ VERIFY=$("$CAST" call "$LM" "feeDestination()(address)" --rpc-url "$RPC_URL" | s
log " feeDestination set to: $VERIFY"
[[ "${VERIFY,,}" == "${LM,,}" ]] || die "feeDestination verification failed: expected $LM, got $VERIFY"
# ── 3c. Fund LM with 1000 ETH and deploy into positions via recenter ───────────
# ── 3b. Fund LM with 1000 ETH and deploy into positions via recenter ───────────
# Send ETH as WETH (LM uses WETH internally), then recenter to deploy into positions.
# Without recenter, the ETH sits idle and the first recenter mints massive KRK.
log "Funding LM with 1000 ETH ..."
@ -174,7 +161,7 @@ LM_ETH=$("$CAST" balance "$LM" --rpc-url "$RPC_URL" | sed 's/\[.*//;s/[[:space:]
LM_WETH=$("$CAST" call "$WETH" "balanceOf(address)(uint256)" "$LM" --rpc-url "$RPC_URL" | sed 's/\[.*//;s/[[:space:]]//g')
log " LM after recenter: ETH=$LM_ETH WETH=$LM_WETH"
# ── 4. Take Anvil snapshot (clean baseline, includes recenterAccess grant) ─────
# ── 4. Take Anvil snapshot (clean baseline) ────────────────────────────────────
log "Taking Anvil snapshot..."
SNAP=$("$CAST" rpc anvil_snapshot --rpc-url "$RPC_URL" | tr -d '"')
log " Snapshot ID: $SNAP"
@ -419,7 +406,7 @@ CAST binary: /home/debian/.foundry/bin/cast
### Recenter caller — Anvil account 2
- Address: ${RECENTER_ADDR}
- Private key: ${RECENTER_PK}
- Has recenterAccess on LiquidityManager
- Can call recenter() (permissionless — 60s cooldown + TWAP check enforced)
---
@ -446,7 +433,7 @@ to rebalance, then re-deploys positions at the current price. It:
- Can mint NEW KRK (increasing supply → decreasing floor)
- Can burn KRK (decreasing supply → increasing floor)
- Moves ETH between positions
Only recenterAccess account can call it.
recenter() is permissionless — any account can call it (subject to 60s cooldown and TWAP check).
### Staking
\`Stake.snatch(assets, receiver, taxRateIndex, positionsToSnatch)\`