
Loading...
Loading
Loading...
LoadingLoading audit report...

WalletGuard.ai, powered by Gestalt Labs
Findings selected for deep verification. Where possible we generated a Solidity proof-of-concept and executed it against a forked mainnet.
contracts/GaugeManager.solFunction: distributeAllcontracts/GaugeManager.solFunction: claimBribesLines: 310-315The analyzed contract appears to be a ve(3,3) decentralized exchange and governance protocol on Ethereum mainnet, encompassing gauge management, liquidity incentives, voting escrow NFTs, and governance execution. The analysis identified 0 critical, 8 high, 17 medium, 9 low, and 6 informational findings across 40 total submissions after deduplication. The single most dangerous pattern is the governance execute() function permitting execution of Defeated and Expired proposals, which allows governance actions explicitly rejected by token holders to be forced through, including potential unauthorized token minting. Overall, the contract suite presents a high risk posture due to compounding logic errors in governance, reward accounting, and access control that together expose user funds and protocol integrity to material exploitation.
The governance system is supposed to only execute proposals that won a majority vote. Due to a logic error, proposals that were voted down or expired can also be executed. This means a single actor could push through governance actions the community explicitly rejected, such as minting tokens or changing protocol parameters.
Due to a naming collision in the code, the reward rate stored for a liquidity pool is never actually updated when new rewards are added. Every subsequent reward distribution calculates leftover rewards as zero, meaning accumulated unpaid rewards are silently lost each epoch. Liquidity providers receive incorrect reward amounts and the protocol's accounting becomes permanently incorrect.
The function that updates the router contract address has its safety check backwards. It only accepts the zero address (an invalid address) and rejects all real addresses. This means the router can never be legitimately updated, and if it is ever called as written, it would set the router to an invalid address and break all liquidity operations.
5 centralization points identified
The unnecessary approve grants the manager persistent approval over released tokens, creating an elevated privilege surface. Exploitation requires a secondary compromise of the manager contract's logic.
releaseLock()Duplicate of Finding 27 (FindingId 928e9e43) from a different agent perspective; same root cause and impact. Admin setting dibsPercentage at or above the denominator bricks fee collection.
setReferralFee()The dependency on GaugeManager as the sole reward claim path means GaugeManager downtime or upgrade could temporarily freeze user reward access; this is a design risk without an immediate exploit path.
getReward()An authorized admin setting dibsPercentage above the denominator would cause all fee claims to revert due to arithmetic underflow, effectively bricking fee collection; the risk is bounded by the access control of the setReferralFee function.
setReferralFee()Finding 5 (Governor execute() allows Defeated/Expired proposals) combines with Finding 16 (BlackGovernor uses block.number-1 as timestamp for proposal threshold). The misconfigured proposal threshold check may allow a proposer with minimal voting power to create proposals. Once a proposal is created and voted down by the community, the execute() logic error permits the attacker to execute it anyway. Together, the attacker can bypass both the proposal creation threshold and the voting outcome requirement to force arbitrary governance actions.
Finding 9 (GaugeFactoryCL.createGauge has no access control) enables any attacker to call createGauge, which internally triggers createEternalFarming (Finding 11). createEternalFarming calls safeApprove for 1e10 reward tokens and transfers them to an attacker-controlled farming address if the farmingParam has been set to a malicious contract by a compromised GaugeAdmin (Finding 3). The attacker can repeatedly create gauges to drain the factory's token balance or any token allowance granted to the factory.
Finding 36 (AutoVotingEscrow.lockOwner returns wrong owner for unregistered tokens due to default index 0) combines with Finding 34 (releaseLock does not verify tokenId exists before using tokenIdIndex). An attacker or a logic bug in the manager can pass an unregistered tokenId to releaseLock, which defaults to index 0 and deletes the first registered lock. The corrupted lockOwner lookup then returns the wrong owner, potentially allowing unauthorized token release via disableAutoVoting in the manager.
Finding 1 and Finding 17 both describe the same underlying rewardRate shadow variable bug in GaugeCL.notifyRewardAmount, causing the storage rewardRate to remain at 0. Finding 22 (uint256 to uint128 truncation) then silently truncates large reward values before passing them to the farming contract. Together, the accounting layer reports zero reward rate while simultaneously passing potentially truncated reward amounts to the farming pool, causing LP rewards to be calculated and distributed incorrectly across every epoch.
| Agent | Status | Findings | Severity | Confidence | Duration | Coverage |
|---|---|---|---|---|---|---|
| reentrancy | success | 8 | 2H2M | 79% | 1.6m | Cross-function reentrancy in GaugeCL deposit/withdraw/getReward/notifyRewardAmount/claimFees, Cross-function reentrancy in GaugeV2 deposit/withdraw/getReward/notifyRewardAmount, ERC-777 callback reentrancy via token transfers in GaugeCL and GaugeV2, Bribe contract reentrancy via notifyRewardAmount callbacks, AutoVotingEscrow lock management reentrancy, GaugeManager distribute functions for reentrancy, GaugeFactoryCL createGauge and createEternalFarming for reentrancy and logic errors, BlackClaims claimAndStakeReward for reentrancy and accounting errors, ReentrancyGuard usage verification across all contracts, CEI pattern compliance, Shadow variable analysis in GaugeCL.notifyRewardAmount, Governor execute state checks, GenesisPoolManager router update logic, VoterV3 vote/reset cross-function reentrancy, Pair.swap callback-based flash loan reentrancy (uses custom lock modifier), AutoVotingEscrowManager enableAutoVoting/disableAutoVoting reentrancy, RewardsDistributor claim reentrancy |
| access control | success | 10 | 1H3M1L | 74% | 1.5m | Access control on all public/external state-changing functions across all contracts, Initializer protection for upgradeable contracts (GaugeFactoryCL, AlgebraPoolAPIStorage, GaugeManager, AutoVotingEscrowManager, MinterUpgradeable), Ownership and role patterns including two-step transfers and self-grant risks, Signature verification in Pair.permit() and VotingEscrow.delegateBySig(), ecrecover return value checks, Governance execute() logic in Governor.sol and BlackGovernor.sol, Fee distribution access control in GaugeCL and GaugeV2, AutoVotingEscrow lock/release mechanics, Genesis pool manager logic including router setter, Bribe contract access control, ERC20 transfer patterns and reentrancy guards |
| economic | success | 11 | 2H2M1L | 76% | 2.2m | Flash loan attack vectors on gauge deposit/withdraw functions, Oracle manipulation - no direct price feed oracles found; Algebra pool slot0 used only for quote computation in API helpers, not for liquidation, Governance attack vectors - BlackGovernor proposal/execute flow, voting weight mechanics, quorum calculation, Flash loan governance capture - veNFT-based voting using getPastVotes with timestamp snapshots, Reward manipulation in GaugeCL and GaugeV2 - rewardRate state variable shadowing, MEV exposure in RouterV2 swap functions, Sandwich attack vectors on epoch distributions, BlackClaims reward calculation math, GenesisPoolManager logic errors including setRouter zero-address check inversion, AutoVotingEscrow manager AVM flow and lock management, MinterUpgradeable emission calculation and nudge() logic, Bribe contract reward accumulation and checkpoint logic, GaugeFactoryCL createEternalFarming seed reward sourcing, BlackGovernor execute() state machine allowing defeated/expired proposal execution, VotingEscrow delegation and balance calculation |
| logic validation | success | 14 | 3H6M2L | 85% | 2.0m | Input validation on all public/external functions, Integer overflow/underflow including unchecked blocks, State machine integrity for GenesisPool, BlackClaims seasons, governance proposals, Governance execute() state checks across both Governor implementations, Arithmetic precision in reward rate calculations, Array bounds checking in API helper contracts, Access control modifiers and role-based permissions, EIP-712 domain separator usage in VotingEscrow.delegateBySig, abi.encodePacked hash collision risks, Timestamp dependence in epoch calculations, Unbounded loops in distribution and API functions, Truncation from uint256 to uint128 in reward calculations, Router zero-address validation logic |
| code quality | success | 16 | 1L | 83% | 2.3m | ERC-20 compliance (Black token), ERC-721 compliance (VotingEscrow, Thenian), Access control on all external/public functions, Integer overflow and unsafe downcasts, Reentrancy vulnerabilities, Governance logic (BlackGovernor, L2Governor), Fee distribution logic (GaugeManager, GaugeCL, GaugeV2), Genesis pool lifecycle logic, AutoVotingEscrow lock management, Router and swap logic, Reward distribution (RewardsDistributor, Bribes), Loop bounds and array bounds, Zero address checks, Token transfer safety, Epoch and time-based logic, Proxy/upgrade safety (OwnableUpgradeable, Initializable), Cross-contract interaction patterns |
| compiler bugs | success | 4 | 1H2M | 81% | 59.6s | GaugeCL deposit/withdraw/getReward/notifyRewardAmount access control and logic, GaugeFactoryCL createGauge and createEternalFarming incentive key construction, GaugeManager distribution, fee distribution, and claimRewards access control, GenesisPoolManager router setter zero-address check, Bribe deposit/withdraw/getReward/notifyRewardAmount logic, VoterV3 vote/reset/poke access control and epoch gating, MinterUpgradeable nudge and update_period logic, AutoVotingEscrowManager enableAutoVoting/disableAutoVoting token custody, BlackClaims season finalization and claim logic, RewardsDistributor claim and checkpoint_token logic, Variable shadowing in GaugeCL.notifyRewardAmount (rewardRate), Compiler bug patterns (pragma 0.8.13 - not in any known affected range for listed bugs), Integer overflow/underflow in unchecked blocks, Reentrancy guard coverage across all state-mutating functions, Emergency mode activation/deactivation consistency |
| assembly safety | success | 12 | 1H2M2L | 81% | 2.1m | All assembly{} blocks scanned - Base64.sol contains assembly for base64 encoding (standard pattern, no issues), VotingEscrow.sol safeTransferFrom contains assembly revert (standard OZ pattern), no other assembly blocks found, Full codepoint-by-codepoint scan for non-ASCII characters in identifiers, comments, and string literals - no non-ASCII characters found, Invisible character attacks (RTLO U+202E, zero-width joiners U+200D/200B/200C, Cyrillic homoglyphs) - none detected, Keyword obfuscation (lookalike assembly/selfdestruct/delegatecall identifiers) - none detected, Governance logic in BlackGovernor and L2Governor execute() state checks, GaugeCL reward distribution and notifyRewardAmount logic, GaugeFactoryCL access control and createEternalFarming, AutoVotingEscrow lock management and releaseLock, GenesisPoolManager router setter, BlackClaims reward claiming math, GaugeV2 withdrawal and balance deduction logic, Bribe reward claiming access patterns, Integer truncation in uint128 casts, Zero-address guard correctness across all setter functions, Reentrancy patterns across all nonReentrant-guarded functions, Storage variable shadowing in return parameters |
| l2 specific | success | 13 | 2H4M2L | 84% | 2.0m | Governor.sol execute() and propose() flow for proposal state logic, GaugeCL.sol notifyRewardAmount for variable shadowing, GaugeFactoryCL.sol access control on createGauge, GaugeV2.sol and GaugeCL.sol for access control, fee logic, and input validation, BlackClaims.sol for reward accounting logic, AutoVotingEscrow.sol and AutoVotingEscrowManager.sol for ownership tracking, GenesisPoolManager.sol for router setter logic, MinterUpgradeable.sol for emission calculation and nudge logic, VoterV3.sol for voting window and AVM checks, TradeHelper.sol for loop bounds and integer underflow, BlackTimeLibrary.sol for epoch duration configuration, GaugeFactoryCL.sol for fee bounds checking, RewardsDistributor.sol for claim logic and balance accounting, Bribes.sol for deposit/withdraw and reward distribution logic, VotingEscrow.sol for lock mechanics and delegation, PairFactory.sol and Pair.sol for AMM safety, RouterV2.sol for swap routing and access control, GaugeManager.sol for distribution logic and governance |
This automated audit has inherent limitations. The following areas are not covered.
This report is an automated point-in-time assessment and does not guarantee protection against all possible attacks. It does not cover off-chain components, economic modeling, or business logic correctness unless explicitly noted. Changes to the contract after the audit commit are not reviewed. This is not financial or legal advice. WalletGuard, powered by Gestalt Labs, provides this analysis as-is with no warranty of completeness.
[](https://walletguard.ai/audit/cc944a7f-4a16-4eb6-bc87-3e29f8c74f68)
<a href="https://walletguard.ai/audit/cc944a7f-4a16-4eb6-bc87-3e29f8c74f68"> <img src="https://walletguard.ai/api/badge/cc944a7f-4a16-4eb6-bc87-3e29f8c74f68" alt="WalletGuard Audit Badge" /> </a>