周围朋友,微信圈,自己都遇到过因为网络拥堵导致交易迟迟不被打包,眼看ico额度被抢完却无能为力, 那有没有一种方法让我们取消未打包的交易呢?答案是肯定的,以太坊系统本身提供了替换交易的能力,也就是用新交易取消旧交易。
如何取消和重新发送交易
有几个流程
1)确保老交易还未被打包
2)获取老交易的nonce
3) 获取老交易的from
4)获取老交易的gasPrice
5)用上面的from, nonce并设置一个更高的gasPrice(至少为老交易的1.1倍), 构造一个新交易然后发送(需要from的私钥,即必须是from账号的拥有者)
前面四个信息都可以在etherscan输入老交易的txid(交易发起后是会返回一个txid)查询到,具体如下:
对于专业人员:
利用from, nonce, gasPrice等信息,然后通过web3.signRawTransaction即可构造新交易
运行geth的专业人员更容易:
eth.sendTransaction({from: eth.accounts[0], to: "...", gasPrice: “oldprice*1.2"})
var tx = eth.pendingTransactions[0]
eth.resend(tx, web3.toWei(10, “replace"))
对于普通用户:
通过myetherwallet钱包操作
如果显示”Transaction Found“,则已经打包进去,没法替换和取消了
如果显示“Transaction not found”,这说明交易还未传播到myetherwallet,继续等待一会
如果现实为上面的“Pending Transactions found”,可以unlock wallet, 然后就可以点击发送交易。这种情况下是替换交易,如果要取消交易,需要将value值修改为0即可。所以取消和替换交易时一回事,只是value=0时你转出的金额为0, 自然就相当于取消了交易。
原理源码分析
func (l *txList) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Transaction) {
// If there's an older better transaction, abort
//txlist是一个address对应的列表,这里的所有交易都是同一个from的
//这里根据nonce检测新的交易是否有对应的老交易,有的话替换
old := l.txs.Get(tx.Nonce())
if old != nil {
//priceBump=10,也就是新交易的gasPrice至少为原来的1.1倍
threshold := new(big.Int).Div(new(big.Int).Mul(old.GasPrice(), big.NewInt(100+int64(priceBump))), big.NewInt(100))
// Have to ensure that the new gas price is higher than the old gas
// price as well as checking the percentage threshold to ensure that
// this is accurate for low (Wei-level) gas price replacements
if old.GasPrice().Cmp(tx.GasPrice()) >= 0 || threshold.Cmp(tx.GasPrice()) > 0 {
return false, nil
}
}
// Otherwise overwrite the old transaction with the current one
l.txs.Put(tx)
if cost := tx.Cost(); l.costcap.Cmp(cost) < 0 {
l.costcap = cost
}
if gas := tx.Gas(); l.gascap < gas {
l.gascap = gas
}
return true, old
}
注意:取消和重新发送交易都是相对专业的操作,请小心操作。本文内容仅做参考,风险自负, 由此引起的任何损失,本文作者不承担任何责任。
/********************************
* 本文来自CSDN博主"爱踢门"
* 转载请标明出处:http://blog.csdn.net/itleaks
******************************************/