主页 > imtoken如何转账 > 简介 | 以太坊程序员的常见误解

简介 | 以太坊程序员的常见误解

imtoken如何转账 2023-11-24 05:08:49

最近偶然看到一篇文章《程序员对时区的误解》,让我笑出了声。 这篇文章让我想到了程序员的其他误解,比如名字和时间,于是我开始寻找关于以太坊的东西。 可我苦苦寻觅无果,只得使出浑身解数。

对气体的误解

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

调用 estimateGas 确实会返回 gas 成本,但这是在当前状态下打包交易所花费的 gas 量。 而且区块链现在的状态可能和你需要交易上链时的状态有很大的不同。 因此,当你的交易被有效地包含在区块中时,它可能会走不同的代码路径,消耗的 gas 量可能会完全不同。

如果执行相同的代码,我的交易消耗相同数量的气体。

错误的。 即使您使用相同的参数执行相同的命令,gas 成本也可能不同。 例如,如果您正在写入新的存储位置,SSTORE(写入存储操作)将比已经具有非零值的存储位置(请参阅 EIP2200)昂贵得多。 这意味着如果您向一个新地址发送两笔 ERC20 代币转账,第一笔交易的成本将远高于第二笔交易,即使两者执行完全相同的代码。

如果状态完全一样,我的交易就会消耗同样数量的gas

通常是的,除非你有不幸的硬分叉导致某些操作被重新定价。 虽然这听起来很复杂,但底线是你不能安全地硬编码 dApp 中交易的 gas 限制,除非你决心在每次硬分叉后发布 dApp 更新。

如果代码相同,状态相同,没有硬分叉,我能相信estimateGas的返回值吗?

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

以太坊智能合约是什么_以太坊合约代码查看_以太坊合约交易怎么玩

在多重签名钱包中,这种情况经常发生:即使在交易失败的情况下,大多数多重签名钱包也会将操作标记为已执行,这意味着它们无法撤消最外层的交易(带来影响)。 因此,返回一个可能足以用于多重签名代码的值的原始气体估计可能不足以用于您实际想要运行的操作。 这就是为什么 Gnosis Safe 有专门的气体估算方法。

请注意,这就是为什么由于气体不足而导致的操作失败很难被发现的原因。 内部调用可能会因为分配的 gas 太少而耗尽 gas,而交易本身可能仍有大量 gas 可用。 这意味着查看交易的 gas 使用量和 gas 限制并不是检测 gas 错误的可靠方法。

没关系,我只是每次发送更多的气体

在大多数情况下,此方法有效。 但请记住,合约可以查看它在交易中收到的气体。 因此,如果收到过多的气体,合同很容易被编程为失败。 不过,我怀疑除了证明这一点之外,这样做没有任何意义。

关于交易的误解

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

好主意。 以太坊的网络拥堵会导致 gas 价格大幅波动,因此您的交易可能会被逐出 mempool(等待开采的交易集合)。 如果 gas 价格飙升,您需要重新发送交易。

我可以稍微提高 gas 价格并重新提交交易

只要您将 gas 价格提高到与您交互的节点所需的最低值(请参阅 txpool.pricebump),就可以了,否则您仍然会被拒绝。

矿工总是选择 gas price 最高的交易

以太坊合约交易怎么玩_以太坊智能合约是什么_以太坊合约代码查看

不必要。 矿工可以选择任何他们想要的。 他们可能会为了自己的利益插入自己的交易,甚至会开辟一个协议外通道,为符合他们要求的用户打包交易。

然而,即使他们根据收入优先打包,如何最佳地填充块也是一个背包问题。 由于交易不能拆分成多个部分,将两笔 5M 的 gas 交易打包在一个 gas limit 为 10M 的区块中可能比一笔 6M 的 gas 交易更有利可图,即使 5M 的 gas 交易的 gas 价格很低 6M 的交易气体。

