本文探讨了Solidity编程语言的学习难度,尽管语言本身与JavaScript等类似,快速上手可能性高,但深入理解以太坊环境及一些独特特性如gas成本、I/O操作以及重入攻击等,则需要时间和经验。文章通过代码示例展示了常见的陷阱和挑战,强调了在掌握Solidity语言之后,还需大量实践才能精通以太坊生态系统。
学习 solidity 作为一种语言,可以说是比较容易学习的语言之一。然而,学习以 Ethereum 为环境的开发是困难的。
它看起来与 javascript 非常相似,或者说与任何源自 C 的花括号语言都很相像。
if 语句、for 循环、类继承、变量类型等都很熟悉。
Solidity 具有一些独特的怪异,特别是在移动加密货币时。例如,每个函数调用都有一个环境变量,指示与函数调用一起发送了多少 ether,并且有一些特定的 API 用于与其他智能合约进行交互。Solidity 还具有像 delegatecall 和 selfdestruct 等在其他语言中找不到的奇怪指令,但那些在稍微研读文档后就容易理解。
然而,Solidity 和 Ethereum 开发可能充满惊喜。以下是三个示例。
这个合约的功能非常简单。它将代币从另一个合约转移到自己的合约,然后在同一事务中将其转移给调用者。
但是,openFaucetInefficient 和 openFaucetMoreEfficient 的 gas 成本可能会有天壤之别。为什么?在底层,ERC20 代币将用户的余额存储为存储变量。当一个存储变量从零变为非零时,会导致该变量在区块链上创建。而创建步骤是相对昂贵的。当变量被设置为零时,它会被隐式地擦除。所以第一个函数反复创建和擦除一个存储变量。
第二个函数则高效得多。它为自己的余额创建了存储变量,然后确保在最终转移最后一个代币之前不会被销毁。这防止了不必要的存储变量的创建。
第三个函数具有一种奇特的 for 循环结构,效率更高。由于 Solidity 编译器中的一些奇特之处,以这种方式重新排列 for 循环会更高效,即使你告诉编译器在代码上运行自动效率改进。
你怎么知道这一点?好吧,没有直接的方法知道。这就是为什么 Solidity 不容易掌握。
x 和 y 都是存储变量,你可以把它们想象成存储在持久磁盘上的。它们在交易之间保持其值。
当被询问时,许多开发者假设如果 x 小于或等于 10,x 将被设置为 newValue 并将 y 设置为 2 倍的 x。例如,如果 newValue 为 5,x 将为 5 而 y 将为 10。如果 newValue 为 20,x 将为 20,而 newValue 不会改变。
但这并不是发生的事情。如果交易中的任何地方发生撤回,写入 x 的操作会被撤销。
这对于开发者来说是非常违反直觉的,因为大多数 I/O 操作不会撤回。然而,Ethereum 上的所有交易都是原子的。因此,x 永远不能大于 10,x 和 y 必须同时改变。
上面的代码似乎在用户调用 mintTokens 时发送一个 ERC20 代币和一个 ERC1155 代币。表面上,每个地址只能铸造一次,因为有 alreadyClaimed 的检查。
然而,有可能在一个事务中耗尽合约中的所有代币。ERC1155 中的 _mint 函数不仅简单地铸造一个代币,同时也将在更新发送者已声明其代币之前将控制权交给事务的发送者。这使得发送者可以通过在 _mint 将控制权归还给他们时递归调用 mintTokens 来主张所有代币。
是否有理由知道哪些函数会将控制权交给其他合约。人们只需记住它们。
如上所示,表面上看似简单的语言却充满了惊喜。我们这里只触及了表面。你知道“不可变”智能合约能够更改其字节码吗?还有关于糟糕代码设计的问题,这使得买家在没有重入攻击的情况下可以双重消费他们的 ether?在区块链完全确定且透明的情况下,你能安全地生成随机数吗?
尽管使用了一种“容易”学习的编程语言,区块链依然充满未知的未知。这就是为什么黑客攻击如此普遍的原因。
Solidity 可以在一个周末内掌握。如果你已经知道另一种编程语言,这里有我们的免费教程,帮助你快速 学习 Solidity。
但掌握完整的生态系统并不会在几天内完成。
你想掌握这个生态系统吗?立即申请我们的全远程 Solidity 启蒙营。
原文发表于 2022 年 11 月 8 日
- 原文链接: rareskills.io/post/solid...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!