요약
시스템 트랜잭션은 Stable 프로토콜이 Stable SDK 작업에 대한 EVM 이벤트를 발생시킬 수 있는 방법을 제공합니다. 언본딩 완료와 같은 스테이킹 이벤트가 SDK 계층에서 발생하면 프로토콜은 해당 이벤트를 발생시키는 EVM 트랜잭션을 자동으로 생성하여 이러한 작업이 EVM 도구 및 애플리케이션에 완전히 표시되도록 합니다.동기
Stable의 EVM 사용자와 애플리케이션은eth_getLogs와 같은 표준 EVM 인터페이스를 통해 블록체인 이벤트를 모니터링할 것으로 기대합니다. 그러나 중요한 작업은 EVM 이벤트를 자연스럽게 발생시키지 않는 Stable SDK 모듈에서 발생합니다. 이는 가시성 격차를 만듭니다: EVM dapp은 사용자의 토큰이 언제 언본딩을 완료하는지 쉽게 추적할 수 없습니다.
시스템 트랜잭션은 이 격차를 해소합니다. 스테이킹 모듈이 언본딩 작업을 완료하면 Stable의 x/stable 모듈이 이벤트를 감지하고 StableSystem 프리컴파일 (0x0000000000000000000000000000000000009999)을 호출하는 시스템 트랜잭션을 생성합니다. 그런 다음 프리컴파일은 모든 dapp이 구독할 수 있는 적절한 EVM 이벤트를 발생시킵니다. 시스템 트랜잭션은 프로토콜만 사용할 수 있는 특수 발신자 주소(0x0000000000000000000000000000000000000001)로 실행됩니다. 이는 누구도 프로토콜 이벤트를 위조할 수 없도록 방지하면서 이벤트 발생을 무신뢰적이고 온체인에서 검증 가능하게 유지합니다.
명세
시스템 트랜잭션은 세 가지 주요 구성 요소를 통해 작동합니다: x/stable 모듈의 EndBlocker, PrepareProposal 핸들러 및 StableSystem 프리컴파일입니다.아키텍처 개요

