Core Contracts

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

Uncontrolled Governance Proposal Execution Order Due to Unused Predecessor Parameter

Relevant GitHub Links

https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/governance/proposals/TimelockController.sol#L114-L137

https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/governance/proposals/Governance.sol#L509

Summary

The TimelockController's predecessor parameter, designed to enforce proposal execution order, is not utilized in Governance.sol, allowing proposals to be executed in arbitrary order. This can break protocol functionality when proposals are meant to be executed sequentially.

Vulnerability Details

The TimelockController implements a predecessor system to enforce execution order of operations:

// TimelockController.sol
function scheduleBatch(
address[] calldata targets,
uint256[] calldata values,
bytes[] calldata calldatas,
bytes32 predecessor, // Parameter for execution order control
bytes32 salt,
uint256 delay
) external override onlyRole(PROPOSER_ROLE) returns (bytes32) {
// ...
// @audit: always set to 0
// Check predecessor if specified
if (predecessor != bytes32(0)) {
if (!isOperationDone(predecessor) && !isOperationPending(predecessor)) {
revert PredecessorNotExecuted(predecessor);
}
}
}

However, in Governance.sol, this parameter is always set to zero:

// Governance.sol
function _queueProposal(uint256 proposalId) internal {
// ...
_timelock.scheduleBatch(
proposal.targets,
proposal.values,
proposal.calldatas,
bytes32(0), // predecessor always set to 0
salt,
_timelock.getMinDelay()
);
// ...
}

Impact

  • Proposals that depend on previous proposals can be executed out of order

  • Can lead to incorrect protocol state when parameter updates are sequential

  • Protocol upgrades requiring specific execution order can be mishandled

  • No direct fund loss, but potential protocol functionality disruption

Example scenario:

  1. Proposal A: Set new liquidation threshold

  2. Proposal B: Update positions based on new threshold
    If B executes before A, positions will be updated with old threshold.

Tools Used

Manual Review

Recommendations

Add a dependency tracking system to the Proposal struct and use the predecessor parameter in TimelockController properly to enforce proposal execution order. This ensures dependent proposals are executed in the correct sequence.

Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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

Give us feedback!