智能合约安全之Solidity函数默认可见性漏洞

本文探讨了Solidity中函数可见性的重要性,如何导致潜在的安全漏洞,以及如何通过明确函数可见性来避免这些问题。通过实例分析和修复建议,展示了正确设置函数可见性的最佳实践,包括公共与私有的区分,以确保智能合约的安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

漏洞原理

在 Solidity 中,函数有可见性类型,指示函数被允许如何被调用。可见性决定了函数是否可以由用户、其他派生合约、仅在内部或外部调用。函数有四个可见性类型(关于函数的可见性详见另一篇博文 Solidity语言详解——函数和状态变量的可见性及Getter函数)。Solidity 中的函数默认为公共的,即允许用户或合约从外部调用它们。不正确地使用函数可见性可能会导致智能合约中的一些破坏性漏洞。

安全隐患

Solidity 中函数的默认可见性是 public。因此,没有指定任何可见性的函数将被外部用户或合约调用。当开发人员错误地忽略了应该是私有 (或仅在合约内部可调用) 的函数的可见性说明时,问题就出现了。

让我们来看一下这个合约例子:

// SPDX-License-Identifier: MIT
pragma solidity ^0.4.18;

contract HashForEther {
    function withdrawWinnings() {
        // Winner if the last 8 hex characters of the address are 0.
        require(uint32(msg.sender) == 0);
        withdraw();
     }

     function withdraw() {
         msg.sender.transfer(this.balance);
     }
}

这个简单的合约被设计成一个地址猜测赏金游戏。为了赢得合约的余额,用户必须生成一个最后 8 个十六进制字符为 0 的以太坊地址。一旦获得,它们可以调用 withdraw() 函数来获得奖励。

不幸的是,合约中函数的可见性没有被指定。特别是,withdraw() 函数是公共的,因此任何合约都可以调用该函数来窃取奖金。

如何预防

最好总是在合约中指定所有函数的可见性,即使它们是有意公开的。Solidity 的最新版本现在会在编译过程中对没有显式指定可见性的函数显示警告或错误提示,这样就可以预防此类错误的发生。

以下是经修复后的合约代码,通过将 withdraw() 的可见性设置为 private 来限制该函数仅允许在合约内部调用。

// SPDX-License-Identifier: MIT
pragma solidity ^0.4.18;

contract HashForEtherFixed {
    function withdrawWinnings() public {
        // Winner if the last 8 hex characters of the address are 0.
        require(uint32(msg.sender) == 0);
        withdraw();
     }

     function withdraw() private {
         msg.sender.transfer(this.balance);
     }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

StevenX5

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值