1. 什么是gas?
- gas是“燃料”的意思。在以太坊区块链上实现了一个EVM(以太坊虚拟机)的代码运行环境,在链上执行写入操作时,网络中的每个全节点都会进行相同的计算并存储相同的值。
- 这种执行的消耗是昂贵的,为了促使大家将能在链下进行的运算都不放到链上进行,也为了奖励矿工,在链上每执行一个写入操作时,都需要支付一定的费用,用gas为单位来计数。
- 每个在链上可以执行的命令都设置了一个消耗的gas值,例:
PUSH操作
需要消耗3个gas
,一次转账
一般要消耗21000 gas
,gas使用ether
来支付。 - 1 ether = 1 x 10^18 wei = 1 x 10^9 Gwei 。
注意:无论您执行的命令是成功还是失败,都需要支付计算费用,即使失败,节点也验证并执行了您的交易(计算),因此必须和成功执行支付一样的费用。
2. 什么是gasPrice?
Gas Price
就是你愿意为一个单位的Gas出多少ether
,一般用Gwei
作单位。Gas Price
越高,就表示交易中每运算一步,会支付更多的ether
。- 通过
gas price
可以节省矿工费用,但也会减慢矿工打包的速度。因为,矿工会优先打包gas price
设置高的交易,如果您想加快转账,您可以把gas price
设置得更高,这样您就可以插队靠前。 - 以太坊的交易手续费为:
TxFee = gas * gas Price
,单位Gwei
。 一次转账
一般要消耗21000 gas
,如果你设置的gas Price = 1000000000wei = 1Gwei
,则此次转账的交易手续费为:TxFee = 21000 Gwei = 0.000021 ether
。- A账户欲向B账户转账
4 ether
,则要求A账户至少要有4 + 0.000021 = 4. 000021 ethrer
。
最后值得一提的是
Gas Price
越高,你提交的交易会越快被矿工接纳。 但通常人们都不愿多支付手续费, 那么究竟应该将Gas Price设置为多少,才可以保证在能接受的时间内,让交易被确认到区域链上呢?
我们可以为交易定义gas price
,具体的值可以参考 ETH gas station 。这里能看到以太坊区块链上最近完成的交易对应的消耗单价、记录时间、等待时间、手续费均价等。根据自身交易需求,我们可以参考右下Safelow/Standard/Fast
三个速度对应的gasPrice
。
3. 如何设置gas和gasPrice?
- 为了能让交易更快地被执行,我们可以在发起交易时设置
gas和gasPrice
,还可以设置noce
,设置方法如下:
eth.sendTransaction({
from: 0x4fd9555dd1309e7a2a356ea7e92c1b41cb7bb144,
to: 0xf7deba629960e4f31f1aba61927f6f1e966c4462,
value: web3.toWei(1, "ether"),
gas: 60000,
gasPrice: web3.toWei(40,'gwei'),
nonce: 30
});
参考链接:
以太坊转账 gas 费用太低,一直 pending 怎么办
4. 什么是gasLimit?
Gas Limit
就是一次交易中gas
的可用上限,也就是你的交易中最多会执行多少步运算。 由于交易复杂程度各有不同,
确切的Gas消耗量是在完成交易后才会知道,因此在你提交交易之前,需要为交易设定一个Gas用量的上限。- 每个区块有
gas limit
,即单个区块允许的最多gas总量,可以用来决定单个区块中能打包多少笔交易。 - 我们每一次交易或合约调用都要设置一个
gas limit
,如果该次操作所使用的gas数量小于或等于您所设置的gas limit
,则会被执行。但如果gas总消耗量超过gas limit
,所有的操作都会被重置,但费用依旧会被收取——因为要奖励已经付出劳动的矿工。 - 在执行中实际消耗的gas值总和叫
gas used
,gas used
未达到gas Limit
, 那么只会按实际gas used
收取交易服务费,没有使用完的gas会退还到原账号。根据我查找的资料来看,这里所说的gas Limit
就是指chapter 3
中的gas属性
。 - 如果您尝试将一个会使用超过当前区块
gas limit
的交易打包,则会被网络拒绝,会反馈below gas limit
。
5. 手续费不足异常(insufficient funds)的解决
- 在多主机多节点的转账过程中,自己本来想从节点01的A账户(里面有
4 ether
)向节点02的B账户(里面0 ether
)转账1 ether
,粗心的将节点03搞成了节点01。节点03的A账户里面0 ether
,因此报出了insufficient funds
异常。
> eth.sendTransaction({from:eth.accounts[1],to:"0x4161514855682c94e3cbcb4808eb8766cf889e17",value:web3.toWei(1,"ether")})
Error: insufficient funds for gas * price + value
at web3.js:3143:20
at web3.js:6347:15
at web3.js:5081:36
at <anonymous>:1:1
-
因此查询了
insufficient funds
异常的解决办法,汇总如下:
① 创世区块的配置问题:关于以太坊私有链中进行交易时余额不足的问题处理,更改了chainId
,估计很难遇到由chainId
引起的异常。
② 更靠谱的方法是,计算一下gas*gasPrice + value
是不是大于当前账户的值,这里的value是指交易金额。参考链接:https://liankexing.com/question/question_page/id/757.html。 -
自己就是属于上面的
第二种情况
,而且是一种很极端的情况,对没有任何余额的账户进行转账操作
!傻逼了~ -
如何计算
gas*gasPrice + value
是不是大于当前账户的值?
//使用eth.estimateGas()方法来估计gas消耗量
> gas = eth.estimateGas({from:from, to: to, value: web3.toWei(2,"ether")})
21000
//获取gasPrice,单位为 wei
> eth.gasPrice
1000000000
//计算交易手续费TxFee
> fee = gas*eth.gasPrice
21000000000000
//计算gas*gasPrice + 2 ether
> parseInt(fee) + parseInt(web3.toWei(2,"ether"))
2000021000000000000
//查看账户余额
> eth.getBalance(eth.accounts[0])
201000042000000000000
//账户余额远大于gas*gasPrice + value,可以执行转账
> eth.sendTransaction({from:eth.accounts[1],to:"0x4161514855682c94e3cbcb4808eb8766cf889e17",value:web3.toWei(1,"ether")})
INFO [03-24|11:49:52.745] Setting new local account address=0x74f3141E22E415dD9eDAae9CD1EF26E4EF704984
INFO [03-24|11:49:52.746] Submitted transaction fullhash=0x6c82be3da7181b7d2c44398f35453e2d21e16a2cb376b29556d1fb30c4addb51 recipient=0x4161514855682C94e3CBcb4808eb8766cf889e17
"0x6c82be3da7181b7d2c44398f35453e2d21e16a2cb376b29556d1fb30c4addb51"
计算方法的参考链接:
以太坊估算交易gas消耗量
以太坊中以太币及代币计量单位
以太坊手续费不足异常(insufficient funds)
参考链接:
以太坊中的gas、gas price、gas limit到底是什么
以太坊中的Gas、GasPrice和GasLimit是什么?
以太坊中的交易及交易费用