最近,我偶然读到了一篇题为《程序员关于时区的误解》的文章,让我爆笑不已。这篇文章让我想到了程序员在其它方面的误解,如人名和时间,于是我开始寻找有没有关于以太坊的。奈何寻觅无果,我只得尽自己的绵薄之力。

关于 Gas 的误解

调用 estimateGas 会返回交易所需消耗的 gas 量

调用 estimateGas 确实会返回一个 gas 耗费量,但这是该笔交易在 当前状态 下被打包会花费的 gas 量。而区块链的当前状态可能与你需要该笔交易上链时的状态大相径庭。因此,当你的交易被有效打包进区块时,可能会采用不同的代码路径,需要消耗的 gas 量也有可能完全不同。

如果执行的代码相同,我的交易所需消耗的 gas 量也相同。

不对。即使你使用相同的参数来执行相同的指令,gas 成本也有可能不同。例如,相比已经有非零值的存储位置,如果你要写入新的存储位置,SSTORE(写入存储操作)的成本会高得多(参见 EIP2200)。这就意味着,如果你向一个新地址发送两笔 ERC20 代币转账,第一笔交易的成本会比第二笔高得多,即使二者执行的代码完全相同。

如果状态完全相同,我的交易所需消耗的 gas 量也相同

通常情况下是的,除非你很倒霉地碰上了硬分叉,导致一些操作重新定价。虽然这听起来很复杂,但说白了就是,你无法针对 dApp 中交易的 gas 上限进行安全的硬编码,除非你决心在每次发生硬分叉后都发布 dApp 更新。

如果代码相同,状态也相同,且没有发生硬分叉,我就可以相信 estimateGas的返回值了吗?

这下你可以相信 estimateGas 的返回值就是你的交易所需消耗的 gas 量了,但是你不知道这笔交易是否会如你所愿的那般进行。所谓的 gas 估测,就是节点将使用不同的 gas 值来尝试你的交易,并返回确保你的交易不会失败的最低 gas 值。但是,节点只会看你的交易,不会看交易的内部调用。这就意味着,如果你调用的合约代码有一个 try/catch 块,导致内部调用发生后无法撤销,你获得的 gas 估测值对调用合约来说是够用的,但是对被调用合约来说就不够了。

在多签名钱包中,这种情况经常发生:即使是在交易失败的情况下,大多数多签钱包会将操作标记为已执行,也就是说它们无法撤销最外层的交易(所带来的影响)。因此,一个原生的 gas 估测返回的值可能对多签代码来说是足够的,对你实际想运行的操作来说不一定足够。这就是为什么 Gnosis Safe 有一个专门的 gas 估测方法。

请注意,这也就是为什么因为 gas 不够而导致操作失败的情况很难察觉。内部调用可能会因为被分配到的 gas 太少而将 gas 耗尽,而交易本身可能还有很多 gas 可用。这就意味着,查看交易的 gas 使用量和 gas 上限并非检测 gas 错误的可靠方式。

管他呢,我每次多发送点 gas 就好了

多数情况下,这个方法是管用的。但是请记住,合约是可以查看它在一笔交易中收到的 gas 的。因此,可以轻而易举地将合约编写成,一旦收到过多 gas,交易就会失败。不过我怀疑的是,除了证明这一点外,这么做没有任何意义。

关于交易的误解

只要节点接受了交易,交易就会被挖出

想得美哦。以太坊的网络拥堵会导致 gas 价格波动很大,因此你的交易可能会被逐出 mempool(等待被挖出的交易集合)。如果 gas 价格飙升,你就需要重新发送交易。

我可以略微提高 gas 价格然后重新提交交易

只要你将 gas 价格提高到与你交互的节点所需的最小量(参见 txpool.pricebump ),那就没什么问题,否则还是会被拒绝。

矿工总选择 gas 价格最高的交易

并不一定。矿工可以随心所欲进行选择。他们可能会为了自己的利益而塞入自己的交易,甚至可以开一个协议外通道,为符合自己要求的用户打包交易。

但是,即使他们依据收益来决定打包优先级,如何以最优方式填满区块也是一个背包问题(knapsack problem)。由于交易无法被分割成几部分,所以,在 gas 上限为 10M 的区块中打包两个 5M gas 交易,而不是一个 6M gas 的交易,可能更为有利可图,即使 5M gas 交易的 gas 价格低于 6M gas 交易。

如果我以更高的 gas 价格发送相同的交易,矿工会选择后一个交易来替换前一个交易吗

替换交易必须在旧交易上链之前发送到矿工那里。也就是说,如果你发送了替换交易,你依然需要监控你之前发送的同一个 nonce 下的所有交易的哈希值。

关于 Nonce 的误解

我可以通过 getTransactionCount得到我的下一笔交易的 nonce

