Summary
The DifferenceMomentumUpdateRule::validParameters function lacks a negative kappa value check when setting rules for a pool, which allows negative kappa values to be configured. Having a negative kappa value would impact the intended functionality of the strategy.
Vulnerability Details
In DifferenceMomentumUpdateRule::validParameters, there is a condition to validate kappa values by checking if they are `== 0`. However, this validation does not account for negative kappa values.
function validParameters() {
...
@> if (kappa[i] == 0) {
unchecked {
valid = 0;
}
}
Although only the pool creator can configure the rules and set kappa values, given the significant impact of allowing negative kappa values, it should be validated before rule-setting. Negative kappa values reverse the intended functionality of the momentum strategy, causing weightage adjustment in the opposite direction.
Proof of Concept
Add this in the QuantAMMWEightedPoolFactory.t.sol test file
Prepare create pool param
function _createPoolParams() internal returns (QuantAMMWeightedPoolFactory.NewPoolParams memory retParams) {
PoolRoleAccounts memory roleAccounts;
IERC20[] memory tokens = [address(dai), address(usdc)].toMemoryArray().asIERC20();
MockMomentumRule momentumRule = new MockMomentumRule(owner);
DifferenceMomentumUpdateRule differenceMomentumRule;
vm.startPrank(owner);
differenceMomentumRule = new DifferenceMomentumUpdateRule(address(updateWeightRunner));
vm.stopPrank();
uint32[] memory weights = new uint32[]();
weights[0] = uint32(uint256(0.5e18));
weights[1] = uint32(uint256(0.5e18));
int256[] memory initialWeights = new int256[]();
initialWeights[0] = 0.5e18;
initialWeights[1] = 0.5e18;
uint256[] memory initialWeightsUint = new uint256[]();
initialWeightsUint[0] = 0.5e18;
initialWeightsUint[1] = 0.5e18;
uint64[] memory lambdas = new uint64[]();
lambdas[0] = 0.2e18;
int256[][] memory parameters = new int256[][]();
parameters[0] = new int256[]();
parameters[0][0] = -0.2e18;
parameters[1] = new int256[]();
parameters[1][0] = 0.2e18;
address[][] memory oracles = new address[][]();
oracles[0] = new address[]();
oracles[0][0] = address(chainlinkOracle);
retParams = QuantAMMWeightedPoolFactory.NewPoolParams(
"Pool With Donation",
"PwD",
vault.buildTokenConfig(tokens),
initialWeightsUint,
roleAccounts,
MAX_SWAP_FEE_PERCENTAGE,
address(0),
true,
false,
ZERO_BYTES32,
initialWeights,
IQuantAMMWeightedPool.PoolSettings(
new IERC20[](2),
IUpdateRule(differenceMomentumRule),
oracles,
60,
lambdas,
0.2e18,
0.2e18,
0.2e18,
parameters,
address(0)
),
initialWeights,
initialWeights,
3600,
0,
new string[][]()
);
}
Test deploy pool with a negative kappa value
function test_negativeKappaInDifferenceMomentum() public {
QuantAMMWeightedPoolFactory.NewPoolParams memory params = _createPoolParams();
(address pool, ) = quantAMMWeightedPoolFactory.create(params);
assertTrue(pool != address(0), "Pool should be created");
}
Test passed, indicating a pool using the Difference Momentum Rule can be deployed with a negative kappa value
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 29.41ms (2.80ms CPU time)
Impact
Allowing negative kappa values disrupts the core functionality of the momentum strategy by reversing its effect.
Tools Used
Recommendations
Change the comparison operator from == to <= to include checks for negative value
function validParameters() {
...
- if (kappa[i] == 0) {
+ if (kappa[I] <= 0) {
unchecked {
valid = 0;
}
}