Farseen0/scar-pairs huggingface dataset:
HIGH severity: Redemption of failed registration fees and pre-validated QI is not guaranteed to be possible. **Description:** [`Ignite::registerWithStake`](https://github.com/Benqi-fi/ignite-contracts/blob/bbca0ddb399225f378c1d774fb70a7486e655eea/src/Ignite.sol#L202) performs a [low-level call](https://github.com/Benqi-fi/ignite-contracts/blob/bbca0ddb399225f378c1d774fb70a7486e655eea/src/Ignite.sol#L215-L2...

Vulnerable code:
// Verify that the sender can receive AVAX
(bool success, ) = msg.sender.call("");
require(success);

(bool success, ) = msg.sender.call{ value: avaxRedemptionAmount}("");
require(success);

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

import "forge-std/Test.sol";

contract A {}

contract TestPayable is Test {
    address eoa;
    A a;

    function setUp() public {
        eoa = makeAddr("EOA");
        a = new A();
    }

    function test_payable() external {
        // Attempt to call an EOA with zero-value transfer
        (bool success, ) = eoa.call{value: 0 ether}("");

        // Assert that the call succeeded
        assertEq(success, true);

        // Attempt to call a contract that does not have a payable fallback/receive function with zero-value transfer
        (success, ) = address(a).call{value: 0 ether}("");

        // Assert that the call failed
        assertEq(success, false);
    }
}
HIGH severity: `StakingContract` refunds are affected by global parameter updates. **Description:** When [`StakingContract::refundStakedAmount`](https://code.zeeve.net/zeeve-endeavors/benqi_smartcontract/-/blob/b63336201f50f9a67451bf5c7b32ddcc4a847ce2/contracts/staking.sol#L691-741) is called by the BENQI admin, the following validation is performed using the globally-defined...

Vulnerable code:
require(
    block.timestamp > record.timestamp + refundPeriod,
    "Refund period not reached"
);
HIGH severity: Insufficient validation of Chainlink price feeds. **Description:** Validation of the `price` and `updatedAt` values returned by Chainlink `AggregatorV3Interface::latestRoundData` is performed within the following functions:
- [`StakingContract::_validateAndSetPriceFeed`](https://code.zeeve.net/zeeve-endeavors/benqi_smartcontract/-/blob/b63336201f50...

Vulnerable code:
(uint80 roundId, int256 price, , uint256 updatedAt, ) = priceFeed.latestRoundData();
if(roundId == 0) revert InvalidRoundId();
if(updatedAt == 0 || updatedAt > block.timestamp) revert InvalidUpdate();
HIGH severity: Incorrect operator when validating subsidisation cap. **Description:** When a new registration is created, `Ignite::_registerWithChecks` [validates](https://github.com/Benqi-fi/ignite-contracts/blob/bbca0ddb399225f378c1d774fb70a7486e655eea/src/Ignite.sol#L925-L928) that the subsidisation amount for the registration does not cause the maximum to be...

Vulnerable code:
require(
    totalSubsidisedAmount + subsidisationAmount < maximumSubsidisationAmount,
    "Subsidisation cap exceeded"
);

require(
-       totalSubsidisedAmount + subsidisationAmount < maximumSubsidisationAmount,
+       totalSubsidisedAmount + subsidisationAmount <= maximumSubsidisationAmount,
        "Subsidisation cap exceeded"
    );
HIGH severity: `StakingContract::slippage` can be outside of `minSlippage` or `maxSlippage`. **Description:** When the BENQI admin sets the `slippage` state by calling [`StakingContract::setSlippage`](https://code.zeeve.net/zeeve-endeavors/benqi_smartcontract/-/blob/b63336201f50f9a67451bf5c7b32ddcc4a847ce2/contracts/staking.sol#L313-328), it is validated that this new value is between the.....

Vulnerable code:
require(
    _slippage >= minSlippage && _slippage <= maxSlippage,
    "Slippage must be between min and max"
);

it("can have slippage outside of max and min", async function () {
    // slippage is set to 4
    await stakingContract.connect(benqiAdmin).setSlippage(4);
    // max slippage is updated below it
    await stakingContract.connect(benqiAdmin).setMaxSlippage(3);

    const slippage = await stakingContract.slippage();
    const maxSlippage = await stakingContract.maxSlippage();
    expect(slippage).to.be.greaterThan(maxSlippage);
});
HIGH severity: Lack of user-defined slippage and deadline parameters in `StakingContract::swapForQI` may result in unfavorable `QI` token swaps. **Description:** When a user interacts with `StakingContract` to provision a hosted node, they can choose between two methods:[`StakingContract::stakeWithAVAX`](https://code.zeeve.net/zeeve-endeavors/benqi_smartcontract/-/blob/b63336201f50f9a67451bf5c7b32ddcc4a847ce2/contracts/staking.sol#L457-L511)...

Vulnerable code:
// Get the best price quote
uint256 slippageFactor = 100 - slippage; // Convert slippage percentage to factor
uint256 amountOutMin = (expectedQiAmount * slippageFactor) / 100; // Apply slippage

uint256 deadline = block.timestamp;
HIGH severity: `AccessControlUpgradeable::_setupRole` is deprecated. **Description:** In [`ValidatorRewarder::initialize`](https://github.com/Benqi-fi/ignite-contracts/blob/bbca0ddb399225f378c1d774fb70a7486e655eea/src/ValidatorRewarder.sol#L38-L59) the `DEFAULT_ADMIN_ROLE` is assigned using...

Vulnerable code:
/**
 * @dev Grants `role` to `account`.
 * ...
 * NOTE: This function is deprecated in favor of {_grantRole}.
 */
function _setupRole(bytes32 role, address account) internal virtual {
    _grantRole(role, account);
}
HIGH severity: Unnecessary `amount` parameter in `StakingContract::stakeWithER`. **Description:** When provisioning a node through [`StakingContract::stakeWithERC20`](https://code.zeeve.net/zeeve-endeavors/benqi_smartcontract/-/blob/b63336201f50f9a67451bf5c7b32ddcc4a847ce2/contracts/staking.sol#L513-L577), users can pay with a supported ERC20 token. The...

Vulnerable code:
require(isTokenAccepted(token), "Token not accepted");
uint256 hostingFee = calculateHostingFee(duration);

uint256 totalRequiredToken = convertAvaxToToken(
    token,
    avaxStakeAmount + hostingFee
);

require(amount >= totalRequiredToken, "Insufficient token");

// Transfer tokens from the user to the contract
IERC20Upgradeable(token).safeTransferFrom(
    msg.sender,
    address(this),
    totalRequiredToken
);
HIGH severity: Staking amount in QI should be calculated differently. **Description:** Currently, if the stake token is `QI`, `stakingAmountInQi` is [calculated](https://code.zeeve.net/zeeve-endeavors/benqi_smartcontract/-/blob/b63336201f50f9a67451bf5c7b32ddcc4a847ce2/contracts/staking.sol#L542-544) as shown below:

However, this can result in a precision loss of 1...

Vulnerable code:
stakingAmountInQi = totalRequiredToken - convertAvaxToToken(token, hostingFee);
HIGH severity: Tokens with more than `18` decimals will not be supported. **Description:** Currently, tokens with more than `18` decimals are not supported due to the decimals handling logic in [`StakingContract::_getPriceInUSD`](https://code.zeeve.net/zeeve-endeavors/benqi_smartcontract/-/blob/b63336201f50f9a67451bf5c7b32ddcc4a847ce2/contracts/staking.sol#L953):

and...

Vulnerable code:
uint256 decimalDelta = uint256(18) - tokenDecimalDelta;

uint tokenAmount = uint(avaxPrice) * registrationFee / uint(tokenPrice) / 10 ** (18 - token.decimals());
HIGH severity: Incorrect revert strings in `StakingContract::revokeAdminRole`. **Description:** There are two revert strings [[1](https://code.zeeve.net/zeeve-endeavors/benqi_smartcontract/-/blob/b63336201f50f9a67451bf5c7b32ddcc4a847ce2/contracts/staking.sol#L1021), [2](https://code.zeeve.net/zeeve-endeavors/benqi_smartcontract/-/blob/b63336201f50f9a67451bf5c7b32ddcc4a847ce2/c...

Vulnerable code:
function revokeAdminRole(bytes32 role, address account) public {
    // Ensure the account parameter is not a zero address to prevent accidental misassignments
    require(
        account != address(0),
        "Cannot assign role to the zero address"
    );

    /* snip: other conditionals */

    } else {
        // Optionally handle cases where an unknown role is attempted to be granted
        revert("Attempting to grant an unrecognized role");
    }

    /*snip: internal call & event emission */
}
HIGH severity: Placeholder recipient constants in `Ignite` should be updated before deployment. **Description:** While it is understood that the [`FEE_RECIPIENT`](https://github.com/Benqi-fi/ignite-contracts/blob/bbca0ddb399225f378c1d774fb70a7486e655eea/src/Ignite.sol#L43) and [`SLASHED_TOKEN_RECIPIENT`](https://github.com/Benqi-fi/ignite-contracts/blob/bbca0ddb399225f378c1d774fb70a7486e655eea...

Vulnerable code:
address public constant FEE_RECIPIENT = 0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaAa; // @audit-info - update placeholder values
address public constant SLASHED_TOKEN_RECIPIENT = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;
HIGH severity: Unnecessary validation of `EnumerableSet` functions. **Description:** When invoking `EnumerableSet::add` and `EnumerableSet::remove`, it is not necessary to first check whether an element [already exists](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/2f0bc58946db746c0d17a2b9d9a8e13f5a8edd7f/contracts/utils/structs/EnumerableSet.sol#L66)....

Vulnerable code:
function addToken(
    address token,
    address priceFeedAddress,
    uint256 maxPriceAge
) external onlyRole(BENQI_ADMIN_ROLE) {
-    require(!acceptedTokens.contains(token), "Token already exists");

    _validateAndSetPriceFeed(token, priceFeedAddress, maxPriceAge);
-    acceptedTokens.add(token);
+    require(acceptedTokens.add(token), "Token already exists");
    emit TokenAdded(token);
}
HIGH severity: Unnecessary conditional block in `Ignite::getTotalRegistrations` can removed. **Description:** The conditional in [`Ignite::getTotalRegistrations`](https://github.com/Benqi-fi/ignite-contracts/blob/bbca0ddb399225f378c1d774fb70a7486e655eea/src/Ignite.sol#L483-L494) is intended to handle the case where there are no registrations aside from the default placeholder...

Vulnerable code:
function getTotalRegistrations() external view returns (uint) {
    if (registrations.length <= 1) {
        return 0;
    }

    // Subtract 1 because the first registration is a dummy registration
    return registrations.length - 1;
}
HIGH severity: Unnecessary validation in `Ignite::getRegistrationsByAccount`. **Description:** In [`Ignite::getRegistrationsByAccount`](https://github.com/Benqi-fi/ignite-contracts/blob/bbca0ddb399225f378c1d774fb70a7486e655eea/src/Ignite.sol#L512-L536), there is [validation](https://github.com/Benqi-fi/ignite-contracts/blob/bbca0ddb399225f378c1d774fb70a7486e655eea/src/Ignite....

Vulnerable code:
require(from < to, "From value must be lower than to value");
require(to <= numRegistrations, "To value must be at most equal to the number of registrations");
HIGH severity: Unnecessary price feed address validation in `Ignite::configurePriceFeed`. **Description:** Unlike [`Ignite::addPaymentToken`](https://github.com/Benqi-fi/ignite-contracts/blob/bbca0ddb399225f378c1d774fb70a7486e655eea/src/Ignite.sol#L791), which performs no validation on the price feed address itself, and only the data it returns,...

Vulnerable code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

import "forge-std/Test.sol";

contract TestZeroAddressCall is Test {
    function test_zeroAddressCall() external {
        vm.expectRevert(); // see: https://book.getfoundry.sh/cheatcodes/expect-revert#gotcha:~:text=%E2%9A%A0%EF%B8%8F%20Gotcha%3A%20Usage%20with%20low%2Dlevel%20calls
        (bool revertsAsExpected, bytes memory returnData) =
            address(0).call(abi.encodeWithSelector(AggregatorV3Interface.latestRoundData.selector));
        assertFalse(revertsAsExpected); // the call itself does not revert

        vm.expectRevert(); // it's the decode step that reverts
        (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) =
            abi.decode(returnData, (uint80, int256, uint256, uint256, uint80));
    }
}

interface AggregatorV3Interface {
    function latestRoundData()
        external
        view
        returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
}
HIGH severity: Misconfigured index boundaries prevent certain swaps in QuantAMMWeightedPool. **Description:** Balancer pools can handle up to 8 tokens in weighted pools. QuantAMM uses this feature but optimizes storage by using only two slots. As a result, the first four tokens and the last four tokens are treated separately.

For swaps, this logic is implemented in...

Vulnerable code:
// if both tokens are within the first storage element
if (request.indexIn < 4 && request.indexOut < 4) {
    QuantAMMNormalisedTokenPair memory tokenWeights = _getNormalisedWeightPair(
        request.indexIn,
        request.indexOut,
        timeSinceLastUpdate,
        totalTokens
    );
    tokenInWeight = tokenWeights.firstTokenWeight;
    tokenOutWeight = tokenWeights.secondTokenWeight;
} else if (request.indexIn > 4 && request.indexOut < 4) {
    // if the tokens are in different storage elements
    QuantAMMNormalisedTokenPair memory tokenWeights = _getNormalisedWeightPair(
        request.indexOut,
        request.indexIn,
        timeSinceLastUpdate,
        totalTokens
    );
    tokenInWeight = tokenWeights.firstTokenWeight;
    tokenOutWeight = tokenWeights.secondTokenWeight;
} else {
    tokenInWeight = _getNormalizedWeight(request.indexIn, timeSinceLastUpdate, totalTokens);
    tokenOutWeight = _getNormalizedWeight(request.indexOut, timeSinceLastUpdate, totalTokens);
}

function _getNormalisedWeightPair(
    uint256 tokenIndexOne, // @audit indexOut
    uint256 tokenIndexTwo, // @audit indexIn
    // ...
) internal view virtual returns (QuantAMMNormalisedTokenPair memory) {
    uint256 firstTokenIndex = tokenIndexOne; // @audit indexOut
    uint256 secondTokenIndex = tokenIndexTwo; // @audit indexIn
    // ...
    if (tokenIndexTwo > 4) { // @audit indexIn will always be > 4 from the branch above
        firstTokenIndex = tokenIndexOne - 4; // @audit indexOut, must be < 4 hence underflow
        secondTokenIndex = tokenIndexTwo - 4;
        totalTokensInPacked -= 4;
        targetWrappedToken = _normalizedSecondFourWeights;
    } else {

if (tokenIndex > 4) { // @audit should be >=
    // get the index in the second storage element
    index = tokenIndex - 4;
    targetWrappedToken = _normalizedSecondFourWeights;
    tokenIndexInPacked -= 4;
} else {
    // @audit first slot
    if (totalTokens > 4) {
         tokenIndexInPacked = 4;
    }
    targetWrappedToken = _normalizedFirstFourWeights;
HIGH severity: Token Index error in `getNormalizedWeights` calculates incorrect weight leading to incorrect pool asset allocation. **Description:** The `_getNormalizedWeights()` function in `QuantAMMWeightedPool.sol` contains a critical indexing error when handling multipliers for pools with more than 4 tokens. The error causes incorrect multiplier values to be used when calculating interpolated weights for tokens 4-7,...

Vulnerable code:
function _getNormalizedWeights() internal view virtual returns (uint256[] memory) {
    // ...
    uint256 tokenIndex = totalTokens;
    if (totalTokens > 4) {
        tokenIndex = 4;  // @audit Sets to 4 for first slot multipliers
    }

    // First slot handles correctly
    normalizedWeights[0] = calculateBlockNormalisedWeight(
        firstFourWeights[0],
        firstFourWeights[tokenIndex],  // Uses indices 4-7 for multipliers
        timeSinceLastUpdate
    );
    // ...

    // Second slot has indexing error
    if (totalTokens > 4) {
        tokenIndex -= 4;  // @audit Resets to 0, breaking multiplier indices
        int256[] memory secondFourWeights = quantAMMUnpack32(_normalizedSecondFourWeights);
        normalizedWeights[4] = calculateBlockNormalisedWeight(
            secondFourWeights[0],
            secondFourWeights[tokenIndex],  // @audit Uses wrong indices 0-3 for multipliers -> essentially weight and multiplier are same
            timeSinceLastUpdate
        );
        // ...
    }
}
HIGH severity: Incorrect handling of negative multipliers in `QuantAMMWeightedPool` leads to underflow in weight calculation. **Description:** In [`QuantAMMWeightedPool::calculateBlockNormalisedWeight`](https://github.com/QuantAMMProtocol/QuantAMM-V1/blob/7213401491f6a8fd1fcc1cf4763b15b5da355f1c/pkg/pool-quantamm/contracts/QuantAMMWeightedPool.sol#L505-L521):

**Impact:** All swaps with negative multiplier which aren't...

Vulnerable code:
if (multiplier > 0) {
    return uint256(weight) + FixedPoint.mulDown(uint256(multiplierScaled18), timeSinceLastUpdate);
} else {
    // @audit silent overflow, uint256(multiplierScaled18) of a negative value will result in a very large value
    return uint256(weight) - FixedPoint.mulUp(uint256(multiplierScaled18), timeSinceLastUpdate);
}

function testGetNormalizeNegativeMultiplierOnSwapOutGivenInInitialToken0Token1() public {
    testParam memory firstWeight = testParam(0, 0.1e18, 0.001e18);
    testParam memory secondWeight = testParam(1, 0.15e18, -0.001e18);
    _onSwapOutGivenInInternal(firstWeight, secondWeight, 2, 1.332223208952048000e18);
}

- return uint256(weight) - FixedPoint.mulUp(uint256(multiplierScaled18), timeSinceLastUpdate);
+ return uint256(weight) - FixedPoint.mulUp(uint256(-multiplierScaled18), timeSinceLastUpdate);
HIGH severity: Mismatch in multiplier position causes incorrect weight calculations in `QuantAMMWeightedPool`. **Description:** The primary feature of QuantAMM weighted pools is to periodically update weights based on various trading rules set during pool creation. These weights are updated by a singleton contract, `UpdateWeightRunner`, which provides new weights and multipliers. The multipliers help to...

Vulnerable code:
/// @dev Update weight runner gives all weights in a single array shaped like [w1,w2,w3,w4,w5,w6,w7,w8,m1,m2,m3,m4,m5,m6,m7,m8], we need it to be [w1,w2,w3,w4,m1,m2,m3,m4,w5,w6,w7,w8,m5,m6,m7,m8]

uint256 tokenLength = weights.length / 2;
splitWeights = new int256[][](2);
splitWeights[0] = new int256[](8);
for (uint i; i < 4; ) {
    splitWeights[0][i] = weights[i];
    splitWeights[0][i + 4] = weights[i + tokenLength];


    unchecked {
        i++;
    }
}

splitWeights[1] = new int256[](8);
uint256 moreThan4Tokens = tokenLength - 4;
for (uint i = 0; i < moreThan4Tokens; ) {
    uint256 i4 = i + 4;
    splitWeights[1][i] = weights[i4];
    splitWeights[1][i4] = weights[i4 + tokenLength];

    unchecked {
        i++;
    }
}
MEDIUM severity: Incorrect range validation in `quantAMMPackEight32` allows invalid values to be packed. **Description:** The `ScalarQuantAMMBaseStorage::quantAMMPackEight32` function contains incorrect validation logic that fails to properly check minimum bounds for six out of eight input parameters. The require statement incorrectly reuses `_firstInt` for minimum bound checks instead of checking...

Vulnerable code:
require(
    _firstInt <= MAX32 &&
        _firstInt >= MIN32 &&
        _secondInt <= MAX32 &&
        _secondInt >= MIN32 &&
        _thirdInt <= MAX32 &&
        _firstInt >= MIN32 &&  // @audit should be _thirdInt
        _fourthInt <= MAX32 &&
        _firstInt >= MIN32 &&  // @audit should be _fourthInt
        _fifthInt <= MAX32 &&
        _firstInt >= MIN32 &&  // @audit should be _fifthInt
        _sixthInt <= MAX32 &&
        _firstInt >= MIN32 &&  // @audit should be _sixthInt
        _seventhInt <= MAX32 &&
        _firstInt >= MIN32 &&  // @audit should be _seventhInt
        _eighthInt <= MAX32 &&
        _firstInt >= MIN32,    // @audit should be _eighthInt
    "Overflow"
);
HIGH severity: Lack of permission check allows unauthorized updates to `lastPoolUpdateRun`. **Description:** To apply the weight changes calculated by the rules, any user can call [`UpdateWeightRunner::performUpdate`](https://github.com/QuantAMMProtocol/QuantAMM-V1/blob/7213401491f6a8fd1fcc1cf4763b15b5da355f1c/pkg/pool-quantamm/contracts/UpdateWeightRunner.sol#L256-L279).

Each pool has...

Vulnerable code:
// Current breakglass settings allow DAO or pool creator to trigger updates. This is subject to review.
if (poolRegistryEntry & MASK_POOL_DAO_WEIGHT_UPDATES > 0) {
    address daoRunner = QuantAMMBaseAdministration(quantammAdmin).daoRunner();
    require(msg.sender == daoRunner, "ONLYDAO");
} else if (poolRegistryEntry & MASK_POOL_OWNER_UPDATES > 0) {
    require(msg.sender == poolRuleSettings[_poolAddress].poolManager, "ONLYMANAGER");
}
poolRuleSettings[_poolAddress].timingSettings.lastPoolUpdateRun = _time;

function testAnyoneCanUpdatePoolLastRunTime() public {
    // pool lacks MASK_POOL_DAO_WEIGHT_UPDATES and MASK_POOL_OWNER_UPDATES but has MASK_POOL_PERFORM_UPDATE
    mockPool.setPoolRegistry(1);

    vm.startPrank(owner);
    // Deploy oracles with fixed values and delay
    chainlinkOracle1 = deployOracle(1001, 0);
    chainlinkOracle2 = deployOracle(1002, 0);

    updateWeightRunner.addOracle(chainlinkOracle1);
    updateWeightRunner.addOracle(chainlinkOracle2);
    vm.stopPrank();

    address[][] memory oracles = new address[][](2);
    oracles[0] = new address[](1);
    oracles[0][0] = address(chainlinkOracle1);
    oracles[1] = new address[](1);
    oracles[1][0] = address(chainlinkOracle2);

    uint64[] memory lambda = new uint64[](1);
    lambda[0] = 0.0000000005e18;
    vm.prank(address(mockPool));
    updateWeightRunner.setRuleForPool(
        IQuantAMMWeightedPool.PoolSettings({
            assets: new IERC20[](0),
            rule: IUpdateRule(mockRule),
            oracles: oracles,
            updateInterval: 10,
            lambda: lambda,
            epsilonMax: 0.2e18,
            absoluteWeightGuardRail: 0.2e18,
            maxTradeSizeRatio: 0.2e18,
            ruleParameters: new int256[][](0),
            poolManager: addr2
        })
    );

    address anyone = makeAddr("anyone");

    vm.prank(anyone);
    updateWeightRunner.InitialisePoolLastRunTime(address(mockPool), uint40(block.timestamp));

    vm.expectRevert("Update not allowed");
    updateWeightRunner.performUpdate(address(mockPool));
}

}
+ else {
+     revert("No permission to set lastPoolUpdateRun");
+ }
poolRuleSettings[_poolAddress].timingSettings.lastPoolUpdateRun = _time;
HIGH severity: Faulty permission check in `UpdateWeightRunner::getData` allows unauthorized access. **Description:** Certain actions on a pool are protected by permissions. One such permission is `POOL_GET_DATA`, which governs access to the [`UpdateWeightRunner::getData`](https://github.com/QuantAMMProtocol/QuantAMM-V1/blob/7213401491f6a8fd1fcc1cf4763b15b5da355f1c/pkg/pool-quantamm/contracts/Updat...

Vulnerable code:
bool internalCall = msg.sender != address(this);
require(internalCall || approvedPoolActions[_pool] & MASK_POOL_GET_DATA > 0, "Not allowed to get data");

function testUpdateWeightRunnerGetDataPermissionCanByBypassed() public {
    vm.prank(owner);
    updateWeightRunner.setApprovedActionsForPool(address(mockPool), 1);

    assertEq(updateWeightRunner.getPoolApprovedActions(address(mockPool)) & 2 /* MASK_POOL_GET_DATA */, 0);

    // this should revert as the pool is not allowed to get data
    updateWeightRunner.getData(address(mockPool));
}

- function getData(address _pool) public returns (int256[] memory outputData) {
+ function getData(address _pool) public view returns (int256[] memory outputData) {
-     bool internalCall = msg.sender != address(this);
-     require(internalCall || approvedPoolActions[_pool] & MASK_POOL_GET_DATA > 0, "Not allowed to get data");
+     require(approvedPoolActions[_pool] & MASK_POOL_GET_DATA > 0, "Not allowed to get data");
// ...
-     if(!internalCall){
-         emit GetData(msg.sender, _pool);
-     }