这取决于你所使用的区块参数。如果你根据最新区块来查询你的交易记数,就会忽略你的未打包交易,并进一步导致你不小心覆盖你的某笔未打包交易。

我可以通过 getTransactionCount('pending')得到我的下一笔交易的 nonce

虽然这在大多数情况下可行,但是你不能保证你的所有未打包交易都在你所查询的节点的 mempool 中。如果你有很多未打包交易,你所通信的节点可能已经丢弃了其中一些交易,但是这些交易仍有可能存在于其它地方!

关于 Log 的误解

我可以通过持续调用 getLogs 来有效监控事件

尽管这是一个非常管用的方法(没错,说的就是轮询!),但是遇上链重组就会出问题。如果你要轮询最新区块上的新 log,你不会收到关于区块重组的通知,也不知道你所看到的事件是否需要重新调整。

我可以通过安装过滤程序来有效监控事件

直到两周前,这还不是一种常见选择,因为 Infura 不支持基于 http 的过滤程序,MetaMask 默认使用基于 http 的过滤程序,也就是说你的 dApp 有 99% 的用户都使用这种过滤程序(注:我可能有些夸大)。除了新事件之外,过滤程序还会通知你因区块重组而删除的事件。但是,这就要求你正在与之交互的基础设施和节点保持在线。如果它们碰巧丢失了过滤程序的状态,你就有可能错过重组事件。

我可以通过 websocket 订阅来有效监控事件

太好了!这样下来,除了要相信你的节点会保持在线之外,你还要相信你本人会保持在线,你和节点之间的连接是可靠的。我想知道这周你在参加 Zoom 会议时掉线了几次?

现在,我必须承认,我已经对这个话题有点着迷了,以至于我在 Devcon 5 上就此进行了一场闪电演讲。如果你想了解更多内容,EIP234 很好地阐述了这些挑战的基本原理,ethereumjs-blockstream 则解决了这一问题。

关于合约的误解

智能合约是不可更改的

兄弟,如果你还有这种想法,你真的 out 了。我在一篇长达 30 页的文章中阐述过这一点,真的非常长。

不包含任何 DELEGATECALL的智能合约就是不可更改的

实际上,合约可以定期调用( CALL)到一个可变地址中,并将结果作为计算的一部分,或者作为更改状态的指令,从而更改正在运行的代码。

那不包含任何 DELEGATECALL或 CALL的智能合约,总是不可更改的了吧?

还有 STATICCALL。别忘了 STATICCALL!

不包含任何 CALL 的智能合约是不可更改的

你还得排除一种情况:这个智能合约是通过 CREATE2 部署的,会在其初始码(initcode)中动态载入运行时,并且可以自毁。在这种情况下,“所有者” 可以销毁合约,并使用不同的代码在同一个地址上重新创建这个合约。

不包含任何 CALL 且不通过 CREATE2 部署的智能合约是不可更改的

还得排除一种情况:这个合约是通过由 CREATE2 部署的合约部署的。因此,你需要追溯整个部署链条,找到最初创建合约的以太坊外部账户,确保没有任何猫腻,而且不存在自毁操作。这篇文章深入探究了这一问题。

关于 ERC20 代币的误解

我就不展开了,这个话题更适合写成一篇完整的文章。在与代币交互时,使用 OpenZeppelin 的 SafeERC20(你可以在这篇文章中相关内容)就好。请记住,在转账时,接收者所收到的代币并不一定等于发送者被扣除的代币。我们来看下一部分吧。

关于以太币的误解

以太币的总供应量只会增加

我们都知道,有很多以太币是无法使用的,有的是因为外部账户的私钥丢失,有的是因为意外发送到全零地址,还有的是因为被卡在合约中无法处理(对不起,我没忍住)。总而言之,这部分以太币依然存在,但是无法访问。

不过,有一种方法可以销毁以太币。如果你指令一个合约自毁 selfdestruct 并指定其自身作为资金的接收方,这个合约内的所有以太币都将被销毁。这就意味着,只要愿意销毁比区块奖励更多的以太币,就可以让以太币通缩。

我可以写一个能拒绝任何以太币转入的合约

你或许知道,如果你没有声明任何 payable 方法,Solidity 会拒绝所有发送到你的合约的以太币转账,防止资金被卡在合约内。但是,我们也可以在不触发任何代码的情况下,将资金发送到合约内:要么将该合约指定为自毁操作奖励的接收方,要么将其指定为区块奖励的接收方。正如 @gorgos 在评论中指出的那样,可以预先计算出合约部署地址,并在合约部署前将以太币发送到该地址。

也就是说,如果你追踪所有发送到你的合约的以太币转账,你的总余额可能大于你处理的所有转账的总和。