如果我以更高的 gas 价格发送同一笔交易,矿工会选择后一笔交易而不是前一笔交易吗?

替换交易必须在旧交易上链之前发送给矿工。 也就是说,如果您发送替换交易,您仍然需要在您之前发送的同一随机数下监控所有交易的哈希值。

对Nonce的误解

我可以通过 getTransactionCount 获取下一笔交易的随机数

这取决于您使用的块参数。 如果你根据最新的区块查询你的交易计数,你将忽略你的解包交易,并进一步导致你不小心覆盖了你的一个解包交易。

我可以通过 getTransactionCount('pending') 获取下一笔交易的随机数

虽然这在大多数情况下都有效,但您不能保证所有未捆绑的交易都在您正在查询的节点的内存池中。 如果你有很多未捆绑的交易,你与之通信的节点可能已经丢弃了其中一些,但这些交易可能仍然存在于其他地方!

对Log的误解

以太坊智能合约是什么_以太坊合约代码查看_以太坊合约交易怎么玩

我可以通过不断调用 getLogs 来有效地监控事件

虽然这是一种非常有用的方法(是的,轮询!),但它可能会在链重组的情况下导致问题。 如果您要轮询最新块上的新日志,您将不会收到有关块重组的通知,也不知道您看到的事件是否需要重新调整。

我可以通过安装过滤器来有效地监控事件

直到两周前,这不是一个常见的选项,因为 Infura 不支持基于 http 的过滤器,MetaMask 默认使用基于 http 的过滤器,这意味着你的 dApp 的 99% 的用户都在使用它们(注意:我可能有点夸张) . 除了新事件外,过滤器还会通知您因块重组而删除的事件。 但是,这需要您与之交互的基础设施和节点保持在线。 如果它们碰巧丢失过滤器状态,您将面临丢失重组事件的风险。

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

伟大的! 这样以太坊合约代码查看,除了要相信你的节点会一直在线,你还要相信你会一直在线,你和节点之间的连接是可靠的。 我想知道在这周的 Zoom 会议中,您掉线了多少次?

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

对合同的误解

智能合约是不可变的

兄弟,你要是还有这种想法,那你就真的out了。 我在一篇 30 页的文章中写了这个,真的很长。

以太坊合约交易怎么玩_以太坊智能合约是什么_以太坊合约代码查看

不包含任何 DELEGATECALL 的智能合约是不可变的

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

不包含任何 DELEGATECALL 或 CALL 的智能合约总是不可变的,对吧?

和静态呼叫。 不要忘记静态呼叫!

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

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

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

必须排除另一种情况:该合约由 CREATE2 部署的合约部署。 因此,需要对整个部署链进行追溯,找到最初创建合约的以太坊外部账户,确保没有猫腻,没有自毁操作。 本文深入探讨这个问题。

关于 ERC20 代币的误解

我就不展开了,这个话题更适合写一篇完整的文章。 与令牌交互时,使用 OpenZeppelin 的 SafeERC20(您可以在这篇文章中阅读更多相关信息)。 请记住,在转移资金时,接收方收到的代币不一定等于从发送方扣除的代币。 让我们继续下一部分。

以太坊合约代码查看_以太坊合约交易怎么玩_以太坊智能合约是什么

对以太坊的误解

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

我们都知道有很多以太币不能花掉,有的是因为外部账户的私钥丢失,有的是不小心发送到全零地址,有的是卡在合约里面无法处理(对不起,我忍不住了)。 总而言之,这部分以太币仍然存在,只是无法访问。

但是,有一种方法可以燃烧乙醚。 如果您指示合约自毁并将其指定为资金接收者,则合约中的所有以太币都将被销毁。 这意味着只要你愿意燃烧比区块奖励更多的以太币,就可以让以太币通缩。

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

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

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

(结束)

(本文链接较多,可点击左下方“阅读原文”从EthFans网站获取)

原文链接: