本文深入探讨了Solidity中的可见性修饰符(public, external, internal, private),分析了它们的基础知识、优化技巧(external函数比public函数更节省gas)以及安全注意事项(private并非真正私有)。同时,文章强调了访问控制和输入验证的重要性,并提供了关于函数布局和接口可见性的实用建议。
在使用 Solidity 语言学习智能合约开发时,至关重要的部分之一是掌握可见性说明符。
Solidity 中的可见性说明符为开发者提供了额外的能力来控制智能合约中函数或状态变量的可访问性(或可见性)。
它们主要有 4 种不同的类型 -> external、public、internal 和 private。
好的!现在我们将快速回顾基础知识,以便更好地理解本文接下来要介绍的部分。
然而,如果你已经了解了基础知识,请随时移至优化部分。
2. External
关于 public & external 函数的 gas 消耗差异的一个非常有趣的事实在本文的优化**部分中进行了解释。
3. Internal
4. Private
❓快速提问❓
如果 private 可见性 限制了任何第三方合约或用户对状态变量的访问,这是否意味着我们可以将秘密信息存储在智能合约的 private 状态变量中?
🤔 思考一下,我们将在 安全部分 回答它。
虽然具有 external 和 public 可见性的函数行为几乎相似,但两者之间存在一些重要的 gas 优化差异,必须牢记。
例如,快速浏览下面的图片。👇
External 和 Public 可见性函数之间的 Gas 消耗的明显差异
你是否注意到 public 函数比 external 函数消耗更多的 gas?
在 public 函数的情况下,函数的参数被复制到 𝐌𝐄𝐌𝐎𝐑𝐘 中。而另一方面,具有 external 可见性的函数可以直接从 𝐂𝐀𝐋𝐋𝐃𝐀𝐓𝐀 中读取参数。
现在,由于 CALLDATA 比 MEMORY 便宜,因此 external 函数产生的执行成本比 public 函数低。
好吧,这可能会导致另一个问题:
为什么 public 函数将参数复制到 memory 中,而 external 函数不复制?
正如先前讨论的,public 函数可以从合约的外部和内部调用,即内部调用。
内部调用通过操作码 JUMP 执行,因为数组参数在内部通过指向内存的指针传递。
因此,当编译器为内部函数生成操作码时,该函数期望其参数位于内存本身中。
但是,这根本不是 external 函数的情况。它们根本不关心内部调用,因此最终节省了一些 gas。
还记得 基础知识 部分中的快速问题吗?
是时候回答了。⏰
智能合约开发者,尤其是初学者,通常会误以为 private 可见性说明符实际上使状态变量不可读或完全无法访问。
好吧,事实并非如此。💡
具有 private 关键字的状态变量仍然可以在链上读取。
此外,即使你的合约未经过验证,任何第三方参与者都可以查看其交易,以找出存储在合约状态中的值。
你问,具体是怎么做到的? 🤔
查看这个快速精彩视频,它清楚地解释了如何完成它的底层细节。
因此,如果任何未加密的重要数据存储在链上,即使具有 private 可见性,也会成为安全问题。
敏感或关键数据应完全存储在链下,或在链上进行充分加密。
2. 默认可见性可能非常危险 🔴
还在使用低于 0.5 的 solidity 版本?
那么你可能需要小心默认可见性。
在低于 0.5.0 的 solidity 版本中,没有任何显式可见性关键字分配的函数默认被认为是 public。
如果对关键状态进行修改的函数由于错误而根本没有分配任何可见性关键字,这可能会导致潜在的利用场景。
由于默认可见性 public 将分配给这个重要函数,因此任何恶意参与者都可以通过触发该函数来进行意外的状态修改。
此安全问题清楚地说明了 solidity 中可见性类型的重要性,以及为什么应该非常仔细地为特定函数选择它们。
3. 对于可供世界访问的函数,访问控制无疑非常重要 ⚠️
考虑到前面的提示,重要的是要注意,任何具有 external/public 可见性的函数基本上对任何用户都是可见、可读和可访问的。
一个关于 访问控制不足 或 缺乏输入验证 的 200 万美元黑客攻击 的快速示例,发生在 external 或 public 函数 中 (200 万美元黑客攻击) 。🥷
由于访问控制不足导致的 TempleDao 黑客攻击
因此,在开发或审计此类函数时,必须牢记 2 个重要点。
谁可以调用这些函数?
在此处 阅读有关不同类型的访问控制机制的更多信息。
如何调用这些函数?
- 原文链接: decipherclub.com/deciphe...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!