Summary
Players who have successfully registered and have been approved can call the ThePredicter::register
function successfully
Vulnerability Details
The ThePredicter::register
can be called by players that have been approved, this is make them lose their approval status and previous funds in which they used to register. This vulnerability can be traced to the check for player's status, their is only a check for pending players, which means only pending players cannot register twice.
function register() public payable {
if (msg.value != entranceFee) {
revert ThePredicter__IncorrectEntranceFee();
}
if (block.timestamp > START_TIME - 14400) {
revert ThePredicter__RegistrationIsOver();
}
@> if (playersStatus[msg.sender] == Status.Pending) {
revert ThePredicter__CannotParticipateTwice();
}
playersStatus[msg.sender] = Status.Pending;
}
POC
function test_approvedRegisterAgain() public {
vm.startPrank(stranger);
vm.warp(1);
vm.deal(stranger, 1 ether);
thePredicter.register{value: 0.04 ether}();
vm.stopPrank();
vm.startPrank(organizer);
vm.warp(2);
thePredicter.approvePlayer(stranger);
vm.stopPrank();
vm.startPrank(stranger);
vm.warp(1);
vm.deal(stranger, 1 ether);
thePredicter.register{value: 0.04 ether}();
vm.stopPrank();
}
Impact
When approved players mistakingly call the ThePredicter::register
function it will revert the player to a pending status and previous entrance funds will be a waste. There is also no guarantee that the player will be approved again.
Tools Used
Manual Review
Recommendations
The check for player status should cover both pending and approved players, they should not be allowed to register again.
function register() public payable {
if (msg.value != entranceFee) {
revert ThePredicter__IncorrectEntranceFee();
}
if (block.timestamp > START_TIME - 14400) {
revert ThePredicter__RegistrationIsOver();
}
//@audit an approved player can register again
- if (playersStatus[msg.sender] == Status.Pending) {
+ if (playersStatus[msg.sender] == Status.Pending || playersStatus[msg.sender] == Status.Approved) {
revert ThePredicter__CannotParticipateTwice();
}
playersStatus[msg.sender] = Status.Pending;
}