09.状态变量覆盖的含义状态变量覆盖是指子类中的状态变量将父类的状态变量进行覆盖,子类和父类使用了相同名称的状态变量。在这种情况下,如果操作子类的状态变量不会修改父类的状态变量,而此时代码的真实意图可能是为了修改父类的状态变量。
状态变量覆盖是指子类中的状态变量将父类的状态变量进行覆盖,子类和父类使用了相同名称的状态变量。在这种情况下,如果操作子类的状态变量不会修改父类的状态变量,而此时代码的真实意图可能是为了修改父类的状态变量。因此这类覆盖问题有可能会存在安全问题。
漏洞代码test_statevar_shadow.sol
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.5.10;
contract Base {
address public owner;
modifier onlyOwner() {
require(msg.sender==owner,"Only Owner can call the function");
_;
}
}
contract Children is Base {
uint public totalSupply = 100;
address public owner;
constructor() public {
owner = msg.sender;
}
function withdraw(uint _amount) public onlyOwner {
totalSupply = totalSupply - _amount;
// console.log(“aaa”);
}
}
使用slither进行检测
slither test_statevar_shadow.sol
遍历代码中的每个合约
取得该合约对应的父合约中的声明过的状态变量。
得到父合约状态变量的方法为:遍历父合约,只要父合约中有实现过的函数,就交该父合约的状态变量保存到variables_fathers中。
判断当前合约中的变量名与2中的统计的父合约的变量名是否有相同的,如果存在完全相同的变量名,就存在状态变量覆盖的问题。
其中对升级合约中的变量有个单独的判断,is_upgradable_gap_variable,用来忽略掉对升级合约中的误报。
代码位于slither/slither/detectors/shadowing/state.py文件中
def detect_shadowing(contract: Contract):
ret = []
variables_fathers = []
for father in contract.inheritance:
if any(f.is_implemented for f in father.functions + father.modifiers):
variables_fathers += father.state_variables_declared
for var in contract.state_variables_declared:
# Ignore __gap variables for updatable contracts
if is_upgradable_gap_variable(contract, var):
continue
shadow = [v for v in variables_fathers if v.name == var.name]
if shadow:
ret.append([var] + shadow)
return ret
漏洞参考
https://github.com/crytic/slither/wiki/Detector-Documentation#state-variable-shadowing
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!