Wagmi를 사용하여 과거 블록에서 컨트랙트 상태 읽기
Source: Dev.to
핵심 아이디어
Ethereum(및 일반적인 EVM 체인)은 언제든지 과거 블록에 존재했던 계약 상태를 조회할 수 있게 해줍니다. 계약 메서드가 view 혹은 pure라면 특별한 인덱싱 인프라 없이도 과거 블록에서 읽을 수 있습니다. Wagmi는 blockNumber 파라미터를 통해 이를 직접 노출합니다.
시나리오: 과거 시점의 Chainlink 가격
Chainlink 가격 피드는 latestRoundData()와 같은 메서드를 제공합니다. 라운드 ID를 이미 알고 있다면 직접 조회할 수 있지만, 때때로 타임스탬프만 알고 있을 때가 있습니다. 신뢰할 수 있는 방법은 관심 있는 타임스탬프를 블록 번호로 변환한 뒤 해당 블록에서 계약을 읽는 것입니다.
import { readContract } from '@wagmi/core';
import { parseAbi } from 'viem';
const aggregatorAbi = parseAbi([
'function latestRoundData() view returns (uint80,int256,uint256,uint256,uint80)'
]);
const priceFeedAddress = '0x...';
const blockNumber = 18_500_000n; // 원하는 타임스탬프에 해당하는 블록
const data = await readContract({
address: priceFeedAddress,
abi: aggregatorAbi,
functionName: 'latestRoundData',
blockNumber,
});
Wagmi는 RPC 노드에 “블록 18,500,000에 체인이 있다고 가정하고 이 함수가 무엇을 반환하는가?”라고 묻습니다. 결과는 해당 블록에서 Chainlink 계약이 반환했을 정확한 값이며, 현재 값이 아닙니다.
왜 작동하는가
Ethereum 노드는 과거 상태를 저장합니다. blockNumber를 지정하면 노드는 그 히스토리 스냅샷에 대해 호출을 실행합니다—서브그래프나 외부 인덱서가 필요 없으며, 블록체인 상태만으로 결정적입니다.
시간 → 블록 매핑
보통 블록 번호보다 타임스탬프를 알고 있습니다. 해당 블록을 찾는 일반적인 방법은 다음과 같습니다:
- 이진 탐색:
eth_getBlockByNumber를 사용해 타임스탬프 기준으로 블록을 검색. - 헬퍼 API(예: 블록 탐색기 서비스) 활용 후 매핑을 캐시.
- 아카이브 노드 사용 – 가장 정확함.
블록 번호를 확보하면 나머지는 Wagmi가 처리합니다.
React와 함께하는 프론트엔드 예시
React 앱에서 Wagmi 훅을 사용한다면:
import { useReadContract } from 'wagmi';
const { data } = useReadContract({
address: priceFeedAddress,
abi: aggregatorAbi,
functionName: 'latestRoundData',
blockNumber: 18_500_000n,
});
활용 사례
- 과거 가격 차트
- 이전 계약 상태 감사
- 특정 시점의 온체인 데이터가 필요한 모든 기능
중요한 주의사항
- RPC 지원: 모든 RPC 제공자가 히스토리 상태를 제공하는 것은 아니며, 아카이브 노드가 필요할 수 있습니다.
- 성능: 오래된 블록에 대한 쿼리는 현재 상태 호출보다 느릴 수 있습니다.
마무리 생각
Wagmi는 이 기능을 크게 홍보하지 않지만, 언제든지 계약 상태를 과거 시점에서 읽을 수 있다는 것을 깨닫게 되면 많은 문제를 더 간단히 해결할 수 있습니다. blockNumber를 활용하면 오프체인 스냅샷이나 인덱서에 의존하지 않고 과거의 정확한 온체인 데이터를 가져올 수 있습니다.