以太坊计算能力,以太坊计算002588史丹利器2019

针对区块链安全问题,成都安联技能团队每周都会对智能合约的安全缝隙进行剖析和连载,期望协助程序员写出更安全、更结实的合约,防患于未然。

导语:“以言治骨角者,既斩之,又议之;治玉者,既有打磨,又有重磨,有精,但求其精。”宋珠熙

前情概要

前次承继的变量名和实在的不一样,结构函数名失去了含义。

在编写智能契约的过程中,选用正确的结构函数声明,坚持契约名与结构函数名共同,是保证结构函数特殊性和唯一性的条件,也是构建契约安全根底的重中之重。结构函数中的一切者权限既不能太强,也不能落入别人之手。承继的父函数变量和新声明的子类函数变量之间有纤细的不同。当称号相一起,将调用父类的变量进行操作。只要剖析和了解这些细节,才干避免开发中的失误,一起避免蜜罐以相似方法套取资金。规范的正确称号也表现了开发者对项目和安全性的尊重。

本期论题

除四除五也抛弃,浮点精度数无小事。

通过第十一期的解说和学习,咱们逐步从常见的严峻缝隙延伸到合同开发的细节和不易发觉的安全隐患,旨在倡议更具体的安全开发流程和专心于安全防备的“工匠精力”。在序列化的开端,咱们提到了臭名远扬的整数溢出缝隙,并着重运用SafeMath库来检查溢出,以避免严峻的成果。请往深处走:溢出缝隙类型归纳剖析。

可是,在合约的数学运算中,不只存在溢出问题,还存在与精度密切相关的除法运算和浮点运算。提到浮点和精度,这是核算机最基本也是最有争议的论题。传闻即使是最简略的核算器,精度也比超级核算器高。举个很实践的比方,你用干流编程言语算0.2 0.4。测验的话,能够运用Chrome和FireFox浏览器,按F12进入控制台,然后输入核算成果。成果变成了:

然后用最简略的核算器,手持核算器或许体系自带的核算器算出成果。肯定是0.6,比照一下就清楚了。所以咱们能够说,核算精度的要害不在于它的频率和内存,而在于它是怎么规划、表明和核算的。

在巩固性上,浮点和精度也有相似的争议。本期咱们将评论浮点核算带来的精度缝隙。

根底知识

关于厚实,咱们需求知道以下两个方面。

1.浮点型,固定长度浮点型

Solidity现在不支撑浮点,也不完全支撑定长浮点。

定长浮点型能够用来在Solidity中声明变量,但不能用来赋值。

Fixed/ufixed:表明有符号和无符号的固定位浮点数。要害字是ufixedMxN和ufixedMxN。

m表明该类型占用的位数,能够是8到256位,步长为8。

n代表小数点的个数,能够是0到80。

2.除法运算

除法的成果会是四比五,只取整数部分。例如,下面的运算显现了直接将5除以2和用分数表明5除以2之间的比较。

这显现一切除法的成果。假如有小数点,小数点后的部分将被丢掉,只取整数部分。

所以,官方的主张是,假如你需求更高的精度,请考虑运用乘法器,或许存储分子和分母。

数学核算无误,运算成果误差

幻想一下,假如令牌运算的成果小于1Ether,那么0。XXX大约等于0。相似地,4.9个令牌将大约等于4,导致必定程度的准确度丢失。因为代币的经济特点,精准度的丢失相当于财物的丢失,所以在频频生意时会带来集腋成裘的问题。这让我想起了每个人都在讲的笑话

如上所述,Solidity的最新版本是0.4.25,依然不支撑浮点型或定长浮点型。一般浮点数在Solidity顶用整数类型表明,比方ERC20中的Token。假如运用不正确的转化,可能会呈现过错乃至缝隙。

因为Solidity中没有浮点类型,开发者需求运用规范的整数数据类型来完结自己的类型。在这个过程中,开发者可能会遇到一些圈套。

