Liquid Staking

Stakelink
DeFiHardhatOracle
50,000 USDC
View results
Submission Details
Severity: medium
Invalid

contracts/ethStaking/OperatorWhitelist.sol

The OperatorWhitelist contract you provided has a few potential vulnerabilities and areas for improvement. Here are some of the key points to consider:

  1. Reentrancy Risk:

    • Although the contract does not call external contracts, it is still a good practice to use the Checks-Effects-Interactions pattern, especially if you plan to expand the contract later. While the current implementation is safe, ensure that any future changes maintain this pattern.

  2. Gas Limit in Loops:

    • Functions like addWhitelistEntries and removeWhitelistEntries iterate over _accounts, which can lead to gas limit issues if the input array is large. Consider implementing a more gas-efficient mechanism, such as batching or allowing for only a fixed number of entries to be processed in a single transaction.

  3. Address Zero Checks:

    • There's no validation for the _wlOperatorController and the addresses in _whitelist. An address of zero should be checked to avoid adding it to the whitelist or setting it as the controller, as it can lead to unexpected behavior.

    require(_wlOperatorController != address(0), "Controller address cannot be zero");
  4. Event Emission:

    • It is advisable to emit events for state-changing functions like addWhitelistEntries, removeWhitelistEntries, useWhitelist, and setWLOperatorController. This will allow off-chain applications and users to track the changes to the whitelist more easily.

    event WhitelistEntryAdded(address indexed account);
    event WhitelistEntryRemoved(address indexed account);
    event WhitelistEntryUsed(address indexed account);
    event WLOperatorControllerSet(address indexed newController);
  5. Redundant State Variable:

    • The isUsed state variable might not be necessary, as it is tied to the specific logic of whether an account can use its whitelist entry. Consider if you need this variable or if it can be managed in a different way, depending on your overall logic design.

  6. Access Control:

    • Currently, only the owner can add or remove addresses from the whitelist. Ensure that the owner is adequately managed and consider adding multi-signature functionality or using a more sophisticated access control pattern for improved security.

  7. Consider Visibility Modifiers:

    • The getWhitelistEntry function could be marked as public instead of external, as it is only called from within the contract. While this is not a vulnerability per se, it can enhance gas efficiency when called internally.

  8. Potential for Integer Overflow/Underflow:

    • While Solidity 0.8.x has built-in checks for integer overflow and underflow, it is still good practice to be aware of this in case you ever switch to an earlier version.

Here’s a revised version of your contract addressing some of these issues:

// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.15;
import "@openzeppelin/contracts/access/Ownable.sol";
/**
* @title Operator Whitelist
* @notice Tracks which accounts are able to add new whitelisted operators
*/
contract OperatorWhitelist is Ownable {
struct WhitelistEntry {
bool isWhitelisted;
bool isUsed;
}
address public wlOperatorController;
mapping(address => WhitelistEntry) private whitelist;
event WhitelistEntryAdded(address indexed account);
event WhitelistEntryRemoved(address indexed account);
event WhitelistEntryUsed(address indexed account);
event WLOperatorControllerSet(address indexed newController);
constructor(address _wlOperatorController, address[] memory _whitelist) {
require(_wlOperatorController != address(0), "Controller address cannot be zero");
wlOperatorController = _wlOperatorController;
for (uint256 i = 0; i < _whitelist.length; i++) {
require(_whitelist[i] != address(0), "Whitelist cannot contain zero address");
whitelist[_whitelist[i]] = WhitelistEntry(true, false);
emit WhitelistEntryAdded(_whitelist[i]);
}
}
function getWhitelistEntry(address _account) public view returns (WhitelistEntry memory) {
return whitelist[_account];
}
function useWhitelist(address _account) external {
require(msg.sender == wlOperatorController, "Sender is not wl operator controller");
require(whitelist[_account].isWhitelisted, "Account is not whitelisted");
require(!whitelist[_account].isUsed, "Account whitelist spot already used");
whitelist[_account].isUsed = true;
emit WhitelistEntryUsed(_account);
}
function addWhitelistEntries(address[] calldata _accounts) external onlyOwner {
for (uint256 i = 0; i < _accounts.length; i++) {
address account = _accounts[i];
require(account != address(0), "Cannot whitelist zero address");
require(!whitelist[account].isWhitelisted, "Account already whitelisted");
whitelist[account] = WhitelistEntry(true, false);
emit WhitelistEntryAdded(account);
}
}
function removeWhitelistEntries(address[] calldata _accounts) external onlyOwner {
for (uint256 i = 0; i < _accounts.length; i++) {
address account = _accounts[i];
require(whitelist[account].isWhitelisted, "Account is not whitelisted");
whitelist[account].isWhitelisted = false;
emit WhitelistEntryRemoved(account);
}
}
function setWLOperatorController(address _wlOperatorController) external onlyOwner {
require(_wlOperatorController != address(0), "Controller address cannot be zero");
wlOperatorController = _wlOperatorController;
emit WLOperatorControllerSet(_wlOperatorController);
}
}

Summary

The code is relatively straightforward, but attention to gas efficiency, proper checks for address validity, and good practices such as event emissions can help improve the security and usability of your contract. Always ensure to conduct thorough testing and audits before deploying any smart contract to production.

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Lack of quality

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.