There is no check that the ticks passed into claimConcentratedRewards actually match the position’s ticks. A user could pass in arbitrary ticks to try to claim rewards for liquidity they don’t own.
The claimConcentratedRewards function allows users to claim mining rewards for a specific position they hold, identified by the lowerTick and upperTick range.
Here’s the vulnerability related to validating the tick inputs in the claimConcentratedRewards function.
function claimConcentratedRewards(
address payable owner,
bytes32 poolIdx,
int24 lowerTick,
int24 upperTick,
uint32[] memory weeksToClaim
) internal {
// Lookup position based on passed ticks
RangePosition72 storage pos = lookupPosition(
owner,
poolIdx,
lowerTick,
upperTick
);
// Rest of reward calculation and transfer
The lowerTick and upperTick passed into the function are used to look up the position via lookupPosition.
However, there is no validation that these match the actual ticks of the position stored in the contract’s mapping.
This means a malicious user could pass in arbitrary tick values that don’t match their position, and claim rewards for liquidity they don’t actually own.
To clarify, here’s a simplified proof of concept demonstrating the lack of tick validation:
// Simplified contract with the same vulnerability
contract LiquidityMining {
struct RangePosition72 {
int24 lowerTick;
int24 upperTick;
}
mapping(address => mapping(bytes32 => RangePosition72)) positions;
function claimConcentratedRewards(
address payable owner,
bytes32 poolIdx,
int24 lowerTick,
int24 upperTick,
uint32[] memory weeksToClaim
) internal {
// Lookup position based on passed ticks
RangePosition72 storage pos = positions[owner][poolIdx];
// Rest of reward calculation and transfer
}
}
The claimConcentratedRewards function retrieves the position based on the passed lowerTick and upperTick without validating whether these ticks match the position’s ticks stored in the mapping of the position.
To exploit this, a user could call claimConcentratedRewards with arbitrary lowerTick and upperTick values, potentially claiming rewards for liquidity they don’t own. The contract lacks the validation checks to ensure that the provided ticks match the actual position.
Vs
The ticks should be validated against the position, the contract should validate lowerTick and upperTick match the position’s ticks after looking it up:
// Lookup position
RangePosition72 storage pos = lookupPosition(/*...*/);
// Validate ticks match position
require(pos.lowerTick == lowerTick, "Invalid lower tick");
require(pos.upperTick == upperTick, "Invalid upper tick");
// Rest of function
Adding this tick validation prevents the attack vector where users can claim arbitrary liquidity rewards.
Invalid Validation
The text was updated successfully, but these errors were encountered:
All reactions