让咱们从一个代码示例开端(为了简略起见,疏忽任何上溢/下溢问题)。

这份简略的代币生意合同,在代币生意上有一些显着的问题。尽管生意代币的数学核算是正确的,可是短少浮点数会给出过错的成果。例如,当运用uint toke时

ns= msg.value/weiPerEth*tokensPerEth; 核算能够取得多少token时,假如发送的Ether数量小于1

Ether,开始的除法将导致成果为0,进而使最终的乘法成果也是0(eg:200 wei除以1e18weiPerEth等于0)。

同理,当出售代币时,数量少于10代币的状况下将会收到0 ether。事实上,这儿四舍五入总是向下约等于最近的整数,所以比方出售29 tokens,将只能收成2 Ether。

这个合约的问题是精度只能到最近的Ether(即1e18 wei)。当面对更高的精度时,例如运用decimals扩展精度的ERC20代币,作业会变得很扎手。

缝隙修正

坚持智能合约的正确准确度非常重要,尤其是在处理反映经济决议计划的份额或许比率时。

处理方案:

1. 大分子

所以咱们应该保证运用的任何份额或比率都在分数中具有大分子。例如,咱们tokensPerEth在示例中运用了费率。运用weiPerTokens这将是一个很大的数字,作用自然会更好。这样能够处理咱们用msg.sender/weiPerTokens核算的代币数量问题。一起给出更准确的成果。

2. 运算次序

要记住的另一个战略是留意操作的次序。在上面的比方中,购买代币的核算是msg.value/weiPerEth*tokenPerEth。请留意,这儿的除法发生在乘法之前。假如核算首要进行乘法,然后再进行除法,那么这个比方会到达更高的精度,例如修改为msg.value*tokenPerEth/weiPerEth。

3. 精度转化

最终,当为数字界说恣意精度时,将变量转化为更高精度,履行一切数学运算,然后最终在需求时将其转化回输出精度不失为一个好主意。一般uint256运用它们(因为它们关于gas运用来说是最佳的),它们的规模约为60个数量级,其间一些可用于提高数学运算的准确度。

可能会呈现这样的状况:最好先将一切变量高精度地坚持稳定,然后在外部应用程序中转化回较低的精度(这实践上是ERC20代币合约中decimals变量的作业原理)。要了解怎么完结此操作的示例以及要履行此操作的库,可检查Maker DAO DSMath。

精度无小事,细节定胜败

从上面的缝隙修正方法咱们能够看出,三个办法正好对应了精度的规划,精度的运算,精度的表明三个方面。从这个视点来看,智能合约运算中的精度问题其实刨根究底也是核算机精度问题的延伸。可是因为区块链工业现在的经济特点,精度无疑成为安全的一个重要考量,在精度的问题上多下功夫,有益无害。依据官方的音讯,Solidity或许其他开发言语在今后也会在浮点和精度的问题上做进一步的完善和提高。阐明官方也在尽力为这个工业安全性准确性的进行不断完善。咱们在重视和投身这个工业的过程中,做好细节的完善,也是为其添砖加瓦的一种最好表现。

引证:

<1>: Solidity Security: blog.sigmaprime.io/solidity-security.html

<2>: Ethereum Safety: github/ethereum/wiki/wiki/Safety#beware-rounding-with-integer-pision

<3>: 代码之谜(五)- 浮点数:justjavac.iteye/blog/1724438

<4>: Solidity学习 (3):blog.csdn.net/sunniy27/article/details/78806685

<5>: 以太坊智能合约 ―― 最佳安全开发攻略:blog.csdn.net/laoerhan/article/details/81078760

(作者:成都链安科技,内容来自链得得内容敞开渠道“得得号”;本文仅代表作者观念,不代表链得得官方态度)

发布于 2023-12-24 20:12:37
收藏
分享
海报
3
目录

    推荐阅读