Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
View results
Submission Details
Severity: low
Invalid

Add Check In Cancel() function before Cancel.

Summary

Cancel Function can be called with the already cancelled prosposal ID.

Vulnerability Details

Function cancel is used to cancels active proposals but due to no check user can call already canceled state proposal id this is check effect Interaction

function cancel(uint256 proposalId) external override { // QA @audit can pass alreadt cancled ID
ProposalCore storage proposal = _proposals[proposalId];
if (proposal.startTime == 0) revert ProposalDoesNotExist(proposalId);
ProposalState currentState = state(proposalId);
if (currentState == ProposalState.Executed || currentState == ProposalState.Canceled) {
revert InvalidProposalState(proposalId, currentState, ProposalState.Active, "Cannot cancel executed proposal");
}
// Only proposer or if proposer's voting power dropped below threshold
if (msg.sender != proposal.proposer &&
_veToken.getVotingPower(proposal.proposer) >= proposalThreshold) {
revert InsufficientProposerVotes(proposal.proposer,
_veToken.getVotingPower(proposal.proposer), proposalThreshold, "Proposer lost required voting power");
}
proposal.canceled = true;
emit ProposalCanceled(proposalId, msg.sender, "Proposal canceled by proposer");
}

Impact

cancel Function can be called with already cancel proposal Id.

Tools Used

Manual View

POC

it("should cancel Cancelled Proposal", async () => {
// Setup voting power
await veToken.mock_setVotingPower(await user1.getAddress(), ethers.parseEther("6000000"));
const startTime = await moveToNextTimeframe();
expect(await governance.state(proposalId)).to.equal(ProposalState.Active);
// Cast vote
await governance.connect(user1).castVote(proposalId, true);
// Wait for voting period to end
await time.increaseTo(startTime + VOTING_PERIOD);
await network.provider.send("evm_mine");
// Queue the proposal
await governance.execute(proposalId);
expect(await governance.state(proposalId)).to.equal(ProposalState.Queued);
// Wait for timelock delay
const timelockDelay = await timelock.getMinDelay();
await time.increase(timelockDelay);
await network.provider.send("evm_mine");
// Execute the proposal
await governance.cancel(proposalId);
expect(await governance.state(proposalId)).to.equal(ProposalState.Canceled);
await governance.cancel(proposalId);
});

Recommendations

add Check in cancel() function

if (currentState == ProposalState.Executed || currentState == ProposalState.Canceled) {
revert InvalidProposalState(proposalId, currentState, ProposalState.Active, "Cannot cancel executed proposal");
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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