Summary
The constructor does not set an initial deadline by calling setDeadline(). This leaves the deadline variable in a default value of 0. The result is that the beforeDeadline modifier will incorrectly prevent users from calling deposit() and refund() functions.
Vulnerability Details
constructor (address _WBTC, address _WETH, address _USDC) {
host = msg.sender;
i_WBTC = IERC20(_WBTC);
whitelisted[_WBTC] = true;
i_WETH = IERC20(_WETH);
whitelisted[_WETH] = true;
i_USDC = IERC20(_USDC);
whitelisted[_USDC] = true;
}
function deposit(address _token, uint256 _amount) external beforeDeadline {
if(!whitelisted[_token]) {
revert NotSupportedToken();
}
if(participant[msg.sender]){
balances[msg.sender][_token] += _amount;
IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);
emit GenerousAdditionalContribution(msg.sender, _amount);
} else {
participant[msg.sender] = true;
balances[msg.sender][_token] += _amount;
IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);
emit NewSignup(msg.sender, _amount, getParticipationStatus(msg.sender));
}
}
function refund() external nonReentrant beforeDeadline {
address payable _to = payable(msg.sender);
_refundERC20(_to);
_refundETH(_to);
emit Refunded(msg.sender);
}
modifier beforeDeadline() {
if(block.timestamp > deadline) {
revert BeyondDeadline();
}
_;
}
Impact
The deposit() and refund() functions become unusable. The modifier prevents their usage because the block.timestamp will always be greater than 0 (the default value of deadline because it was not set). These impacts will persist until the setDeadline function is called by the host.
Tools Used
Manual Review.
Recommendations
Set the deadline in the constructor directly:
constructor (address _WBTC, address _WETH, address _USDC, uint256 _days) {
host = msg.sender;
deadline = block.timestamp + _days * 1 days;
i_WBTC = IERC20(_WBTC);
whitelisted[_WBTC] = true;
i_WETH = IERC20(_WETH);
whitelisted[_WETH] = true;
i_USDC = IERC20(_USDC);
whitelisted[_USDC] = true;
}