addr.send() 进行以太币转账是一个很好的例子,这对于其他外部调用也有效。
if(!addr.send(1)) { revert() } 2. 高成本循环 高成本循环从 Solidity 安全榜单的第四名上升至第二名。受该问题影响的智能合约数量增长了近 30%。 大家都知道,以太坊上的运算是需要付费的。因此,减少完成操作所需的计算,不仅仅是优化问题(效率),还涉及到成本费用。 循环是一个昂贵的操作,这里有一个很好的例子:数组中包含的元素越多,就需要更多迭代才能完成循环。最终,无限循环会耗尽所有可用 GAS。 for(uint256 i=0; i< elements.length; i++) { // do something } 如果攻击者能够影响元素数组的长度,则上述代码将导致拒绝服务 (执行无法跳出循环)。而在扫描的智能合约中发现有 8%的合约存在数组长度操纵问题。 3. 权力过大的所有者 这是 Soldiity 十大安全问题新出现的问题,该问题影响了约 16%的合约,某些合约与其所有者(Owner)紧密相关,某些函数只能由所有者地址调用, 如下例所示: 只有合约所有者能够调用 doSomething() 和 doSomethingElse() 函数:前者使用 onlyOwner 修饰器, 而后者则显式执行该修饰器。这带来了严重的风险:如果所有者的私钥遭到泄露, 则攻击者可以控制该合约。 4. 算术精度问题 由于使用 256 位虚拟机(EVM[7]),Solidity 的数据类型有些复杂。Solidity 不提供浮点运算, 并且少于 32 个字节的数据类型将被打包到同一个 32 字节的槽位中。考虑到这一点,你应该预见以下程序精度问题: function calculateBonus(uint amount) returns (uint) { return amount/DELIMITER*BONUS; } 如上例所示,在乘法之前执行的除法,可能会有巨大的舍入误差。 5. 依赖 tx.origin 智能合约不应依赖于 tx.origin 进行身份验证,因为恶意合约可能会进行中间人攻击,耗尽所有资金。建议改用 msg.sender: function transferTo(address dest, uint amount) { require(tx.origin == owner) { dest.transfer(amount); } } 可以在 Solidity 的文档中找到 Tx Origin 攻击的详细说明 [8] 。简单的说,tx.origin 始终是合约调用链中的最初的发起者帐户,而 msg.sender 则表示直接调用者。如果链中的最后一个 合约依赖于 (责任编辑:admin1) |