Liquid Staking

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

contracts/core/test/PriorityPoolMock.sol

The Solidity code you provided implements a mock contract called PriorityPoolMock that is designed for testing purposes. While it leverages OpenZeppelin's Pausable contract, there are several considerations and potential vulnerabilities to be aware of:

  1. Pausable Functionality:

    • The contract includes functions to pause and unpause, but updateDistribution calls _unpause() directly, which could lead to vulnerabilities if called under unsafe conditions. It's crucial to ensure that only authorized users can invoke this function, or it should be managed through more stringent access control mechanisms.

  2. Lack of Access Control:

    • The updateDistribution, pauseForUpdate, and setUpkeepNeeded functions are public and can be called by anyone. This can be problematic because it allows any user to modify critical state variables:

      • updateDistribution: Anyone can update the merkleRoot, ipfsHash, amountDistributed, and sharesAmountDistributed.

      • pauseForUpdate: Anyone can pause the contract, potentially disrupting operations.

      • setUpkeepNeeded: Anyone can set the upkeep flag, affecting the control flow of the contract.

    • Consider using a modifier like onlyOwner from OpenZeppelin's Ownable contract or implementing custom access control to restrict access to these functions.

  3. Lack of Input Validation:

    • There is no input validation in the updateDistribution function. For example, you might want to check if the _amountDistributed and _sharesAmountDistributed are greater than zero or if they don't exceed certain limits.

  4. State Variable Visibility:

    • All state variables are public by default, which is fine but consider whether this is the intended design. It may be beneficial to encapsulate these variables to control how they are accessed or modified.

  5. Gas Optimization:

    • The checkUpkeep function returns a boolean value along with the data. This might be acceptable, but the _data parameter is not used to determine the upkeep condition. Consider removing unused parameters to save on gas and improve readability.

  6. Logic in performUpkeep:

    • The performUpkeep function merely assigns _data to lastPerformData. Depending on its intended use, you may want to include logic to ensure it performs necessary actions or checks.

  7. Lack of Events:

    • It’s often beneficial to emit events for important state changes, like when distributions are updated or the contract is paused/unpaused. This can enhance transparency and aid in monitoring.

  8. Reentrancy:

    • If any of the functions update external states or call other contracts, be cautious of potential reentrancy attacks. Although this contract does not currently make such calls, it's good to keep this in mind for future enhancements.

  9. No Error Handling for Upkeep:

    • The checkUpkeep function should ideally include logic that accurately assesses whether upkeep is needed based on contract conditions. As it stands, it relies solely on the upkeepNeeded flag, which may not reflect the actual state of the contract.

Here's a revised version of the PriorityPoolMock contract that addresses some of the above concerns, particularly adding access control using OpenZeppelin's Ownable:

// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.15;
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
/**
* @title Priority Pool
* @notice Mocks contract for testing
*/
contract PriorityPoolMock is Pausable, Ownable {
bytes32 public merkleRoot;
bytes32 public ipfsHash;
uint256 public amountDistributed;
uint256 public sharesAmountDistributed;
uint256 public depositsSinceLastUpdate;
bytes public lastPerformData;
bool public upkeepNeeded;
constructor(uint256 _depositsSinceLastUpdate) {
depositsSinceLastUpdate = _depositsSinceLastUpdate;
}
function updateDistribution(
bytes32 _merkleRoot,
bytes32 _ipfsHash,
uint256 _amountDistributed,
uint256 _sharesAmountDistributed
) external onlyOwner {
amountDistributed = _amountDistributed;
sharesAmountDistributed = _sharesAmountDistributed;
merkleRoot = _merkleRoot;
ipfsHash = _ipfsHash;
}
function checkUpkeep(bytes calldata) external view returns (bool, bytes memory) {
return (upkeepNeeded, upkeepNeeded ? abi.encode(150 ether) : bytes(""));
}
function performUpkeep(bytes calldata _data) external {
lastPerformData = _data;
// Additional logic could be added here
}
function pauseForUpdate() external onlyOwner {
_pause();
}
function setDepositsSinceLastUpdate(uint256 _depositsSinceLastUpdate) external onlyOwner {
depositsSinceLastUpdate = _depositsSinceLastUpdate;
}
function setUpkeepNeeded(bool _upkeepNeeded) external onlyOwner {
upkeepNeeded = _upkeepNeeded;
}
// Emit events for important state changes
event DistributionUpdated(bytes32 indexed merkleRoot, bytes32 indexed ipfsHash, uint256 amountDistributed, uint256 sharesAmountDistributed);
event UpkeepStatusChanged(bool upkeepNeeded);
// Override functions to emit events
function updateDistribution(
bytes32 _merkleRoot,
bytes32 _ipfsHash,
uint256 _amountDistributed,
uint256 _sharesAmountDistributed
) external onlyOwner {
amountDistributed = _amountDistributed;
sharesAmountDistributed = _sharesAmountDistributed;
merkleRoot = _merkleRoot;
ipfsHash = _ipfsHash;
emit DistributionUpdated(_merkleRoot, _ipfsHash, _amountDistributed, _sharesAmountDistributed);
}
function setUpkeepNeeded(bool _upkeepNeeded) external onlyOwner {
upkeepNeeded = _upkeepNeeded;
emit UpkeepStatusChanged(_upkeepNeeded);
}
}

Summary

  • Implement access control (e.g., onlyOwner).

  • Add input validation where necessary.

  • Consider emitting events for state changes.

  • Address any potential reentrancy issues if further complexity is added.

  • Maintain a clear contract design to enhance readability and maintainability.

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.