Unfuzzed State Variables
Overview
- Severity: Medium
- Confidence: High
- Affected Versions: All
What are Unfuzzed State Variables?
Unfuzzed state variables refer to contract state variables that are not being included in fuzz testing functions. Fuzz testing is a technique where random or semi-random data is input into a system to uncover potential bugs or vulnerabilities. In the context of smart contracts, when state variables are not fuzzed, it means they are not being subjected to this randomized testing, potentially leaving unexplored vulnerabilities or edge cases.
Why is Fuzz Testing State Variables Important?
Fuzz testing state variables is crucial because:
- It helps uncover unexpected behaviors or vulnerabilities that might not be apparent with standard unit tests.
- It can reveal edge cases that developers might not have considered during the initial implementation.
- It increases the overall test coverage and robustness of the smart contract.
- It can identify potential attack vectors that could be exploited by malicious actors.
Technical Example of Vulnerable Code
pragma solidity ^0.8.0;
contract Token {
mapping(address => uint256) public balances;
uint256 public totalSupply;
address public owner;
constructor(uint256 _initialSupply) {
totalSupply = _initialSupply;
balances[msg.sender] = _initialSupply;
owner = msg.sender;
}
function transfer(address _to, uint256 _amount) public {
require(balances[msg.sender] >= _amount, "Insufficient balance");
balances[msg.sender] -= _amount;
balances[_to] += _amount;
}
function mint(address _to, uint256 _amount) public {
require(msg.sender == owner, "Only owner can mint");
totalSupply += _amount;
balances[_to] += _amount;
}
}
// Test contract
contract TokenTest {
Token token;
function setUp() public {
token = new Token(1000000);
}
function testFuzz_Transfer(address _to, uint256 _amount) public {
token.transfer(_to, _amount);
}
// Missing fuzz tests for totalSupply and owner variables
}
In this example, while the `transfer` function is being fuzz tested, the `totalSupply` and `owner` state variables are not included in any fuzz tests. This could leave potential vulnerabilities in the `mint` function unexplored.
Technical Example of Fixed Code
pragma solidity ^0.8.0;
import "./Token.sol";
contract TokenTest {
Token token;
function setUp() public {
token = new Token(1000000);
}
function testFuzz_Transfer(address _to, uint256 _amount) public {
token.transfer(_to, _amount);
}
function testFuzz_Mint(address _to, uint256 _amount) public {
uint256 initialSupply = token.totalSupply();
token.mint(_to, _amount);
assert(token.totalSupply() == initialSupply + _amount);
}
function testFuzz_OwnerOnly(address _caller) public {
vm.assume(_caller != token.owner());
vm.prank(_caller);
vm.expectRevert("Only owner can mint");
token.mint(address(0), 100);
}
}
In this improved version, we've added fuzz tests that cover the `totalSupply` and `owner` variables, ensuring more comprehensive testing of the contract's functionality.