智能合约漏洞——不安全的低级调用(Unsafe Low-Level Call)

不安全的低级调用(Unsafe Low-Level Call)

  在solidity中,你可以使用低级调用如:address.call(),address.callcode(),address.delegatecall()和address.send()。或者你可以使用合约调用如:ExternalContract.doSomething()。

   低级调用是有效地或任意地进行合约调用地好方法,但也要注意到它潜在的风险。

1、不检查调用的返回值(Unchecked call return value)

  低级调用永远不会抛出异常,相反,如果遇到异常,将会返回'false',而合约调用将会自动抛出。因此,如果没有检查低级调用的返回值,即使函数调用抛出错误也可以继续执行。这可能导致意外行为并破坏程序的逻辑。调用失败甚至可能是由攻击者故意造成的,攻击者可以进一步利用该程序。

  在低级调用的情况下,一定要检查返回值以处理可能失败的调用。

// Simple transfer of 1 ether
(bool success, ) = to.call{value: 1 ether}("");
// Revert if unsucessful
require(success);

2、成功调用不存在的合约(Successful call to non-existent contract)

  正如solidity文档中所说:由于EVM认为可以对不存在的合约的调用总是成功的,因此solidity语言层面里会使用'extcodesize'操作码来检查要调用的合约是否确实存在(包含代码),如果不存在该合约,则抛出异常。如果返回数据在调用后被解码,则跳过这个检查,因此ABI解码器将捕捉到不存在的合约的情况。

  值得注意的是,这个检查在低级调用时不被执行,这些调用是对地址而不是合约实例进行操作。

  所以不能简单假设通过低级调用调用的合约是存在的,因为如果合约不存在,即使外部调用失败了,逻辑也会继续执行。这可能导致资产的损失或者无效的合约状态。因此,我们必须验证被调用合约是否存在,在被调用之前使用'extcodesize'检查,或者在合约部署期间进行验证和使用常量/不可变值(如果合约可以完全信任)。

// Verify address is a contract
require(to.code.length > 0);
// Simple transfer of 1 ether
(bool success,) = to.call{value: 1 ether}("");
// Revert if unsuccessful
require(success);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值