以太坊代币事件监控_以太坊程序员的常见误解相关推荐

  1. 以太坊代币事件监控_以太坊:什么是ERC20标准?

    不以规矩,不能成方圆 许多人应该都听过 代码即法律(Code Is Law),因为程序写完了,无论执行多少次都会得到同样的结果,除非有外界因素的干扰.在多人协作的过程中一定是要按照一个标准来进行分工, ...

  2. mysql事件示例_卓象程序员:Mysql数据库事件使用与示例

    原标题:卓象程序员:Mysql数据库事件使用与示例 事件简介 事件(event)是MySQL在相应的时刻调用的过程式数据库对象.一个事件可调用一次,也可周期性的启动,它由一个特定的线程来管理的,也就是 ...

  3. c# 以太坊代币_C代币

    c# 以太坊代币 Smallest units of programming language are called Tokens. These are building blocks of prog ...

  4. 以太坊代币空投合约的实现

    2019独角兽企业重金招聘Python工程师标准>>> 本文将介绍如何在以太坊智能合约中实现代币的空投.区块链以太坊世界中所谓空投(airdrop),就是免费给你的区块链地址(公钥) ...

  5. android web3j 代币查询_wallet-eth 以太坊代币钱包 助记词 私钥 keystore 转账

    wallet-eth-android wallet-eth 以太坊代币钱包 助记词 私钥 keystore 转账(bip39.bip32.bip44.web3j) 生成钱包地址 // 生成钱包地址 W ...

  6. 以太坊代币标准: ERC20、ERC223的介绍与比较

    代币(Token)是区块链中定义价值的方式,用于标定金融或数字资产.在以太坊上,代币使用相同的标准,这样代币之间的兑换和DAPP支持就会变得容易. 什么是ERC20标准 ERC-20 标准是在2015 ...

  7. coldwallet java eth_wallet-eth 以太坊代币钱包 助记词 私钥 keystore 转账

    wallet-eth-android wallet-eth 以太坊代币钱包 助记词 私钥 keystore 转账(bip39.bip32.bip44.web3j) 生成钱包地址 // 生成钱包地址 W ...

  8. 以太坊代码标准是什么_以太坊:什么是ERC20标准?

    不以规矩,不能成方圆 许多人应该都听过 代码即法律(Code Is Law),因为程序写完了,无论执行多少次都会得到同样的结果,除非有外界因素的干扰.在多人协作的过程中一定是要按照一个标准来进行分工, ...

  9. 以太坊区块链也拥堵_以太坊开发人员:EOS刻意拥堵以太坊网络 推高交易费到1美元...

    金色财经 比特币7月16日讯根据一些DApp开发人员表示,EOS正在攻击以太坊,试图将交易费提高到1美元.据悉,相关开发人员指责EOS通过随机代币"空投"造成以太坊网络堵塞,而且这 ...

最新文章

  1. java自动雨刷系统,安装雨量传感器实现自动大灯/自动雨刷(详细方法)多图!!
  2. 看一眼凌晨四点的哈佛,就会明白中国缺什么
  3. Factory Method模式的误区:Factory Method模式是简化版的Abstract Factory吗?
  4. 软核,硬核、固核的区别!
  5. 安防硬件WIZnet基于全硬件TCP/IP的安防产品应用及方案
  6. 数论三之组合数学Ⅰ-Max-Min Sums,Binomial Coefficient is Fun,Strivore,Bubble Sort,放棋子,LOJ6671,Iroha and a Grid
  7. U86650-群鸡乱舞【矩阵乘法】
  8. JS 取得当前时间日期
  9. 关于老师给的数据集,链接1
  10. 深圳蛇口人民医院办理健康证,免费体检,2017年后国家承担体检费用
  11. Django后端项目----restful framework 认证源码流程
  12. 奔图打印机显示未连接_国货之“彩” |奔图CP2200DW彩色激光打印机首测
  13. 程序运行中(BSS段、数据段、代码段、堆栈)
  14. iOS KVO实现方式
  15. win10休眠_这样设置以后,WIN10比WIN7运行更流畅
  16. 【linux系统学习笔记】linux基本操作
  17. opengl导入obj模型
  18. 线性可分支持向量机与软间隔最大化
  19. CentOS 7使用ttyd搭建一个WEB共享终端(WebSSH)
  20. xmanager5链接linux配置,使用Xmanager连接CentOS 5.5

热门文章

  1. TiDB-新一代数据库入门介绍
  2. Linux 下的 Docker 安装与使用
  3. Java集合系列---Collection源码解析及整体框架结构
  4. ros云服务器_减少运维工作量,如何通过 ROS 轻松实现资源编排新方式
  5. zblog php mip,zblog网站改造百度MIP的教程仅针对zblog轻奢主题
  6. sublime编辑器无法正常打印中文问题解决
  7. 主从复制中忽略库的参数
  8. SSH-struts2的异常处理
  9. 经典案例之MouseJack
  10. 莱洛三角形和定宽曲线