The PerpetualVault.sol
contract allows the owner to set or change the treasury address via PerpetualVault.sol::setTreasury()
, which lacks multi-signature control, a time delay, or on-chain tracking. This introduces a centralisation risk, as the owner (or a compromised admin) could redirect protocol funds to an attacker-controlled wallet.
Vulnerable code:
Only the contract owner (onlyOwner
) can update treasury, meaning one person has full control.
No event is emitted, making treasury updates difficult to track.
No time delay or governance process, allowing instant fund redirection.
Access Control is enforced via onlyOwner
, meaning only the contract owner can change the treasury.
The function requires \_treasury
to be non-zero, preventing accidental null assignments:
While the above checks improve security, it does not fully prevent fund mismanagement.
Admin Can Still Redirect Funds (Centralisation Risk)
The onlyOwner
modifier does not prevent a malicious or compromised owner from setting treasury to an attacker-controlled address.
If withdrawal fees or revenue-sharing rely on the treasury, fees can be siphoned away before users withdraw.
The treasury can change at any time without on-chain tracking.
Users and security auditors won’t notice malicious treasury updates.
Treasury updates happen immediately.
A rogue owner can change it, withdraw fees, and exit before users react.
Exit Scam Risk: A rogue admin can change the treasury, drain protocol fees, and disappear.
Lack of Transparency: Users cannot verify where fees are going in real-time.
Protocol Governance Bypass: No community oversight exists over treasury updates.
Centralised Control: Even if the owner is trusted, the lack of multi-sig security makes it a single point of failure.
Lack of User Protection: Users cannot veto or delay treasury changes.
From my professional background I had a hunch of potential issues that this and other DeFi protocols might have, I used OpenAI's GPT-4 to help explore the in-scope codebase.
Implement Multi-Signature Approval for Treasury Updates
Emit an Event for Transparency
Enforce a Delay on Treasury Changes
Prevent instant updates by adding a timelock (e.g., 24-hour delay).
Please read the CodeHawks documentation to know which submissions are valid. If you disagree, provide a coded PoC and explain the real likelihood and the detailed impact on the mainnet without any supposition (if, it could, etc) to prove your point. Keepers are added by the admin, there is no "malicious keeper" and if there is a problem in those keepers, that's out of scope. ReadMe and known issues states: " * System relies heavily on keeper for executing trades * Single keeper point of failure if not properly distributed * Malicious keeper could potentially front-run or delay transactions * Assume that Keeper will always have enough gas to execute transactions. There is a pay execution fee function, but the assumption should be that there's more than enough gas to cover transaction failures, retries, etc * There are two spot swap functionalies: (1) using GMX swap and (2) using Paraswap. We can assume that any swap failure will be retried until success. " " * Heavy dependency on GMX protocol functioning correctly * Owner can update GMX-related addresses * Changes in GMX protocol could impact system operations * We can assume that the GMX keeper won't misbehave, delay, or go offline. " "Issues related to GMX Keepers being DOS'd or losing functionality would be considered invalid."
Please read the CodeHawks documentation to know which submissions are valid. If you disagree, provide a coded PoC and explain the real likelihood and the detailed impact on the mainnet without any supposition (if, it could, etc) to prove your point. Keepers are added by the admin, there is no "malicious keeper" and if there is a problem in those keepers, that's out of scope. ReadMe and known issues states: " * System relies heavily on keeper for executing trades * Single keeper point of failure if not properly distributed * Malicious keeper could potentially front-run or delay transactions * Assume that Keeper will always have enough gas to execute transactions. There is a pay execution fee function, but the assumption should be that there's more than enough gas to cover transaction failures, retries, etc * There are two spot swap functionalies: (1) using GMX swap and (2) using Paraswap. We can assume that any swap failure will be retried until success. " " * Heavy dependency on GMX protocol functioning correctly * Owner can update GMX-related addresses * Changes in GMX protocol could impact system operations * We can assume that the GMX keeper won't misbehave, delay, or go offline. " "Issues related to GMX Keepers being DOS'd or losing functionality would be considered invalid."
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.