MEDIUM severity: The vulnerability lies in the SDLPoolCCIPControllerSecondary::performUpkeep function, which is respo. The vulnerability lies in the SDLPoolCCIPControllerSecondary::performUpkeep function, which is responsible for updating the primary chain with information from the secondary chain. The function is only called when there is a message of rewards from the SDLPoolCCIPControllerPrimary, which is a critic...

Vulnerable code:
```\nFile: SDLPoolCCIPControllerPrimary.sol\n\nfunction _ccipReceive(Client.Any2EVMMessage memory _message) internal override {\n    uint64 sourceChainSelector = _message.sourceChainSelector;\n\n    (uint256 numNewRESDLTokens, int256 totalRESDLSupplyChange) = abi.decode(_message.data, (uint256, int256));\n\n    if (totalRESDLSupplyChange > 0) {\n        reSDLSupplyByChain[sourceChainSelector] += uint256(totalRESDLSupplyChange);\n    } else if (totalRESDLSupplyChange < 0) {\n        reSDLSupplyByChain[sourceChainSelector] -= uint256(-1 * totalRESDLSupplyChange);\n    }\n\n    uint256 mintStartIndex = ISDLPoolPrimary(sdlPool).handleIncomingUpdate(numNewRESDLTokens, totalRESDLSupplyChange);\n\n    _ccipSendUpdate(sourceChainSelector, mintStartIndex);\n\n    emit MessageReceived(_message.messageId, sourceChainSelector);\n}\n```\n```\nFile: SDLPoolCCIPControllerSecondary.sol\n\nfunction _ccipReceive(Client.Any2EVMMessage memory _message) internal override {\n    if (_message.data.length == 0) {\n        uint256 numRewardTokens = _message.destTokenAmounts.length;\n        address[] memory rewardTokens = new address[](numRewardTokens);\n\n        if (numRewardTokens!= 0) {\n            for (uint256 i = 0; i < numRewardTokens; i++) {\n                rewardTokens[i] = _message.destTokenAmounts[i].token;\n                IERC20(rewardTokens[i]).safeTransfer(sdlPool, _message.destTokenAmounts[i].amount);\n            }\n            ISDLPoolSecondary(sdlPool).distributeTokens(rewardTokens);\n            if (ISDLPoolSecondary(sdlPool).shouldUpdate()) {\n                shouldUpdate = true;\n            }\n        }\n    } else {\n        uint256 mintStartIndex = abi.decode(_message.data, (uint256));\n        ISDLPoolSecondary(sdlPool).handleIncomingUpdate(mintStartIndex);\n    }\n\n    emit MessageReceived(_message.messageId, _message.sourceChainSelector);\n}\n```\n```\nfunction performUpkeep(bytes calldata) external {\n    if (!shouldUpdate) {\n        revert UpdateConditionsNotMet();\n    }\n\n    shouldUpdate = false;\n    _initiateUpdate(primaryChainSelector, primaryChainDestination, extraArgs);\n}\n```\n```\nit('codehawks performUpkeep reverts', async () => {\n  await token1.transfer(tokenPool.address, toEther(1000));\n  let rewardsPool1 = await deploy('RewardsPool', [sdlPool.address, token1.address]);\n  await sdlPool.addToken(token1.address, rewardsPool1.address);\n  assert.equal(fromEther(await sdlPool.totalEffectiveBalance()), 400);\n  assert.equal((await controller.checkUpkeep('0x'))[0], false);\n  assert.equal(await controller.shouldUpdate(), false);\n\n  // 1. Mint in the secondary pool\n  await sdlToken.transferAndCall(\n    sdlPool.address,\n    toEther(100),\n    ethers.utils.defaultAbiCoder.encode(['uint256', 'uint64'], [0, 0])\n  );\n\n  // 2. The secondary pool needs to update data to the primary chain but the `controller.shouldUpdate` is false so `performUpkeep` reverts the transaction\n  assert.equal(await sdlPool.shouldUpdate(), true);\n  assert.equal((await controller.checkUpkeep('0x'))[0], false);\n  assert.equal(await controller.shouldUpdate(), false);\n  await expect(controller.performUpkeep('0x')).to.be.revertedWith('UpdateConditionsNotMet()');\n})\n```