The arbitrary 10 multiplication leads to uninitialized memory slots, causing invalid data access. performUpkeep attempts to process these uninitialized indexes, leading to a revert.
The error arises when trying to access totalAssets()
on an uninitialized zero address, leading to a revert.
/src/external/chainlink/keepers/fee-conversion-keeper/FeeConversionKeeper.sol:69
69: function checkUpkeep(bytes calldata ) external view returns (bool upkeepNeeded, bytes memory performData) {
70: FeeConversionKeeperStorage memory self = _getFeeConversionKeeperStorage();
71:
72: uint128[] memory liveMarketIds = self.marketMakingEngine.getLiveMarketIds();
73:
74: bool distributionNeeded;
75: uint128[] memory marketIds = new uint128[](liveMarketIds.length * 10);
76: address[] memory assets = new address[](liveMarketIds.length * 10);
/test/integration/external/chainlink/keepers/fee-conversion/checkUpkeep/checkUpkeep.t.sol:32
32: function test_WhenMarketsHaveMoreThanMinFeeForDistribution(
33: )
34: external
35: givenCheckUpkeepIsCalled
36: {
37: uint256 marketId=3967010399546;
38: uint256 amount=115792089237316195423570985008687907853269984665640564039457584007913129639932;
39: uint256 minFeeDistributionValueUsd=9306648518645823426120026427;
40:
41: PerpMarketCreditConfig memory fuzzPerpMarketCreditConfig = getFuzzPerpMarketCreditConfig(marketId);
42:
43: minFeeDistributionValueUsd = bound({
44: x: minFeeDistributionValueUsd,
45: min: 1,
46: max: convertUd60x18ToTokenAmount(address(usdc), USDC_DEPOSIT_CAP_X18)
47: });
48:
49: amount = bound({
50: x: amount,
51: min: minFeeDistributionValueUsd,
52: max: convertUd60x18ToTokenAmount(address(usdc), USDC_DEPOSIT_CAP_X18)
53: });
54: deal({ token: address(usdc), to: address(fuzzPerpMarketCreditConfig.engine), give: amount });
55:
56: changePrank({ msgSender: users.owner.account });
57:
58: configureFeeConversionKeeper(1, 1);
59:
60: changePrank({ msgSender: address(fuzzPerpMarketCreditConfig.engine) });
61:
62: marketMakingEngine.receiveMarketFee(fuzzPerpMarketCreditConfig.marketId, address(usdc), amount);
63:
64: (bool upkeepNeeded, bytes memory performData) = FeeConversionKeeper(feeConversionKeeper).checkUpkeep("");
65:
66: (uint128[] memory marketIds, address[] memory assets) = abi.decode(performData, (uint128[], address[]));
67: console.log("marketIds" , marketIds.length);
68:
69: assertTrue(upkeepNeeded);
70:
71: assertEq(assets[0], address(usdc));
72: assertEq(marketIds[0], fuzzPerpMarketCreditConfig.marketId);
73:
74: FeeConversionKeeper(feeConversionKeeper).performUpkeep(performData);
75: }
performUpkeep will always revert, preventing fee distribution.
Dynamically allocate arrays based on actual asset count instead of using an arbitrary multiplier.