Skip to content

Latest commit

 

History

History
65 lines (46 loc) · 3.44 KB

009.md

File metadata and controls

65 lines (46 loc) · 3.44 KB

Clean Fossilized Stallion

High

Unable to vote or poke for any exchange besides Aerodrome due to incorrect function name in checkIncreaseUnlockTime

Summary

Each time an operator calls vote or poke it checks if the unlock time can be increased for the veNFT in the corresponding voting escrow contract. The issue is that it calls the wrong function name in checkIncreaseUnlockTime to grab the currentLocked.end time for Ramses, Thena, and Equalizer escrow contracts which will cause the transaction to revert and prevent the operator from executing these actions.

Root Cause

The checkIncreaseUnlockTime function will be called in the MasterUtils contract for Thena, Ramses, and Equalizer as it is not overridden in their respective base contracts. The root cause of the issue is that all three call the locked function in the Ive interface. None of the voting escrow contracts of these exchanges implement this function name and therefore will revert when attempting to get the lock end time for their respective VE contracts.

Lets take Thena for example. Below is the function used to get the locked end time. https://bscscan.com/address/0xfBBF371C9B0B994EebFcC977CEf603F7f31c070D#code

/// @notice Get timestamp when `_tokenId`'s lock finishes
    /// @param _tokenId User NFT
    /// @return Epoch time of the lock end
    function locked__end(uint _tokenId) external view returns (uint) {
        return locked[_tokenId].end;
    }

It uses locked__end and not `locked. The same goes for Ramses and Equalizer.

Internal pre-conditions

  1. Tokens are vote escrowed and operators are allowed to vote

External pre-conditions

No response

Attack Path

Any operator attempts to vote it will revert

Impact

Unable to vote in Thena, Equalizer, and Ramses utils contracts

PoC

No response

Mitigation

The function for getting lock time in Ive.sol should be modified.

-function locked(uint256 _tokenId) external view returns (LockedBalance memory);
+function locked__end(uint _tokenId) external view returns (uint)

Then the corresponding checkIncreaseUnlockTime in MasterUtils.sol should be modified to the following

   function checkIncreaseUnlockTime(uint256 tokenId, uint256 lockDuration) public view virtual returns (bool) {
-        Ive.LockedBalance memory currentLocked = Ive(ve).locked(tokenId);
+.      uint memory currentLockedEnd = Ive(ve).locked__end(tokenId);
        uint256 unlockTime = ((block.timestamp + lockDuration) / 1 weeks) * 1 weeks;
-        return unlockTime > currentLocked.end;
+.      return unlockTime > currentLockedEnd;
    }

As the AerodromeUtils.sol already overrides this function with its own interface, it is already implemented correctly.