The `selectPresident` function in the `RankedChoice` contract lacks any access control mechanism, which allows anyone to call this function and select a new president. This poses a significant security risk, as malicious actors could exploit this to manipulate the election process. To mitigate this vulnerability, we recommend introducing an admin role that has exclusive permission to manage the election process. The admin can be designated at contract deployment and should be responsible for running the `selectPresident` function.
Lack of Access Control on selectPresident Function
* Without any restriction on the `selectPresident` function, any external address can call the function and arbitrarily elect a new president, which may not reflect the actual voting results. This can lead to severe issues such as:
* Election manipulation.
* Loss of integrity in the voting process.
* Unauthorized control over contract operations.
:br#### . **Exploit Scenario**:
:br* An external attacker (non-voter) can monitor the election process and, once they identify an opportunity, call `selectPresident()` to manipulate the results or reset the election before it has concluded.
Manual review
Introduce Admin-Based Access Control
------------------------------------
To fix this vulnerability, the following modifications should be applied:
1. **Admin Role**: Introduce an admin role to control the `selectPresident` function. This admin will be responsible for managing the election process and ensuring that only authorized addresses can initiate the selection of the president.
2. **Admin Assignment**: The admin address should be initialized during the contract deployment and should have the ability to transfer admin rights to another address if needed.
3. **Admin Modifier**: Implement a `onlyAdmin` modifier to restrict access to the `selectPresident` function, ensuring that only the designated admin can call this function.
:br```diff
+ address private s_admin; // Admin address
:br+ constructor(address[] memory voters, address admin) EIP712("RankedChoice", "1"){
- constructor(address[] memory voters) EIP712("RankedChoice", "1") {
VOTERS = voters;
i_presidentalDuration = 1460 days;
s_currentPresident = msg.sender;
s_voteNumber = 0;
+ s_admin = admin; // Initialize admin
}
:br+ modifier onlyAdmin() {
+ if (msg.sender != s_admin) {
+ revert RankedChoice__Unauthorized();
+ }
+ _;
+ }
:br+ function selectPresident() external onleAdmin{
- function selectPresident() external {
// excistin code ...
}
+ function transferAdminRole(address newAdmin) external onlyAdmin {
+ s_admin = newAdmin;
+ }
```
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.