논스(nonce)와 API 지갑
배경
탈중앙화 L1은 리플레이 공격을 방지해야 합니다. 사용자가 USDC 이체 트랜잭션에 서명하면, 수신자가 이를 여러 번 브로드캐스트하여 송신자의 지갑을 탈진시키는 일이 발생해서는 안 됩니다. 이를 해결하기 위해 Ethereum은 각 주소에 대해 0부터 시작하는 숫자인 "nonce"를 저장합니다. 각 트랜잭션은 포함되기 위해 정확히 "nonce + 1"을 사용해야 합니다.
API 지갑
문서에서는 agent wallets로도 불립니다. 마스터 계정은 API 지갑이 마스터 계정 또는 서브계정을 대신하여 서명하도록 승인할 수 있습니다.
API 지갑은 서명에만 사용된다는 점에 유의하세요. 마스터 또는 서브계정과 연관된 계정 데이터를 조회하려면 해당 계정의 실제 주소를 전달해야 합니다. 흔한 실수는 에이전트 지갑을 사용하는 것이며, 이는 빈 결과를 초래합니다.
API 지갑 프루닝
API 지갑과 그에 연관된 논스 상태는 다음의 경우 프루닝(제거)될 수 있습니다:
- 지갑이 등록 해제되는 경우. 이는 새로운 무명(unnamed) API 지갑을 등록하는 ApproveAgent 액션이 전송될 때 기존 무명 API 지갑에서 발생합니다. 또한 일치하는 이름으로 ApproveAgent 액션이 전송될 때 기존 기명(named) API 지갑에서도 발생합니다.
- 지갑이 만료되는 경우.
- 에이전트를 등록한 계정에 더 이상 자금이 없는 경우.
중요: API 지갑을 프로그래밍 방식으로 사용하는 경우, 주소를 재사용하지 않을 것을 강력히 권장합니다. 에이전트가 등록 해제되면 그 사용된 논스 상태가 프루닝될 수 있습니다. 예기치 않은 동작을 피하기 위해 향후 사용 시 새로운 에이전트 지갑을 생성하세요. 예를 들어, 논스 집합이 프루닝되면 이전에 서명된 액션이 리플레이될 수 있습니다.
Hyperliquid 논스
Ethereum의 설계는 온체인 오더북에는 적합하지 않습니다. 마켓메이킹 전략은 초당 수천 건의 주문과 취소를 전송할 수 있습니다. 블록체인에 포함되는 정확한 순서를 요구하면 어떤 전략이든 깨지게 됩니다.
Hyperliquid에서는 주소별로 가장 높은 100개의 논스가 저장됩니다. 모든 새 트랜잭션의 논스는 이 집합에서 가장 작은 논스보다 커야 하며, 한 번도 사용된 적이 없어야 합니다. 논스는 사이너별로 추적되며, 주소의 개인 키로 서명한 경우 사용자 주소, API 지갑으로 서명한 경우 에이전트 주소가 사이너입니다.
논스는 (T - 2 days, T + 1 day) 범위 내에 있어야 합니다. 여기서 T는 트랜잭션이 포함된 블록의 유닉스 밀리초 타임스탬프입니다.
중앙화 거래소에서 자동화 전략을 이식해 올 때 다음 단계가 도움이 될 수 있습니다:
- 트레이딩 프로세스마다 API 지갑을 하나씩 사용하세요. 논스는 사이너(즉, 개인 키)별로 저장되므로, 동일한 API 지갑으로 서명하는 개별 서브계정들은 해당 API 지갑의 논스 트래커를 공유합니다. 서로 다른 서브계정에는 별도의 API 지갑을 사용하는 것이 좋습니다.
- 각 트레이딩 프로세스에서 0.1초마다 주문과 취소 요청을 주기적으로 배치(batch)하는 태스크를 두세요. ALO 주문 단위 배치는 검증인에 의해 우선 처리되므로, IOC 및 GTC 주문은 ALO 주문과 분리하여 배치하는 것이 좋습니다.
- 트레이딩 로직 태스크는 주문과 취소를 배치 태스크로 전송합니다.
- 주문 또는 취소의 각 배치에 대해, 해당 주소에 고유한 논스를 보장하는 원자적 카운터를 가져와 증가시키세요. 원자적 카운터는 필요한 경우 현재 유닉스 밀리초로 빨리 감기(fast-forward)할 수 있습니다.
이 구조는 2초 이내의 트랜잭션 순서 뒤바뀜에 강건하며, API 서버와 지리적으로 가까운 자동화 전략에는 충분할 것입니다.
서브계정 및 볼트 사용자를 위한 권장 사항
논스는 트랜잭션에 서명하는 데 사용된 개인 키의 주소인 사이너별로 저장된다는 점에 유의하세요. 따라서 각 트레이딩 프로세스 또는 프론트엔드 세션이 서명에 별도의 개인 키를 사용하는 것이 좋습니다. 특히, 사용자·볼트·서브계정에 대해 서명하는 단일 API 지갑은 모두 동일한 논스 집합을 공유합니다.
사용자가 여러 서브계정을 병렬로 사용하려는 경우, 마스터 계정 아래에 두 개의 별도 API 지갑을 생성하고 각 서브계정마다 하나의 API 지갑을 사용하는 것이 더 쉽습니다. 이는 각 서브계정이 사용하는 논스 집합 간의 충돌을 피합니다.