집중 유동성 풀에서는 현재 가격이 들어 있는 밴드의 스테이킹 유동성만 gauge 배출을 받습니다. 밴드를 좁힐수록 배출 지분은 커지지만 가격이 금방 밴드를 벗어나고, 그때마다 언스테이크 → 유동성 회수 → 비율 맞추기 → 재민팅 → 재스테이크를 해야 합니다. 리밸런스가 잦을수록 가스·스왑 수수료·슬리피지가 배출 수익을 갉아먹고, 체인에 서브그래프가 없어 풀 목록과 손익을 직접 모아야 했습니다.

Overview
Features
- 상태머신 기반 자동 리밸런싱: 밴드 이탈 시 언스테이크 → 회수 → 스왑 재조정 → 새 밴드 민팅 → 스테이킹을 단계별 트랜잭션으로, 실패 지점부터 재시도
- 온체인 우선 상태 복원: 로컬 상태는 캐시로만 쓰고 기동할 때마다 온체인 포지션·스테이킹 상태와 대조
- 실시간 대시보드: 풀 레이더, 게이지 분석, 내 포지션, 봇 현황, 수동 작업(미리보기 후 실행)
- 손익 분해 회계: 포지션마다 가격 효과·비영구적 손실·배출·비용을 나눠 "봇 성과"를 시장 방향과 분리해 판단
- 비용 방어선과 알림: 시퀀스 전 비용 상한, 레인지 이탈 디바운스, 롤링 비용 예산, 비용/배출 경보, 텔레그램 킬스위치
Architecture

다이어그램 원문 (Mermaid)
flowchart TB
subgraph Chain["Robinhood Chain (L2)"]
POOL["Slipstream CL Pool"]
NPM["Position Manager (NFT)"]
GAUGE["CL Gauge (배출)"]
ROUTER["Swap Router"]
end
subgraph Mono["pnpm 모노레포 (TypeScript)"]
CORE["packages/core<br/>viem 클라이언트 · ABI/주소 맵<br/>BigInt 틱·유동성 수학<br/>tx 파이프라인 · 가드"]
BOT["apps/bot<br/>상태머신 엔진<br/>planner · sequencer · defenses"]
SERVER["apps/dashboard/server<br/>Fastify + WebSocket<br/>풀·게이지 인덱싱 · 손익 집계"]
WEB["apps/dashboard/web<br/>React + Vite"]
end
STATE[("state/<br/>bot-state.json · KILL")]
LOGS[("logs/*.jsonl<br/>구조화 로그")]
TG["Telegram<br/>알림 · 조회 · 킬스위치"]
POOL -- "WS newHeads / Swap 로그<br/>(끊기면 HTTP 폴링)" --> CORE
CORE --> BOT
CORE --> SERVER
BOT -- "서명 tx (가드 통과 시)" --> NPM
BOT --> GAUGE
BOT --> ROUTER
BOT <--> STATE
BOT --> LOGS
LOGS --> SERVER
STATE --> SERVER
SERVER -- "스냅숏 (localhost)" --> WEB
WEB -- "킬스위치 · 미리보기/실행" --> SERVER
SERVER --> TG
다이어그램 원문 (Mermaid)
stateDiagram-v2
[*] --> IDLE
IDLE --> PLAN_MINT: 포지션 없음
PLAN_MINT --> SWAP: 비율 재조정
SWAP --> MINT
MINT --> TOPUP: 잔여 자산 보충
TOPUP --> STAKE
MINT --> STAKE
STAKE --> MONITOR
MONITOR --> UNSTAKE: 레인지 이탈 (디바운스 후)
UNSTAKE --> EXIT: decrease + collect
EXIT --> PLAN_MINT
MONITOR --> CLAIM: 주기적 배출 수령
CLAIM --> MONITOR
MONITOR --> HALT: 킬스위치 · 연속 실패
HALT --> [*]: 수동 재개Key decisions
"Slipstream ≠ Uniswap V3"를 절대 규칙으로
이 DEX의 풀은 fee가 아니라 tickSpacing으로 식별하고 수수료는 거버넌스가 바꿀 수 있어 V3용 SDK를 쓰지 않았습니다. 컨트랙트 주소와 ABI는 Blockscout verified 소스와 온체인 팩토리 조회로 교차 검증한 뒤 출처를 남겼고, 수수료는 매번 풀에서 읽습니다.
인덱서 없이 직접 인덱싱하고, 온체인을 유일한 진실로
팩토리 이벤트 스캔과 로그 조회로 풀 목록과 거래량을 직접 만들고, 재시작·네트워크 단절·불확실한 트랜잭션이 있어도 기동 시 온체인과 대조해 복원합니다. 금액과 틱 계산은 BigInt로 격리된 수학 모듈에서 하고 단위 테스트로 고정했습니다.
지표를 "APR"이 아니라 "봇 성과"로 정의
봇이 흑자여도 토큰 가격 하락 때문에 총손익이 적자인 구간이 반복돼, 손익을 가격 효과·IL·배출·비용으로 분해해 보여 주도록 바꿨습니다. 한 시점의 스냅숏만 보고 풀을 전환하면 반복해서 실패했다는 점도 설계 문서에 교훈으로 남겼습니다.
Security
- 봇 전용 핫월렛: 메인 지갑 키를 재사용하지 않고 운용 자금과 가스비만 둠
- 개인키는 소유자만 읽을 수 있는 .env에서만 읽고, 로그·에러·대시보드·커밋에 키나 서명 원문이 나가는 경로를 두지 않음
- 모든 트랜잭션이 하나의 가드 파이프라인: deadline, minOut, 가스비 상한, 시뮬레이션 선행, 필요한 만큼만 approve
- 킬스위치 파일이 있으면 어떤 경로로도 새 트랜잭션을 보내지 않음, 텔레그램에서는 켜기만 가능
- 수동 작업은 미리보기 digest를 받은 뒤 짧은 유효 시간 안에 같은 digest로만 실행, fail-closed와 수동 재개
- 대시보드 서버는 127.0.0.1에만 바인딩
Status
일시 정지
읽기 전용 대시보드, 수동 조작, 자동화까지 구현하고 소액 실자금 자동 운용으로 동작을 검증했습니다. 지금은 킬스위치를 켜 두고 멈춘 상태이며, 배출률 대비 가격 변동성을 다시 조사해 재가동 여부를 검토하고 있습니다.