Skip to content

Gas燃料费

燃料费

燃料费给我们最直观的感知就是日常生活中汽车所使用的汽油的费用,即在加油时付给加油站的油费。以太坊中的燃料费也可以这么理解(以太坊中习惯称为燃料费而不是油费)。

在以太坊中,燃料费付给的不是加油站,而是节点中的矿工。我们付给矿工燃料费的目的是让矿工帮助处理交易订单,把交易订单打包到区块中去。注意这段话中的关键词交易订单,不是转账,转账是交易的真子集。

以太坊中的燃料费又称为手续费,英文单词对应的是Gs。它是用来激励矿工把交易订单打包到区块中而付给矿工的打包费。此外,燃料费的高低会影响当前交易订单被打包的速率,高燃料费的交易订单将会优先被矿工打包进区块,以太坊使用这种价高者优先的策略保证了矿工利益的最大化。

在交易时,燃料费或手续费Gas(单位是wei)并不属于交易函数的参数,它的计算方式是:

go
GasUsed X GasPrice = Gas

我们可以采用下面的例子来进一步理解GasUsed和GasPrice的关系,假设GasUsed代表的是苹果的数量,那么每个苹果的单价就是GasPrice。买了10个苹果,这10个苹果的总价格就是数量乘以单价,最终的总价就是Gas,也就是GasUsed X GasPrice。

公式中的GasUsed和GasPrice在以太坊中有两种解析,分别是:

  1. 基于区块Header的解析。
  2. 作为以太坊交易函数入参(Input Parameter)的解析。

第一种解析,在前文介绍Header区块时已介绍过。第二种解析,在以太坊交易中,当前的交易被矿工打包到区块中时,究竞要付给矿工多少Gs手续费,实际上和交易函数(接口)所携带的参数有关。交易订单被矿工打包进区块中时消耗的是GasUsed,代表实际使用了多少燃料,GasPrice指单价,两者的乘积就是Gas然料费的真实值。

那么,为什么以太坊的矿工打包要消耗Gas,直接打包不就行了吗?这里的原因如下:

  • 弥补计算机资源消耗的代价,因为以太坊公链允许每个人到上面进行交易,这些交易的背后依赖的是代码,而代码的运行自然依赖计算机资源,例如我们常见的服务器费用。
  • 防止不法分子对以太坊网络蓄意攻击或滥用,以太坊协议规定交易或合约调用的每个运算步骤都需要收费,以增加攻击代价。

但是,请注意,以太坊上的操作并非都要扣除燃料费才能进行,常见的需要扣除燃料费的情况有:

  • 交易类型的ETH或ERC20代币转账。
  • 发布智能合约。
  • ERC20代币授权。

从最直观的代码的角度来看,扣除燃料费的操作有一个共同点一它们都是通过调用以太坊的eth_sendTransactioneth_sendRawTransaction接口实现的。

An image

ether就是一个ETH,1eX代表的是10的多少次方。

GasUsed的计算

由燃料费的计算公式GasUsed X GasPrice=Gas可知,真正影响然料费计算结果的是GasUsed。

GasUsed的计算是比较复杂的,主要分为两部分:

  1. 数据量部分,对应交易函数中的data入参(Input Parameter)。
  2. 虚拟机(EVM)执行指令的部分。
go
// Per transaction not creating a contract.
// NOTE:Not payable on data of calls between transactions.
TxGas uint64=21000
// Per transaction that creates a contract.
// NOTE:Not payable on data of calls between transactions.
TxGasContractCreation uint64=53000

从源码中可以看到,对于每一笔交易中的数据量部分的燃料费是通过统计不同类型的字节来计算的,这部分还有一个影响计算的基础量,就是默认的燃料费数值,分下面两种情况:

  1. 创建合约的交易,基础量为53000。
  2. 非创建合约的交易,基础量为21000。

当我们在交易函数中设置的GasLimit比基础量还要小时,就会导致交易失败,出现的错误信息是intrinsic gas too low(固有的燃料太少了);随后在这个基础量的前提下,对数据所占有的字节量计算燃料费,计算的方式也按照以太坊设置的规则,即:

  1. 0字节的收费是4,每发现一个0字节,基础量累加4。
  2. 非0字节的收费68,每发现一个非0字节,基础量累加68。

An image

第一部分燃料费的计算是发生在交易被添加进订单池之前,也是在第一部分数据量所占有燃料费的数值计算结束之后。

对于第二部分的虚拟机(EVM)执行指令的计算过程发生的时机,目前有两种情况:

  1. 在以太坊的矿工(Miner)模块从交易池中取出交易准备打包到区块中之前。
  2. 将区块插入区块链之前需要验证区块的合法性。