Attacker can abuse `RewardsDistributor::triggerRoot` to block reward claims and unpause a paused state
Consider the code of RewardsDistributor::triggerRoot:\\n```\\n    function triggerRoot() external {\\n        bytes32 rootCandidateAValue = rootCandidateA.value;\\n        if (rootCandidateAValue != rootCandidateB.value || rootCandidateAValue == bytes32(0)) revert RootCandidatesInvalid();\\n        root = Root({value: rootCandidateAValue, lastUpdatedAt: block.timestamp});\\n        emit RootChanged(msg.sender, rootCandidateAValue);\\n    }\\n```\\n\\nThis function:\\ncan be called by anyone\\nif it succeeds, sets `root.value` to `rootCandidateA.value` and `root.lastUpdatedAt` to `block.timestamp`\\ndoesn't reset `rootCandidateA` or `rootCandidateB`, so it can be called over and over again to continually update `root.lastUpdatedAt` or to set `root.value` to `rootCandidateA.value`.
Two possible options:\\nMake `RewardsDistributor::triggerRoot` a permissioned function such that an attacker can't call it\\nChange `RewardsDistributor::triggerRoot` to reset `rootCandidateA.value = zeroRoot` such that it can't be successfully called repeatedly.
An attacker can abuse this function in 2 ways:\\nby calling it repeatedly an attacker can continually increase `root.lastUpdatedAt` to trigger the claim delay revert in `RewardsDistributor::claimAll` effectively blocking reward claims\\nby calling it after reward claims have been paused, an attacker can effectively unpause the paused state since `root.value` is over-written with the valid value from `rootCandidateA.value` and claim pausing works by setting `root.value == zeroRoot`.
```\\n    function triggerRoot() external {\\n        bytes32 rootCandidateAValue = rootCandidateA.value;\\n        if (rootCandidateAValue != rootCandidateB.value || rootCandidateAValue == bytes32(0)) revert RootCandidatesInvalid();\\n        root = Root({value: rootCandidateAValue, lastUpdatedAt: block.timestamp});\\n        emit RootChanged(msg.sender, rootCandidateAValue);\\n    }\\n```\\n