The veRAACToken contract implements a whenNotPaused modifier and maintains a paused state variable, but lacks any functionality to actually pause the contract. This creates a misleading security control that can never be activated.
It also creates an attack vector when the emergency flow gets activated because it allows malicious users to mint veRAACTokens without maintaining the required token lock period anymore.
This completely undermines the vote escrow tokenomics and can be exploited to manipulate governance votes and gauge weights across the protocol.
The vulnerability stems from two key issues:
There is no pause functionality to prevent new locks during emergency situations.
The emergency withdrawal mechanism allows immediate withdrawals once enabled.
The contract includes:
A paused state variable:
A whenNotPaused modifier that checks this variable:
This modifier is applied to critical functions like:
lock()
increase()
extend()
However, there are no functions to set the paused state variable, making the pause functionality effectively useless. This means that even in emergency situations, these functions cannot be paused as intended by the modifier's presence.
Now when the emergency withdrawal mechanism gets activated an attacker can call lock() to get veRAACTokens then use these tokens for voting and immediatly withdraw:
Exploit Scenario:
Emergency withdrawal gets enabled by admin
Eve calls lock() with large amount of RAAC tokens
Eve votes on Gauges / Governance Proposals
Eve alls emergencyWithdraw() to retrieve her RAAC tokens back
In order to run the test you need to:
Run foundryup to get the latest version of Foundry
Install hardhat-foundry: npm install --save-dev @nomicfoundation/hardhat-foundry
Import it in your Hardhat config: require("@nomicfoundation/hardhat-foundry");
Make sure you've set the BASE_RPC_URL in the .env file or comment out the forking option in the hardhat config.
Run npx hardhat init-foundry
There is one file in the test folder that will throw an error during compilation so rename the file in test/unit/libraries/ReserveLibraryMock.sol to => ReserveLibraryMock.sol_broken so it doesn't get compiled anymore (we don't need it anyways).
Create a new folder test/foundry
Paste the below code into a new test file i.e.: FoundryTest.t.sol
Run the test: forge test --mc FoundryTest -vvvv
Complete bypass of the vote escrow locking mechanism
Manipulation of protocol governance through artificial voting power
Exploitation of gauge weights to redirect protocol incentives
The fundamental tokenomics of vote escrow tokens rely on users having to lock tokens long-term to gain voting power. This vulnerability completely undermines that mechanism.
Manual Review
Foundry
Either:
Implement proper pause functionality:
Automatically pause new locks when emergency withdrawal is enabled:
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.