StableSystem 프리컴파일
StableSystem 프리컴파일은0x0000000000000000000000000000000000009999에 있으며 EVM 이벤트를 발생시켜야 하는 프로토콜 수준 작업을 처리합니다. 현재 언본딩 완료 알림을 지원합니다.
시스템 트랜잭션 발신자
시스템 트랜잭션은0x0000000000000000000000000000000000000001을 발신자 주소로 사용합니다. 이 주소는:
- 서명 검증이 필요 없음
- PrepareProposal에서 생성된 트랜잭션만 사용 가능
- 사용자나 컨트랙트가 위조할 수 없음
- SystemTxDecorator ante 핸들러를 통해 수수료 공제를 건너뜀
msg.sender == 0x1을 확인하여 시스템 트랜잭션을 인식합니다. 프리컴파일은 이를 사용하여 프로토콜 전용 작업을 제한할 수 있습니다.
이벤트 기반 흐름
사용자의 언본딩 기간이 완료되면 다음과 같은 일이 발생합니다:- Stable SDK 계층: 스테이킹 모듈의 EndBlocker가 언본딩을 완료하고 위임자 주소, 검증자 주소 및 금액과 함께 EventTypeCompleteUnbonding을 발생시킵니다.
- 감지: x/stable 모듈의 EndBlocker는 스테이킹 이후에 실행되며 블록의 이벤트 로그에서 언본딩 이벤트를 스캔합니다. 각 완료에 대해 위임자 주소, 검증자 주소, 금액 및 블록 높이를 포함하는 항목을 상태에 큐에 넣습니다.
- 시스템 트랜잭션 생성: 다음 블록의 PrepareProposal에서 앱은 대기 중인 모든 완료를 쿼리합니다. 있는 경우 현재 블록 높이로 StableSystem.notifyUnbondingCompletions(blockHeight)를 호출하는 시스템 트랜잭션을 생성합니다. 이 트랜잭션은 사용자 트랜잭션보다 먼저 블록 앞에 배치됩니다.
- 실행: 블록 실행 중에 시스템 트랜잭션이 먼저 실행됩니다. 프리컴파일은 해당 블록 높이에서 대기 중인 완료에 대한 상태를 쿼리하고, 각 완료에 대해 UnbondingCompleted 이벤트를 발생시키며(최대 100개), 큐에서 삭제합니다.
- EVM 가시성: 이벤트는 트랜잭션 영수증과 로그에 나타나며, eth_getLogs 쿼리, 블록 탐색기 및 StableSystem 프리컴파일을 모니터링하는 모든 애플리케이션에 표시됩니다.
배치 처리
블록이 너무 커지는 것을 방지하기 위해 시스템은 블록당 최대 100개의 언본딩 완료를 처리합니다. 150개의 완료가 큐에 들어가면:- 블록 N: 완료 0-99를 처리하는 시스템 트랜잭션 생성
- 블록 N+1: 완료 100-149를 처리하는 시스템 트랜잭션 생성
사용 예시
가장 일반적인 사용 사례는 언본딩 기간이 완료될 때 사용자에게 알려야 하는 스테이킹 대시보드입니다. 다음은 언본딩 완료 리스너를 설정하는 방법입니다.특정 사용자에 대한 이벤트 필터링
특정 위임자 주소에 대한 이벤트만 받으려면 인덱싱된 이벤트 매개변수를 사용하여 필터를 만듭니다:과거 이벤트 쿼리
dApp에서 과거 언본딩 완료 기록을 표시해야 하는 경우 블록 범위가 있는 이벤트 필터를 사용하여 과거 이벤트를 쿼리할 수 있습니다:통합 가이드
단계 1: Stable System 컨트랙트 인터페이스 추가
먼저 StableSystem 프리컴파일 인터페이스를 프로젝트에 추가합니다. Foundry 또는 Hardhat을 사용하는 경우 새 인터페이스 파일을 생성합니다:단계 2: 이벤트 리스너 설정
ethers.js provider를 초기화하고 StableSystem 프리컴파일 주소를 가리키는 컨트랙트 인스턴스를 생성합니다. 프리컴파일은 Stable 테스트넷과 메인넷 모두에서 항상0x00000000000....0000009999에 배포됩니다.
참고: 프리컴파일은 아직 Stable 메인넷에 배포되지 않았으며 v1.2.0 업그레이드 후에 제공됩니다.
단계 3: 애플리케이션 로직에서 이벤트 처리
이벤트를 구독하고 애플리케이션 상태를 그에 따라 업데이트합니다. 일반적인 패턴은 다음과 같습니다:- 잔액 업데이트: 언본딩이 완료되면 사용자의 토큰 잔액을 새로 고침
- 알림 시스템: 사용자의 언본딩이 완료될 때 토스트 알림 표시
- 대시보드 통계: 실시간으로 스테이킹 지표 및 차트 업데이트
- 트랜잭션 기록: 완료된 언본딩을 사용자의 활동 피드에 추가
단계 4: 연결 문제 처리
이벤트 구독은 지속적인 websocket 연결에 의존하므로 프로덕션 dApp을 위한 재연결 로직을 구현합니다:왜 이 방법인가?
커스텀 인덱서와 비교
이전에는 Stable SDK가 dApp 개발자에게 SDK 이벤트를 감시하고 데이터베이스에 저장하는 커스텀 인덱서를 실행하도록 요구했습니다. 이는 운영 오버헤드를 추가하고 잠재적인 실패 지점을 도입합니다. 시스템 트랜잭션을 사용하면 별도의 인덱서 인프라가 필요하지 않습니다. 이벤트는 모든 RPC 노드가 이미 인덱싱하고 제공하는 EVM의 로그 시스템을 통해 기본적으로 사용할 수 있습니다. 모든 표준 web3 라이브러리는 추가 도구 없이 이러한 이벤트를 구독할 수 있습니다.SDK 엔드포인트 폴링과 비교
시스템 트랜잭션이 없으면 EVM dApp은 언본딩 기간이 완료되었는지 확인하기 위해 주기적으로 Stable SDK REST 엔드포인트를 호출해야 합니다. 이는 여러 문제를 야기합니다:- 지연 시간 증가: 5-10초의 폴링 간격은 사용자가 업데이트를 보기 전에 그만큼 기다려야 함을 의미합니다
- 더 높은 부하: 모든 dApp 인스턴스의 엔드포인트 폴링은 RPC 인프라의 부하를 증가시킵니다
- 복잡성: dApp은 web3 프로바이더(EVM 상호 작용용)와 Stable SDK REST 클라이언트(SDK 쿼리용)를 모두 처리해야 합니다
- 실시간 업데이트 없음: 폴링은 본질적으로 즉각적인 알림을 제공할 수 없습니다
보안 보증
무신뢰 이벤트 발생
시스템 트랜잭션은 검증자만 실행할 수 있는PrepareProposal ABCI 단계에서 생성됩니다. 사용자가 제출한 트랜잭션은 EVM의 상태 전환 로직이 StableSystem 프리컴파일 주소로의 트랜잭션만 서명 검증을 건너뛸 수 있도록 강제하기 때문에 시스템 발신자 주소(0x1)를 위조할 수 없습니다.
이것은 다음을 의미합니다:
- 사용자는 언본딩 완료 이벤트를 위조할 수 없습니다
- 사용자는 자신의 트랜잭션에서
notifyUnbondingCompletions을 호출할 수 없습니다 UnbondingCompleted이벤트를 발생시키는 유일한 방법은 Stable SDK 스테이킹 모듈에서 실제로 언본딩을 완료하는 것입니다
추가 신뢰 가정 없음
시스템 트랜잭션은 블록체인 합의에 이미 필요한 것 이상의 새로운 보안 가정을 도입하지 않습니다. 검증자가 블록을 올바르게 실행하고 있다고 신뢰한다면 시스템 트랜잭션 이벤트가 Stable SDK 상태 변경을 정확하게 반영한다고 신뢰할 수 있습니다. 이벤트 발생 프로세스는 결정론적입니다:EndBlock에서 동일한 SDK 이벤트가 주어지면 모든 정직한 검증자는 PrepareProposal 중에 동일한 시스템 트랜잭션을 생성합니다. 합의 메커니즘은 검증자가 포함할 시스템 트랜잭션에 대해 합의하도록 보장합니다.
블록 최종성
Stable 블록체인은 StableBFT의 합의 메커니즘을 통해 빠른 최종성을 사용합니다. 블록이 커밋되면 즉시 최종화되며 재구성될 수 없습니다. 이는UnbondingCompleted 이벤트를 받으면 영구적이라고 신뢰할 수 있음을 의미합니다.
확률적 최종성 체인에서처럼 여러 확인을 기다릴 필요가 없습니다. dApp은 이벤트를 받은 즉시 사용자 잔액을 업데이트하고 알림을 표시할 수 있습니다.
성능 및 제한 사항
배치 크기 제약
각 블록은 시스템 트랜잭션을 통해 최대 100개의 언본딩 완료를 처리합니다. 이 제한은 높은 언본딩 활동 기간 동안 무제한 블록 크기를 방지하기 위해 존재합니다. 실제로 블록당 100개의 완료는 평균 블록 시간이 0.7초라고 가정할 때 분당 약 9000개의 완료 처리량을 제공합니다. 일반적인 스테이킹 활동은 이 제한에 거의 도달하지 않습니다. 예외적인 상황에서는 완료가 완전히 처리되기 전에 여러 블록 동안 큐에 대기할 수 있습니다.Gas 소비
시스템 트랜잭션은 실행 중에 gas를 소비하며, 이는 블록의 gas 제한에서 고려됩니다. gas 비용은 처리되는 완료 수에 따라 선형적으로 증가합니다:- 기본 함수 호출: 약 21,000 gas
- 이벤트 발생당: 약 3,000 gas
- 상태 읽기: 완료당 약 2,000 gas
알림 지연
블록 N 동안 언본딩 기간이 완료되면:- Stable 모듈의
EndBlock이 블록 N의 상태에서 완료를 큐에 넣습니다 - 블록 N+1의
PrepareProposal이 시스템 트랜잭션을 생성합니다 - 시스템 트랜잭션이 블록 N+1 동안 실행되어 이벤트를 발생시킵니다
고부하 시나리오
언본딩 완료가 블록당 100개보다 빠르게 도착하면 큐에 누적됩니다. 큐는 FIFO 순서로 처리되므로 가장 오래된 완료가 항상 먼저 알림을 받습니다. 지속적인 고부하 동안 큐가 일시적으로 증가할 수 있습니다. 그러나 급증이 가라앉으면 완료가 적은 후속 블록이 점차 큐를 배출합니다. 시스템은 이벤트를 삭제하지 않고 급증을 처리하도록 설계되었습니다.향후 확장
시스템 트랜잭션 메커니즘은 모든 Stable SDK 작업을 EVM 이벤트로 전달하는 일반적인 패턴을 제공합니다. 현재 언본딩 완료에만 사용되지만 아키텍처는 추가 사용 사례를 포괄하도록 확장될 수 있습니다.스테이킹 작업
언본딩 외에도 다른 스테이킹 이벤트가 EVM 알림을 발생시킬 수 있습니다:- 검증자의 수수료율 변경
- 검증자 Jail 및 Unjail

