Description
The _tokenOwner
mapping allows a user to deploy multiple vesting contracts for the same token (tokenAddress) without restriction. This could result in a Denial of Service
(DoS) scenario by overloading the contract storage or computational resources especially if malicious actors intentionally create excessive deployments.
Impact
Resource Exhaustion:
Deploying numerous vesting contracts for the same token could lead to storage and computation issues potentially slowing down or halting the system.
This could cause increased gas costs for legitimate users or make the contract unusable.
System Overhead:
Each vesting contract needs management and consumes contract resources. Without limits the system might degrade in performance.
Operational Complexity:
Managing multiple vesting schedules for the same token may create conflicts or confusion impacting the overall functionality.
Root Cause
The deployVesting
function does not validate whether a vesting contract already exists for a given tokenAddress. The _tokenOwner
mapping only checks if the caller is the token owner but imposes no restriction on the number of contracts deployable per token.
Recommendations
Restrict Single Deployment per Token:
Introduce a mapping to track deployed vesting contracts for each tokenAddress. Prevent multiple deployments for the same token.
+ mapping(address => address) private _deployedVesting; function deployVesting( address tokenAddress, uint256 startTime, uint256 endTime, uint256 steps, string memory vestingId ) external { require(_tokenOwner[msg.sender] == tokenAddress, "SS_VestingDeployer: caller is not the token owner"); + require(_deployedVesting[tokenAddress] == address(0), "SS_VestingDeployer: vesting already exists for this token"); require(tokenAddress != address(0), "SS_VestingDeployer: token address is zero"); require(startTime > block.timestamp, "SS_VestingDeployer: start time must be in the future"); require(startTime < endTime, "SS_VestingDeployer: start time must be before end time"); require(steps > 0, "SS_VestingDeployer: steps must be greater than 0"); require(manager != address(0), "SS_VestingDeployer: manager not set"); address newVesting = address( new SecondSwap_StepVesting( msg.sender, manager, IERC20(tokenAddress), startTime, endTime, steps, address(this) ) ); + _deployedVesting[tokenAddress] = newVesting; IVestingManager(manager).setSellable(newVesting, true); emit VestingDeployed(tokenAddress, newVesting, vestingId); }
Limit Deployments per Owner:
Restrict the number of vesting contracts a single owner can deploy within a specific timeframe to avoid excessive resource use.