浅析 VOTEToken 合约中的漏洞

起因

看到推友发推文，提及某智能合约中的严重漏洞。

流程分析

攻击者批量调用合约的 VOTEToken()函数，实现凭空创建大量 VOTETRUMP代币，然后将 VOTETRUMP代币通过 Uinswap兑换为 ETH，实现套利。

漏洞分析

正巧最近在参与Solidity 殘酷共學 (DeFiHackLabs x WTF Academy)，在课程的第 11 讲：构造函数和修饰器有这样的描述：

注意：构造函数在不同的 Solidity 版本中的语法并不一致，在 Solidity 0.4.22 之前，构造函数不使用 constructor 而是使用与合约名同名的函数作为构造函数而使用，由于这种旧写法容易使开发者在书写时发生疏漏（例如合约名叫 Parents，构造函数名写成 parents），使得构造函数变成普通函数，引发漏洞，所以 0.4.22 版本及之后，采用了全新的 constructor 写法。

而查看合约代码可以看到合约使用的 Solidity版本是 ^0.4.11，是低于 0.4.22。 这意味着该合约的构造函数定义遵循旧版规则。

构造函数错误：合约名称为 VeritaseumToken，而实际定义的构造函数名为 VOTEToken。由于二者不一致，VOTEToken 函数并未被识别为构造函数，而是成为了一个普通的公共函数。此外，函数没有使用任何可见性修饰符，因此任何人都可以随意调用它，并通过调用该函数将其账户的 VOTETRUMP 代币余额增加到代币的最大供应量。

这种设计失误为攻击者创造了条件，他们通过调用 VOTEToken () 函数铸造出大量 VOTETRUMP 代币，并最终在去中心化交易所中套利。

修复漏洞

升级 Solidity 版本：首先，建议将 Solidity 版本升级至 0.4.22 或更高版本，以使用 constructor 关键字定义构造函数。这可以避免由于构造函数名称拼写错误而引发的漏洞。

修正构造函数定义：如果无法升级合约代码版本，必须确保构造函数名称与合约名称一致。在这个案例中，应该将 VOTEToken () 改为 VeritaseumToken ()。

添加适当的权限控制：即使使用旧版构造函数定义，仍需为重要函数添加适当的权限控制（如 onlyOwner 修饰器），避免任何用户可以调用这些函数进行代币铸造。

警示

此漏洞提醒我们，在使用低版本的 Solidity 编写合约时，必须严格遵循构造函数命名规则，避免因为拼写错误引发的严重安全问题。同时，对于任何涉及代币铸造、转移等关键操作的函数，都应引入权限控制机制，以防止恶意用户滥用合约漏洞。

此外，在设计合约时，建议使用最新稳定版本的 Solidity，以确保利用新特性和修复已知漏洞，从而提升合约的安全性。