一、前言

构造函数缺失漏洞自智能合约产生以来就一直出现,归根到底是由于新进开发者对 代码结构不熟悉造成的。BUGX.IO团队本次就来介绍一下漏洞的基本原理、表现形式以及对开发者的建议。

二、漏洞原理1. 什么是构造函数

编写合约和面向对象编程语言非常相似,我们可以通过构造函数()来初始化合约对象。构造函数就是方法名和合约名字相同的函数,创建合约时会调用构造函数对状态变量进行数据初始化操作。

构造函数_构造函数的八种方法_构造函数法

构造函数可用的函数类型为 或 ,如果有 修饰,就只能是 类型。而大部分人的写法都是 或者不写。不写类型则由函数可见性默认为 类型。同时,如果构造函数带参数,则一定要放在合约下的第一个函数。

pragma solidity 0.4.21;contract Foo {  function Foo() public {    // ...  }}

合约结构的规范化写作可以让其他人更好地阅读,并且 和 函数要放在前面以便更好地查看。官方建议以如下顺序写作:

合约结构的规范写法如下:

contract A {
    constructor() public {
        ...
    }
    function() external {
        ...
    }
    // External functions
    // ...
    // External functions that are view
    // ...
    // External functions that are pure
    // ...
    // Public functions
    // ...
    // Internal functions
    // ...
    // Private functions
    // ...
}

2. 构造函数缺失与危害

构造函数缺失则是由于构造函数与合约名字不同,而又为 类型,就变成了一个公有函数了,可以被任何人调用,一般函数函数比较敏感,用于初始化合约时定义通证数量、管理员地址等基本变量状态,一时变成了公有函数,危害可想而知,权限控制、通证管理基本全线奔溃。

3. 版本升级后构造函数的变化

从0.4.22版本开始, 编译器引入了 关键字,以替代低版本的将合约名作为构造函数名的语法,避免程序员容易出现的编码错误。使用旧写法会出现 信息。

新版本写法为:

contract Ownable {
    address public owner;
    address public admin;
    constructor() public {
        owner = msg.sender;
        admin = msg.sender;
    }
    // Other code
}

三、常见漏洞代码形式1. 构造函数使用库合约名称构造函数构造函数,使得构造函数变成了公有函数,可被任意调用。

我们发现了不少这种错误写法的合约,在主合约中,构造函数写成了 Token() 或 () 。这样子的函数非构造函数,变成了普通函数了。

如 合约:

#code

构造函数_构造函数的八种方法_构造函数法

2. 合约名与构造函数名不同,如大小写不同、拼写错误等,使得构造函数变成了公有函数,可被任意人调用。

只能说开发者太大意,对智能合约开发有什么误解吧。经常看到的漏洞形式是合约名与构造函数不同,只与 name 变量名相同,估计是开发者以为合约名相同就行了,却忽略了构造函数

如 合约:

#code

构造函数法_构造函数_构造函数的八种方法

还有这个 合约,乍一看看不出来,仔细瞅瞅,再仔细瞅瞅,原来 coin 拼错了 。

构造函数_构造函数法_构造函数的八种方法

之前知道创宇发布了关于owned大小写编码漏洞的文章。同时,我们也可以找一些类似的容易大小写错误的库合约,如。不过经过我们的分析,还是以 owned 大小写错误为主。

如 MORPH 合约:

#code

contract Owned {
    address public owner;
    function owned() public {
        owner = msg.sender;
    }

3. 前加了 ,或者加了 然后开头的 C写成了大写,即 () {},使得构造函数变成了公有函数,可被任意人调用。

版本升级后的构造函数只需要单独使用 即可,但很多开发者却忽略了此细节。上面这个写法错误在于两点:

1) 加入了 变成了普通函数形式。但是这时编辑器中会报 信息:

构造函数的八种方法_构造函数_构造函数法

但是有开发者忽了此警告,写出了错误代码。

如 MDOT 合约:

#code

    function constructor() public {
        totalSupply = 5000000000000;       // Set the total supply (in base units)
        balances[0xbfC729007CE9CBBE54132Fb9BFa097D80AAC791C] = 5000000000000;    // Initially assign the entire supply to the specified account
    }

2) 但是如果将错写成了,使得编辑器识别其为普通函数名,没有任何 信息。

如 合约:

#code

构造函数的八种方法_构造函数_构造函数法

四、常见漏洞代码形式

使用新版本写法,并且检查句式、拼写的正确性。

五、漏洞影响范围

通过我们对以太坊上的合约进行整体监测,发现有此漏洞的竟达两千多份,大小写编码错误的约有20 份。其中不乏正在使用中的合约。

构造函数_构造函数法_构造函数的八种方法

六、资料

#-

#order-of-

#-and-

七、公司介绍

BUGX.IO是一家致力于区块链领域的安全公司。核心团队组建于2014年,我们在区块链生态安全、行业解决方案、安全建设、红蓝对抗等方面有深厚积累与过硬专业素养。

*本文作者BUGX.IO-,转载请注明来自.COM


限时特惠:
本站持续每日更新海量各大内部创业课程,一年会员仅需要98元,全站资源免费下载
点击查看详情

站长微信:Jiucxh

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注