Core Contracts

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

Parameter Gaming Due to Lack of Rate Limiting in Governance Updates

1. Summary

A severity vulnerability exists in the governance contract’s parameter update mechanism. While the contract enforces basic bounds checking, it does not implement any rate limiting, allowing malicious actors to rapidly modify governance parameters. This could lead to:

  • Governance instability due to frequent parameter changes

  • Voting process manipulation by adjusting thresholds and timing

  • Potential flash loan governance attacks

2. Vulnerability Details

Severity: Medium

Likelihood: High

Impact: Governance Manipulation

The root cause is the absence of a rate-limiting mechanism in the setParameter function:

function setParameter(GovernanceParameter param, uint256 newValue) external override onlyOwner {
ParameterConfig storage config = _parameters[param];
if (newValue < config.minValue || newValue > config.maxValue) {
if (param == GovernanceParameter.VotingDelay)
revert InvalidVotingDelay(newValue, config.minValue, config.maxValue);
if (param == GovernanceParameter.VotingPeriod)
revert InvalidVotingPeriod(newValue, config.minValue, config.maxValue);
if (param == GovernanceParameter.ProposalThreshold)
revert InvalidProposalThreshold(newValue, config.minValue, config.maxValue);
if (param == GovernanceParameter.QuorumNumerator)
revert InvalidQuorumNumerator(newValue, config.minValue, config.maxValue);
}
uint256 oldValue = config.value;
config.value = newValue;
if (param == GovernanceParameter.VotingDelay) {
votingDelay = newValue;
emit VotingDelaySet(oldValue, newValue, msg.sender);
} else if (param == GovernanceParameter.VotingPeriod) {
votingPeriod = newValue;
emit VotingPeriodSet(oldValue, newValue, msg.sender);
} else if (param == GovernanceParameter.ProposalThreshold) {
proposalThreshold = newValue;
emit ProposalThresholdSet(oldValue, newValue, msg.sender);
} else if (param == GovernanceParameter.QuorumNumerator) {
quorumNumerator = newValue;
emit QuorumNumeratorSet(oldValue, newValue, msg.sender);
}
}

Root Cause

  • No cooldown period between updates

  • No tracking of recent changes to prevent frequent modifications

  • No governance vote required before changing key parameters

Potential Exploit Scenarios

  1. Lowering the ProposalThreshold multiple times → Allows an attacker to spam proposals.

  2. Shortening the VotingPeriod → Enables an attacker to rush votes before defenders react.

  3. Increasing the QuorumNumerator → Makes it harder for legitimate proposals to pass.

  4. Rapid cycling of VotingDelay → Causes confusion and unpredictability in governance.


3. Proof of Concept (PoC)

I write a Hardhat test demonstrates this vulnerability:

const { ethers } = require('hardhat');
const { expect } = require('chai');
describe('Parameter Gaming Vulnerability Test', function () {
let governance, owner, attacker;
const INITIAL_VOTING_DELAY = 86400; // 24 hours
beforeEach(async function () {
[owner, attacker] = await ethers.getSigners();
// Deploy governance contract
const Governance = await ethers.getContractFactory('Governance');
governance = await Governance.deploy(
ethers.constants.AddressZero, // veToken
ethers.constants.AddressZero // timelock
);
// Set up initial state
await governance.setParameter(0, INITIAL_VOTING_DELAY);
});
it('should demonstrate rapid parameter changes', async function () {
const initialDelay = await governance.votingDelay();
console.log('Initial voting delay:', initialDelay.toString());
// Rapid parameter changes
await governance.setParameter(0, INITIAL_VOTING_DELAY / 2);
const delayAfterFirstChange = await governance.votingDelay();
console.log('Delay after first change:', delayAfterFirstChange.toString());
await governance.setParameter(0, INITIAL_VOTING_DELAY / 4);
const delayAfterSecondChange = await governance.votingDelay();
console.log('Delay after second change:', delayAfterSecondChange.toString());
// Verify multiple changes occurred
expect(delayAfterFirstChange).to.not.equal(initialDelay);
expect(delayAfterSecondChange).to.not.equal(delayAfterFirstChange);
});
});

Test Output

Parameter Gaming Vulnerability Test
should demonstrate rapid parameter changes (145ms)
--- Logs ---
Initial voting delay: 86400
Delay after first change: 43200
Delay after second change: 21600

This confirms that an attacker can rapidly adjust governance parameters, enabling governance manipulation.


4. Recommended Mitigations

To secure the governance system, this solution should be implemented:

1. Rate Limiting on Parameter Updates

Enforce a minimum delay between consecutive updates:

mapping(GovernanceParameter => uint256) public lastParameterUpdate;
uint256 public constant MIN_UPDATE_DELAY = 1 days;
modifier rateLimited(GovernanceParameter param) {
require(
block.timestamp >= lastParameterUpdate[param] + MIN_UPDATE_DELAY,
"Parameter update too soon"
);
lastParameterUpdate[param] = block.timestamp;
_;
}
function setParameter(GovernanceParameter param, uint256 newValue)
external
override
onlyOwner
rateLimited(param)
{
// Existing parameter validation and update logic
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 3 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
inallhonesty Lead Judge 3 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.