前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >智能合约审计之变量歧义命名

智能合约审计之变量歧义命名

原创
作者头像
Al1ex
修改2021-07-16 14:48:16
3930
修改2021-07-16 14:48:16
举报
文章被收录于专栏:网络安全攻防

文章前言

Solidity允许在继承时对状态变量进行歧义命名,定义有变量x的合约A可以继承同样含有状态变量x的合约B,这将导致两个单独版本的x,一个可以从合约A访问, 而另一个则需要从合约B访问,在更复杂的合约系统中,这种情况可能不会引起注意, 并随后导致严重的安全问题。

漏洞示例

下面进行一个简单的测试,首先我们来看局部变量与全局变量之间的关系:

代码语言:javascript
复制
pragma solidity 0.4.24;

contract ShadowingInFunctions {
    uint n = 2;
    uint x = 3;

    function test1() constant returns (uint n) {
        return n; // Will return 0
    }

    function test2() constant returns (uint n) {
        n = 1;
        return n; // Will return 1
    }

    function test3() constant returns (uint x) {
        uint n = 4;
        return n+x; // Will return 4
    }
}

首先部署合约:

调用test1函数来测试当同名的全局变量与局部变量同时存在且局部变量未初始化时局部变量作何回应——0:

调用test2函数来测试当同名的全局变量与局部变量同时存在且局部变量初始化时局部变量作何回应—局部变量:

调用test3函数来测试当同名的全局变量与局部变量同时存在且局部变量已初始化并与另一个全局变量进行数值运算时作何回应——当前局部变量与所需的全局变量进行数值运算:

下面我们再来看一个示例,合约TokenSale.s 下面我们再来 ol代码如下:

代码语言:javascript
复制
pragma solidity 0.4.24;

contract Tokensale {
    uint hardcap = 10000 ether;

    function Tokensale() {}

    function fetchCap() public constant returns(uint) {
        return hardcap;
    }
}

contract Presale is Tokensale {
    uint hardcap = 1000 ether;

    function Presale() Tokensale() {}
}

部署以上两个合约:

之后调用Tokensale合约的fetchCap函数来查看hardcap的数值—10000000000000000000000=10000ether:

之后调用继承自TokenSale合约的Presale合约中 fetchCap函数来查看继承合约中的hardcap的数值是多少:

10000000000000000000000=10000ether:

由此可见Presale合约中的同名变量hardcap并未起到预期的作用,在调用fetchCap时使用的变量hardcap依旧源自fetchCap函数所处的合约上下文环境

防御措施

检查合约系统的存储变量布局,并消除歧义,下面是修改上面示例二中修改后的合约代码:

TokenSale_fixed.sol

代码语言:javascript
复制
pragma solidity 0.4.25;

//We fix the problem by eliminating the declaration which overrides the prefered hardcap.

contract Tokensale {
    uint public hardcap = 10000 ether;

    function Tokensale() {}

    function fetchCap() public constant returns(uint) {
        return hardcap;
    }
}

contract Presale is Tokensale {
    //uint hardcap = 1000 ether;
    //If the hardcap variables were both needed we would have to rename one to fix this.
    function Presale() Tokensale() {
        hardcap = 1000 ether; //We set the hardcap from the constructor for the Tokensale to be 1000 instead of 10000
    }
}

首先部署上述两个合约:

之后调用fetchCap进行测试,效果如下所示:

文末小结

在复杂性合约逻辑设计过程中,对于变量名称的定义建议具备"专名专用"的特性,同时对全局变量与局部变量进行合理使用,同时需要注意变量的初始化。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章前言
  • 漏洞示例
  • 防御措施
  • 文末小结
相关产品与服务
区块链
云链聚未来,协同无边界。腾讯云区块链作为中国领先的区块链服务平台和技术提供商,致力于构建技术、数据、价值、产业互联互通的区块链基础设施,引领区块链底层技术及行业应用创新,助力传统产业转型升级,推动实体经济与数字经济深度融合。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档