除不断,理还乱的合约运算 - 漏洞分析之浮点和精度处理不当

当前位置:首页 > 币圈百科 > 除不断,理还乱的合约运算 - 漏洞分析之浮点和精度处理不当

除不断,理还乱的合约运算 - 漏洞分析之浮点和精度处理不当

2023-01-06币圈百科253

针对区块链的安全问题,成都链安全技术团队每周都会对智能合约的安全漏洞进行分析和连载,希望帮助程序员写出更安全、更牢固的合约,防患于未然。

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

前情提要

上一次说继承的变量名字和真实的不一样,构造函数名字也不一样(成都链安全漏洞分析连载第11期:关注契约中“你的名字”——继承变量覆盖和构造函数不匹配)

在编写智能合约的过程中,采用正确的构造函数声明,保持合约名称与构造函数名称一致,是保证构造函数特殊性和唯一性的前提,也是构建合约安全基础的重中之重。构造函数中的所有者权限不能太强大,否则会落入坏人之手。继承的父类函数变量和新声明的子类函数变量之间有细微的差别。在同名的情况下,会是父类变量调用父类函数操作。只有甄别和理解这些细节,才能防止开发中的失误,同时防止蜜罐通过类似手段套取资金。名称的正确规范使用也体现了开发商对项目和安全的尊重。

本期话题

除法运算也放弃,浮点精度无小事。

经过第十一期的讲解和学习,我们逐渐从常见的严重漏洞延伸到合同开发的细节和不易察觉的安全隐患,旨在倡导更加细致的安全开发流程和注重安全防范的“工匠精神”。在序列化的开始,我们提到了臭名昭著的整数溢出漏洞,并强调使用SafeMath库来检查溢出,以防止严重的后果。请往深处走:溢出漏洞类型综合分析。

然而,在合约的数学运算中,不仅存在溢出问题,还有除法运算和浮点运算,这些都与精度密切相关。说到浮点和精度,这是计算机最基本也是最有争议的话题。听说即使是最简单的计算器,精度也比超级计算器高。举个很实际的例子,你可以用主流的编程语言计算0.2 0.4。对于测试,可以使用Chrome或FireFox浏览器,按F12进入控制台,然后输入计算结果。结果竟然是:

图片1。然后,用最简单的计算器、手持计算器或者系统自带的计算器算出结果。肯定是0.6。所以我们可以说,计算精度的关键不在于它的频率和内存,而在于它是如何设计、表示和计算的。

在实性上,浮点和精度也有类似的争议。本期我们将讨论浮点计算带来的精度漏洞。

基础知识

对于Solidity,我们需要了解以下两个方面

浮点型,定长浮点型

Solidity目前不支持浮点型,也不完全支持定长浮点型。

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

fixed/ufixed:表示有符号和无符号的固定位浮点数。关键字是ufixedMxN和ufixedMxN。

M表示该类型占用的位数,可以是8到256位,步长为8。

N表示小数点的个数,可以是0到80。

除法运算

除法运算的结果会是四加五,只取整数部分。例如,下面的操作显示了直接将5除以2的表示方法与用分数表示5除以2的结果的表示方法的比较。

图片二这说明所有的除法结果,如果有小数,小数点后的部分将被丢弃,只取整数部分。

所以,官方的建议是,如果需要更高的精度,请考虑使用乘数或者存储分子分母。

?数学 由于代币的经济性,准确性的损失相当于资产的损失,所以这就会带来频繁交易的代币积少成多的问题。这让我想起了那个全国人都给我一毛钱让我发财的笑话。

图片3案例漏洞分析

上面我们说了,Solidity的最新版本是0.4.25,仍然不支持浮点型或者定长浮点型。浮点数一般在Solidity中用蓑衣网小编2022整数表示,比如ERC20中的Token。如果使用不正确的转换,可能会出现错误甚至漏洞。

由于Solidity中没有浮点类型,开发者需要使用标准的整数数据类型来实现自己的类型。在这个过程中,开发人员可能会遇到一些陷阱。

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

这种简单的代币买卖合同在代币买卖中存在一些明显的问题。虽然买卖代币的数学计算是正确的,但是缺少浮点数会给出错误的结果。比如在计算可以得到多少个token时使用uintTokens=msg.value/weiPerEth*tokensPerEth;如果发送的Ether数小于1

图片4Ether,那么最初的除法会导致结果为0,那么最后的乘法结果也会是0(例如:200个Wei除以1e18weiPerEth等于0)。

同样,出售代币时,数量不足10个代币,将获得0乙醚。实际上,这里的舍入总是大约等于最接近的整数,所以,例如,如果你出售29个代币,你将只得到2个以太。

这个合约的问题是精度只能达到最近的以太(即1e18卫)。当面对更高的精度时,比如使用小数来扩展精度的ERC20令牌,事情就会变得非常棘手。

漏洞修复

保持智能合约的准确性非常重要,尤其是在处理反映经济决策的比例或比率时。

解:

1。大分子

所以我们要保证所用的任何比例或配比在分数中都有大分子。例如,我们tokensPerEth在示例中蓑衣网小编2022使用了rate。使用威珀托肯斯会是一个很大的数字,效果自然会更好。这可以解决我们使用msg.sender/weiPerTokens来计算令牌数的问题。同时给出了更精确的结果。

2。操作顺序

另一个需要记住的策略是注意操作的顺序。在上面的例子中,购买代币的计算是msg.value/weiPerEth*tokenPerEth.注意,这里的除法发生在乘法之前。如果计算先相乘,再相除,那么这个例子会达到更高的精度,比如修改为msg . value * token pereth/weipereth。

3。精度转换

最后,在为数字定义任意精度时,最好将变量转换为更高的精度,执行所有数学运算,然后在需要时最终转换回输出精度。通常uint256使用它们(因为它们最适合气体使用),它们的范围大约是60个数量级。其中一些可以用来提高数学运算的精度。可能是这样的情况,最好先保持所有变量高精度稳定,然后在外部应用中切换回较低精度(这其实是ERC20令牌合约中小数变量的工作原理)。有关如何实现这一点的示例以及实现这一点的库,请查看Maker DAO DSMath。精度无小事,细节决定成败

从以上修复bug的方法中,我们可以看到,三个度量对应的是精度设计、精度计算、精度表达三个方面。从这个角度来看,智能合约操作中的精度问题,其实是计算机精度问题的延伸。然而,由于当前区块链行业的经济属性,准确性无疑已成为安全性的重要考虑因素。在准确性上多下功夫是有益无害的。根据官方消息,Solidity或其他开发语言将在未来进一步改进和增强浮点和精度问题。说明官方也在努力不断提高这个行业的安全性和准确性。 我们在关注和投身这个产业的过程中,做好细节的完善,也是为其添砖加瓦的一种最好体现。x

图片5引用:

[1]:Solidity Security:https://博客。西格玛质数。io/可靠性-安全性。html

[2]:以太eum安全:https://github。com/乙醚eum/wiki/wiki/Safety #当心-整数除法舍入

[3]:代码之谜(五)- 浮点数:http://just javac。iteye。com/blog/1724438

[4]:坚固性学习(3):https://博客。csdn。net/sunny 27/article/details/78806685

[5]:以太坊智能合约—— 最佳安全开发指南:https://博客。csdn。net/老二汗/article/details/81078760

访问作者专栏,查阅更多本系列文章:https://www。8 BTC。com/author/55359

除不断,理还乱的合约运算 - 漏洞分析之浮点和精度处理不当 | 分享给朋友: