Core Contracts

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

Flash Loan Vulnerability in RAACGauge::voteEmissionDirection Allows Vote Manipulation Through Token Borrowing

Summary

The voting mechanism in RAACGauge can be manipulated using flash loans since there is no lock-up period or pre-vote token holding requirement for casting votes. An attacker can borrow RAAC tokens, convert to veRAACToken, vote, and repay the loan in a single transaction.

Vulnerability Details

function voteEmissionDirection(uint256 direction) external whenNotPaused {
voteDirection(direction);
}
function voteDirection(uint256 direction) public whenNotPaused updateReward(msg.sender) {
if (direction > 10000) revert InvalidWeight();
uint256 votingPower = IERC20(IGaugeController(controller).veRAACToken()).balanceOf(msg.sender);
if (votingPower == 0) revert NoVotingPower();
totalVotes = processVote(
userVotes[msg.sender],
direction,
votingPower,
totalVotes
);
emit DirectionVoted(msg.sender, direction, votingPower);
}

The vulnerability exists because:

  1. No minimum token holding period verification

  2. Vote power checks only current balance

  3. Allows immediate voting after obtaining tokens

  4. No snapshot mechanism for vote counting

PoC

it("should allow flash loan voting manipulation", async function() {
const FlashLoanAttacker = await ethers.getContractFactory("MockFlashLoanAttacker");
const flashLoanAttacker = await FlashLoanAttacker.deploy(
raacToken.address,
veRAACToken.address,
raacGauge.address
);
await raacToken.transfer(flashLoanAttacker.address, ethers.parseEther("1000000"));
await flashLoanAttacker.executeFlashLoanAttack(
ethers.parseEther("1000000"),
5000
);
const voteDirection = await raacGauge.userVotes(flashLoanAttacker.address);
expect(voteDirection.direction).to.equal(5000);
expect(voteDirection.weight).to.equal(0);
});

Impact

  • Vote manipulation through flash loans

  • Governance decisions can be controlled by attackers

  • Protocol parameters can be maliciously altered

  • Undermines democratic governance process

Tools Used

  • Manual code review

  • Hardhat testing framework

  • DeFi testing tools

Recommendations

  1. Implement a minimum token holding period before voting

  2. Add vote power snapshots at fixed intervals

  3. Calculate voting power based on historical balances

  4. Add time-weighted voting mechanisms

function voteEmissionDirection(uint256 direction) external whenNotPaused {
require(getTokenHoldingPeriod(msg.sender) >= MIN_HOLDING_PERIOD, "Insufficient holding period");
uint256 votingPower = getPriorVotes(msg.sender, block.number - 1);
_processVoteWithSnapshot(direction, votingPower);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 17 days ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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