Insufficient Parameter Assertion
Overview
- Severity: High
- Confidence: Medium
- Affected Versions: All
What is Insufficient Parameter Assertion?
Insufficient parameter assertion occurs when a smart contract function does not adequately validate or check its input parameters before using them. This can lead to unexpected behavior, vulnerabilities, or logical errors in the contract's execution.
Why is Insufficient Parameter Assertion Dangerous?
Insufficient parameter assertion can be dangerous because:
- It may allow attackers to input malicious or unexpected values that can exploit the contract.
- It can lead to logical errors in the contract's execution, potentially resulting in financial losses or incorrect state changes.
- It may cause the contract to behave in unintended ways, violating its intended purpose or security assumptions.
- It can make the contract more susceptible to other types of attacks, such as integer overflow/underflow or reentrancy.
Technical Example of Vulnerable Code
pragma solidity ^0.8.0;
contract VulnerableContract {
mapping(address => uint256) public balances;
function transfer(address to, uint256 amount) public {
balances[msg.sender] -= amount;
balances[to] += amount;
}
function withdraw(uint256 amount) public {
require(balances[msg.sender] >= amount, "Insufficient balance");
(bool success, ) = msg.sender.call{value: amount}("");
require(success, "Transfer failed");
balances[msg.sender] -= amount;
}
}
In this example, both the `transfer` and `withdraw` functions have insufficient parameter assertions. The `transfer` function doesn't check if the sender has enough balance before the transfer, and neither function validates that the `amount` is greater than zero or that the `to` address is not the zero address.
Technical Example of Fixed Code
pragma solidity ^0.8.0;
contract SecureContract {
mapping(address => uint256) public balances;
function transfer(address to, uint256 amount) public {
require(to != address(0), "Invalid recipient");
require(amount > 0, "Amount must be greater than zero");
require(balances[msg.sender] >= amount, "Insufficient balance");
balances[msg.sender] -= amount;
balances[to] += amount;
}
function withdraw(uint256 amount) public {
require(amount > 0, "Amount must be greater than zero");
require(balances[msg.sender] >= amount, "Insufficient balance");
balances[msg.sender] -= amount;
(bool success, ) = msg.sender.call{value: amount}("");
require(success, "Transfer failed");
}
}
In this improved version, we've added proper parameter assertions to both functions. We check that the recipient address is not the zero address, that the amount is greater than zero, and that the sender has sufficient balance before performing any operations.