китаев.tech

Gas — как считается и кто платит

Как Ethereum считает комиссию транзакции: gas limit, gas used, base fee, priority fee и кто платит за выполнение.

Gas — как считается и кто платит

Gas — это единица стоимости вычислений в Ethereum.

Любая запись в State требует работы EVM: проверить подпись, изменить баланс, выполнить код контракта, записать логи. За эту работу платит отправитель транзакции.


Формула комиссии

text
Комиссия = gasUsed × effectiveGasPrice

gasUsed — сколько gas реально потратила транзакция.

effectiveGasPrice — фактическая цена одного gas в wei.

Если транзакция потратила 21 000 gas, а цена gas была 20 gwei, комиссия будет:

text
21 000 × 20 gwei = 420 000 gwei = 0.00042 ETH

Считаем комиссию реальной транзакции

typescript
import { ethers } from "ethers";

const provider = new ethers.JsonRpcProvider("https://ethereum.publicnode.com");

const block = await provider.getBlock("latest");

if (!block || block.transactions.length === 0) {
  throw new Error("В последнем блоке нет транзакций");
}

const txHash = block.transactions[0];
const tx = await provider.getTransaction(txHash);
const receipt = await provider.getTransactionReceipt(txHash);

if (!tx || !receipt) {
  throw new Error("Транзакция ещё не доступна через RPC");
}

const minedBlock = await provider.getBlock(receipt.blockNumber);
const baseFeePerGas = minedBlock?.baseFeePerGas ?? 0n;
const effectiveGasPrice = receipt.gasPrice;
const totalFee = receipt.gasUsed * effectiveGasPrice;
const priorityFeePerGas = effectiveGasPrice > baseFeePerGas
  ? effectiveGasPrice - baseFeePerGas
  : 0n;

console.log("Hash:", tx.hash);
console.log("From:", tx.from);
console.log("Gas limit:", tx.gasLimit.toString());
console.log("Gas used:", receipt.gasUsed.toString());
console.log("Base fee:", ethers.formatUnits(baseFeePerGas, "gwei"), "gwei");
console.log("Priority fee:", ethers.formatUnits(priorityFeePerGas, "gwei"), "gwei");
console.log("Effective gas price:", ethers.formatUnits(effectiveGasPrice, "gwei"), "gwei");
console.log("Total fee:", ethers.formatEther(totalFee), "ETH");

Этот код берёт транзакцию из последнего блока mainnet и считает, сколько ETH она реально стоила отправителю.


Как это работает

tx.gasLimit — максимум gas, который отправитель разрешил потратить.

receipt.gasUsed — сколько gas транзакция потратила после выполнения в EVM.

receipt.gasPrice — фактическая цена gas для уже включённой транзакции.

baseFeePerGas — обязательная часть комиссии. Она сжигается протоколом и не достаётся валидатору.

priorityFeePerGas — чаевые валидатору за включение транзакции в блок.

receipt.gasUsed * receipt.gasPrice — итоговая комиссия, списанная с отправителя.


Gas limit vs gas used

gasLimit — это лимит, а не точная цена.

text
gasLimit = 100 000
gasUsed  = 63 421

Платите только за 63 421 gas

Неиспользованный gas возвращается отправителю. Если gas закончился во время выполнения, транзакция падает, изменения State откатываются, но потраченный gas не возвращается.


Кто платит

Платит всегда EOA, который подписал транзакцию.

Если вы вызываете контракт, комиссию платит ваш кошелёк. Если контракт внутри своей логики вызывает другой контракт, комиссию всё равно платит исходный отправитель транзакции.

text
EOA отправил транзакцию

Контракт A выполнил код

Контракт A вызвал Контракт B

Gas платит EOA

Контракт может компенсировать пользователю расходы отдельной логикой, но на уровне протокола gas списывается с отправителя транзакции.


Почему чтение бесплатно

eth_call не меняет State. RPC-нода локально симулирует выполнение и возвращает результат.

Поэтому balanceOf(), name(), decimals() и другие view функции можно читать бесплатно. Но если та же функция вызывается внутри транзакции, её выполнение уже потребляет gas.


Частые ошибки

Путать gas и ETH → gas измеряет работу EVM, ETH оплачивает эту работу.

Думать, что gasLimit всегда списывается полностью → списывается только gasUsed × effectiveGasPrice, неиспользованный gas возвращается.

Считать failed-транзакцию бесплатной → если транзакция попала в блок и упала, gas за выполненные операции всё равно списывается.


Что дальше

Материалы китаev.tech публикуются в образовательных целях и не являются инвестиционной рекомендацией. Примеры кода и описания протоколов — для обучения; использование в продакшне на ваш собственный риск. Дисклеймер и политика конфиденциальности.