Как работает подтверждение блока
Что значит confirmation в Ethereum: как блоки подтверждают транзакцию, как считать confirmations и почему приложения ждут несколько блоков.
Как работает подтверждение блока
Подтверждение блока — это новый блок, который появился поверх блока с вашей транзакцией.
Если транзакция попала в блок 100, а текущий блок 103, у транзакции 4 confirmation: сам блок 100 и три блока после него.
Что считается подтверждением
Блок 100: транзакция включена
Блок 101: 2 confirmations
Блок 102: 3 confirmations
Блок 103: 4 confirmationsКогда транзакция только попала в блок, она уже выполнена и имеет receipt. Но приложение может подождать несколько confirmations, чтобы снизить риск reorg.
Читаем confirmations через RPC
import { ethers } from "ethers";
const provider = new ethers.JsonRpcProvider("https://ethereum.publicnode.com");
const latestBlock = await provider.getBlock("latest");
if (!latestBlock || latestBlock.transactions.length === 0) {
throw new Error("В последнем блоке нет транзакций");
}
const txHash = latestBlock.transactions[0];
const tx = await provider.getTransaction(txHash);
const receipt = await provider.getTransactionReceipt(txHash);
const currentBlockNumber = await provider.getBlockNumber();
if (!tx || !receipt) {
throw new Error("Транзакция ещё не доступна через RPC");
}
const confirmations = currentBlockNumber - receipt.blockNumber + 1;
console.log("Hash:", tx.hash);
console.log("Included in block:", receipt.blockNumber);
console.log("Current block:", currentBlockNumber);
console.log("Confirmations:", confirmations);
console.log("Receipt confirmations:", await receipt.confirmations());
console.log("Status:", receipt.status === 1 ? "success" : "failed");Этот код берёт транзакцию из свежего блока mainnet и показывает, сколько подтверждений у неё уже есть.
Как это работает
provider.getBlock("latest") — читает свежий блок.
latestBlock.transactions[0] — берёт hash первой транзакции из блока.
provider.getTransactionReceipt(txHash) — возвращает receipt: результат выполнения и номер блока, куда попала транзакция.
provider.getBlockNumber() — читает текущую высоту сети.
currentBlockNumber - receipt.blockNumber + 1 — считает confirmations. + 1 нужен, потому что блок с самой транзакцией тоже считается первым подтверждением.
Pending, confirmed и finalized
У транзакции есть несколько состояний:
| Состояние | Что значит |
|---|---|
| Pending | транзакция в mempool, блока ещё нет |
| Confirmed | транзакция попала в блок и получила receipt |
| Finalized | блок стал финальным на уровне консенсуса Ethereum |
Для UX часто достаточно 1 confirmation: пользователь видит, что транзакция выполнена.
Для депозитов, мостов и крупных переводов приложения обычно ждут больше confirmations или finalized-состояние.
Что такое reorg
Reorg — это ситуация, когда сеть на короткое время выбирает другую цепочку блоков.
Было:
100 → 101A → 102A
Стало:
100 → 101B → 102B → 103BЕсли транзакция была в блоке 101A, но новый canonical chain использует 101B, транзакция может снова стать pending или попасть в другой блок.
Чем больше блоков построено поверх вашего блока, тем ниже риск reorg.
Сколько confirmations ждать
Для обычного интерфейса:
0 confirmations → показывать "ожидает включения"
1 confirmation → показывать "выполнено"
2+ confirmations → считать результат устойчивееДля финансовой логики не хардкодьте одно число для всех сетей. У Ethereum mainnet, L2 и sidechain разная модель финальности.
Частые ошибки
Считать pending-транзакцию выполненной → пока нет receipt, State сети не изменился.
Забывать про + 1 при ручном подсчёте → блок с транзакцией уже даёт первое confirmation.
Ждать одинаковое число confirmations на всех сетях → mainnet, L2 и мосты имеют разные правила финальности и разные риски.
Что дальше
- Как работает транзакция изнутри — что происходит до появления receipt
- Что такое nonce и зачем он нужен — почему pending-транзакции блокируют следующие
- Gas — как считается и кто платит — почему failed-транзакция с confirmation всё равно стоит gas