Pieces Protocol

First Flight #32
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Severity: medium
Invalid

[M-10]: Centralization Risk for trusted owners

Summary

The TokenDivider contract inherits Ownable, granting the owner privileged rights to perform admin tasks. This introduces a centralization risk, as the owner could perform malicious updates or drain funds. Funds are indirectly at risk if the owner acts maliciously or their keys are compromised.

Vulnerability Details

The TokenDivider contract uses the Ownable pattern, which grants the contract owner significant control over the protocol. The owner can perform privileged actions, such as updating critical parameters or withdrawing funds. If the owner's private key is compromised or the owner acts maliciously, they could exploit these privileges to manipulate the contract or drain funds.

contract TokenDivider is IERC721Receiver, Ownable {
// Owner has privileged rights
}

Impact

Medium Impact: Funds are indirectly at risk if the owner acts maliciously or their keys are compromised.

Centralization Risk: The protocol relies on a single trusted entity, which undermines decentralization and trustlessness.

Potential Exploitation: The owner could manipulate the contract state or drain funds, leading to financial losses for users.

Tools Used

Aderyn, Foundry

Recommendations

To reduce centralization risk, implement a multi-signature mechanism or timelock for critical admin functions. For example:

Multi-Signature Wallet: Require multiple signatures to approve privileged actions.

Timelock: Introduce a delay for critical actions, allowing users to react if the owner behaves maliciously.

Example Implementation:

// Use a timelock for privileged actions
import "@openzeppelin/contracts/access/TimelockController.sol";
contract TokenDivider is IERC721Receiver {
TimelockController private timelock;
constructor(address _timelock) {
timelock = TimelockController(_timelock);
}
function privilegedFunction() external onlyTimelock {
// Critical logic here
}
modifier onlyTimelock() {
require(msg.sender == address(timelock), "TokenDivider: Caller is not the timelock");
_;
}
}
Updates

Lead Judging Commences

fishy Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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