Audit Anomalies Archive — Issue#10
Arrays are essential data structures widely employed in various popular programming languages. They are generally utilized to store data of similar types. When these arrays are passed as inputs to functions, it is crucial to perform basic sanity checks, such as ensuring the array is not empty, checking for duplicate values, verifying the array’s size, etc. Failure to conduct these checks can lead to unpredictable behavior.
In this blog, I will elaborate on a particular behavior I encountered during my recent audit.
ALWAYS VALIDATE THE INPUT PASSED BY USER
The Issue
Imagine a staking contract that mints NFTs in exchange for staked ether, allowing users to both mint
and burn
these NFTs.
Now, there is a feature named “split.” This feature allows users to divide their stake into multiple NFTs by specifying the desired weights for the division.
However, issue arises when the function responsible for splitting the stake
fails to validate the input of the weights
array, presuming its size to always be greater than 0.
Take a look at the code snippet below, illustrating the problem.
function splitStake(uint256[] memory weights, uint256 id) external {
StakingInfo memory theStake = stakes[id];
require(ownerOf(id) == msg.sender, "Not the owner");
//@audit-info -> does not check the length of the array
uint256 totalWeight = 0;
for (uint256 i = 0; i < weights.length; i++) {
totalWeight += weights[i];
}
_destroyStake(id, false);
for (uint256 i = 0; i < weights.length; i++) {
uint256 theValue = (uint256(int256(theStake.amount)) * weights[i]) / totalWeight;
_createStake(theValue);
}
}
The impact of this issue is that the user’s NFT gets burned without a corresponding minting of new NFTs, resulting in the loss of the user’s staked ether.
The Learning
The issues described above fall into the category of Input Validation. As a rule of thumb, whenever users are allowed to provide input, certain checks associated with the input should be consistently performed. The psychology behind this lies in the tendency of developers to primarily consider the happy path, assuming that the input is always valid.
For a practical demonstration of this issue via Foundry, details can be found in this link.
Thanks for Reading !