Open sherlock-admin3 opened 1 month ago
The protocol team fixed this issue in the following PRs/commits: https://github.com/Velocimeter/v4-contracts/pull/14
Fix looks good. MAX_DELEGATES
value is now 50.
The Lead Senior Watson signed off on the fix.
BiasedMerc
High
VotingEscrow MAX_DELEGATES value can lead to DOS on certain EVM-compatible chains
Summary
VotingEscrow
MAX_DELEGATES
is a hardcoded variable that ensures an address does not have an array of delegates that would lead to a DOS when callingtransfer/burn/mint
when moving delegates.. However the current value of1024
can still lead to a DOS on certain chains.Vulnerability Detail
Within the contest README, the protocol states that the code is expected to function on any EVM-compatible chain, without any plans to include Ethereum mainnet:
The sponsor has also stated that it should be assumed the code will be deployed to all EVM compatible chains:
When testing the gas usage of withdrawing a tokenId that currently has the maximum number of delegates, the gas usage is:
console::log("gas used:", 23637422 [2.363e7]) [staticcall]
Popular EVM compatible chains block gas limit (under 24m): Scroll EVM: 10,000,000 Gnosis Chain: 17,000,000
POC
Add the following test function to
VotingEscrow.t.sol
:To run:
forge test --match-test testDelegateLimitAttack -vv
Output:Impact
As seen, this upper gas limit exceeds the outlined EVM-compatible chains, meaning the current hardcoded value of
MAX_DELEGATES
can lead to a DOS by delegating minimum value locks to an address, causing that tokenId to revert when calling any function that calls_moveTokenDelegates
as the gas utilised will exceed the chains gas limit for a singular block. Affected functions: transferFrom(), withdraw(), merge(), _mint().This will lead to a user's NFT being locked from utilising the outlined functions, causing their funds to be locked, leading to a loss of funds with no special outside factors needed to allow this type of attack (apart from deploying on one of the outlined chains, which as stated in the ReadMe is applicable).
Code Snippet
VotingEscrow::transferFrom() VotingEscrow::withdraw() VotingEscrow::merge() VotingEscrow::_mint()
Tool used
Manual Review
Recommendation
Reducing the
MAX_DELEGATES
value to 256 would reduce the cost of the outlined function to ~6,000,000 which would solve the outlined issue.