一文澄清以太坊开发者常见误解: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)到一个可变地址中 , 并将结果作为计算的一部分 , 或者作为更改状态的指令 , 从而更改正在运行的代码 。
那不包含任何 DELEGATECALLCALL 的智能合约 , 总是不可更改的了吧?
还有 STATICCALL 。 别忘了STATICCALL
不包含任何 CALL 的智能合约是不可更改的
你还得排除一种情况:这个智能合约是通过 CREATE2 部署的 , 会在其初始码(initcode)中动态载入运行时 , 并且可以自毁 。 在这种情况下 , “所有者” 可以销毁合约 , 并使用不同的代码在同一个地址上重新创建这个合约 。
不包含任何 CALL 且不通过 CREATE2 部署的智能合约是不可更改的
还得排除一种情况:这个合约是通过由 CREATE2 部署的合约部署的 。 因此 , 你需要追溯整个部署链条 , 找到最初创建合约的以太坊外部账户 , 确保没有任何猫腻 , 而且不存在自毁操作 。 这篇文章深入探究了这一问题 。
关于 ERC20 代币的误解我就不展开了 , 这个话题更适合写成一篇完整的文章 。 在与代币交互时 , 使用 OpenZeppelin 的 SafeERC20 (你可以在这篇文章中阅读更多相关内容)就好 。 请记住 , 在转账时 , 接收者所收到的代币并不一定等于发送者被扣除的代币 。 我们来看下一部分吧 。
关于以太币的误解以太币的总供应量只会增加
我们都知道 , 有很多以太币是无法使用的 , 有的是因为外部账户的私钥丢失 , 有的是因为意外发送到全零地址 , 还有的是因为被卡在合约中无法处理(对不起 , 我没忍住) 。 总而言之 , 这部分以太币依然存在 , 但是无法访问 。
不过 , 有一种方法可以销毁以太币 。 如果你指令一个合约自毁 selfdestruct并指定其自身作为资金的接收方 , 这个合约内的所有以太币都将被销毁 。 这就意味着 , 只要愿意销毁比区块奖励更多的以太币 , 就可以让以太币通缩 。